CVE-2026-31397 (GCVE-0-2026-31397)

Vulnerability from cvelistv5 – Published: 2026-04-03 15:16 – Updated: 2026-08-05 12:22
VLAI
Title
mm/huge_memory: fix use of NULL folio in move_pages_huge_pmd()
Summary
In the Linux kernel, the following vulnerability has been resolved: mm/huge_memory: fix use of NULL folio in move_pages_huge_pmd() move_pages_huge_pmd() handles UFFDIO_MOVE for both normal THPs and huge zero pages. For the huge zero page path, src_folio is explicitly set to NULL, and is used as a sentinel to skip folio operations like lock and rmap. In the huge zero page branch, src_folio is NULL, so folio_mk_pmd(NULL, pgprot) passes NULL through folio_pfn() and page_to_pfn(). With SPARSEMEM_VMEMMAP this silently produces a bogus PFN, installing a PMD pointing to non-existent physical memory. On other memory models it is a NULL dereference. Use page_folio(src_page) to obtain the valid huge zero folio from the page, which was obtained from pmd_page() and remains valid throughout. After commit d82d09e48219 ("mm/huge_memory: mark PMD mappings of the huge zero folio special"), moved huge zero PMDs must remain special so vm_normal_page_pmd() continues to treat them as special mappings. move_pages_huge_pmd() currently reconstructs the destination PMD in the huge zero page branch, which drops PMD state such as pmd_special() on architectures with CONFIG_ARCH_HAS_PTE_SPECIAL. As a result, vm_normal_page_pmd() can treat the moved huge zero PMD as a normal page and corrupt its refcount. Instead of reconstructing the PMD from the folio, derive the destination entry from src_pmdval after pmdp_huge_clear_flush(), then handle the PMD metadata the same way move_huge_pmd() does for moved entries by marking it soft-dirty and clearing uffd-wp.
Impacted products
Vendor Product Version CPE status
Linux Linux Affected: e3981db444a0a18d350d9f92e3f2e8d489b54211 , < f3caaee0f9e489fd2282d4ce45791dc8aed2da62 (git)
Affected: e3981db444a0a18d350d9f92e3f2e8d489b54211 , < e3133d0986dc5a231d5419167dbac65312b28b41 (git)
Affected: e3981db444a0a18d350d9f92e3f2e8d489b54211 , < fae654083bfa409bb2244f390232e2be47f05bfc (git)
guessed Create a notification for this product.
Linux Linux Affected: 6.16
Unaffected: 0 , < 6.16 (semver)
Unaffected: 6.18.20 , ≤ 6.18.* (semver)
Unaffected: 6.19.10 , ≤ 6.19.* (semver)
Unaffected: 7.0 , ≤ * (original_commit_for_fix)
guessed Create a notification for this product.
Show details on NVD website

{
  "containers": {
    "cna": {
      "affected": [
        {
          "defaultStatus": "unaffected",
          "product": "Linux",
          "programFiles": [
            "mm/huge_memory.c"
          ],
          "repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
          "vendor": "Linux",
          "versions": [
            {
              "lessThan": "f3caaee0f9e489fd2282d4ce45791dc8aed2da62",
              "status": "affected",
              "version": "e3981db444a0a18d350d9f92e3f2e8d489b54211",
              "versionType": "git"
            },
            {
              "lessThan": "e3133d0986dc5a231d5419167dbac65312b28b41",
              "status": "affected",
              "version": "e3981db444a0a18d350d9f92e3f2e8d489b54211",
              "versionType": "git"
            },
            {
              "lessThan": "fae654083bfa409bb2244f390232e2be47f05bfc",
              "status": "affected",
              "version": "e3981db444a0a18d350d9f92e3f2e8d489b54211",
              "versionType": "git"
            }
          ]
        },
        {
          "defaultStatus": "affected",
          "product": "Linux",
          "programFiles": [
            "mm/huge_memory.c"
          ],
          "repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
          "vendor": "Linux",
          "versions": [
            {
              "status": "affected",
              "version": "6.16"
            },
            {
              "lessThan": "6.16",
              "status": "unaffected",
              "version": "0",
              "versionType": "semver"
            },
            {
              "lessThanOrEqual": "6.18.*",
              "status": "unaffected",
              "version": "6.18.20",
              "versionType": "semver"
            },
            {
              "lessThanOrEqual": "6.19.*",
              "status": "unaffected",
              "version": "6.19.10",
              "versionType": "semver"
            },
            {
              "lessThanOrEqual": "*",
              "status": "unaffected",
              "version": "7.0",
              "versionType": "original_commit_for_fix"
            }
          ]
        }
      ],
      "cpeApplicability": [
        {
          "nodes": [
            {
              "cpeMatch": [
                {
                  "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
                  "versionEndExcluding": "6.18.20",
                  "versionStartIncluding": "6.16",
                  "vulnerable": true
                },
                {
                  "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
                  "versionEndExcluding": "6.19.10",
                  "versionStartIncluding": "6.16",
                  "vulnerable": true
                },
                {
                  "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
                  "versionEndExcluding": "7.0",
                  "versionStartIncluding": "6.16",
                  "vulnerable": true
                }
              ],
              "negate": false,
              "operator": "OR"
            }
          ]
        }
      ],
      "descriptions": [
        {
          "lang": "en",
          "value": "In the Linux kernel, the following vulnerability has been resolved:\n\nmm/huge_memory: fix use of NULL folio in move_pages_huge_pmd()\n\nmove_pages_huge_pmd() handles UFFDIO_MOVE for both normal THPs and huge\nzero pages.  For the huge zero page path, src_folio is explicitly set to\nNULL, and is used as a sentinel to skip folio operations like lock and\nrmap.\n\nIn the huge zero page branch, src_folio is NULL, so folio_mk_pmd(NULL,\npgprot) passes NULL through folio_pfn() and page_to_pfn().  With\nSPARSEMEM_VMEMMAP this silently produces a bogus PFN, installing a PMD\npointing to non-existent physical memory.  On other memory models it is a\nNULL dereference.\n\nUse page_folio(src_page) to obtain the valid huge zero folio from the\npage, which was obtained from pmd_page() and remains valid throughout.\n\nAfter commit d82d09e48219 (\"mm/huge_memory: mark PMD mappings of the huge\nzero folio special\"), moved huge zero PMDs must remain special so\nvm_normal_page_pmd() continues to treat them as special mappings.\n\nmove_pages_huge_pmd() currently reconstructs the destination PMD in the\nhuge zero page branch, which drops PMD state such as pmd_special() on\narchitectures with CONFIG_ARCH_HAS_PTE_SPECIAL.  As a result,\nvm_normal_page_pmd() can treat the moved huge zero PMD as a normal page\nand corrupt its refcount.\n\nInstead of reconstructing the PMD from the folio, derive the destination\nentry from src_pmdval after pmdp_huge_clear_flush(), then handle the PMD\nmetadata the same way move_huge_pmd() does for moved entries by marking it\nsoft-dirty and clearing uffd-wp."
        }
      ],
      "metrics": [
        {
          "cvssV3_1": {
            "baseScore": 7.8,
            "baseSeverity": "HIGH",
            "vectorString": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
            "version": "3.1"
          },
          "scenarios": [
            {
              "lang": "en",
              "value": "AV:L - The vulnerable path is reached through local `userfaultfd` ioctls, specifically `UFFDIO_MOVE`, on the attacker\u0027s own address space.\nAC:L - An attacker can create aligned anonymous VMAs, materialize a huge zero PMD with reads, register the destination with userfaultfd, and issue `UFFDIO_MOVE`; no uncontrollable race is required.\nPR:L - A basic unprivileged local user can create a userspace-only userfaultfd with `UFFD_USER_MODE_ONLY` and exercise `UFFDIO_MOVE` on their own memory.\nUI:N - Exploitation is driven entirely by the attacker\u0027s own syscalls and memory accesses and does not require a victim user action.\nS:U - The impact is within the local kernel and the attacking process\u0027s memory-management context, with no separate security authority crossed.\nC:H - The bug can install a malformed huge PMD and the fix notes refcount corruption when huge zero PMDs lose special state; treating this as kernel memory corruption makes high confidentiality impact defensible.\nI:H - The malformed PMD/refcount corruption affects kernel-managed memory structures and can plausibly be developed beyond a crash into memory modification or control-flow compromise.\nA:H - On some memory models this is a direct NULL dereference, and on common sparse-vmemmap systems it installs a bogus PMD that can crash the kernel during access or later VM teardown."
            }
          ]
        }
      ],
      "providerMetadata": {
        "dateUpdated": "2026-08-05T12:22:06.974Z",
        "orgId": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
        "shortName": "Linux"
      },
      "references": [
        {
          "url": "https://git.kernel.org/stable/c/f3caaee0f9e489fd2282d4ce45791dc8aed2da62"
        },
        {
          "url": "https://git.kernel.org/stable/c/e3133d0986dc5a231d5419167dbac65312b28b41"
        },
        {
          "url": "https://git.kernel.org/stable/c/fae654083bfa409bb2244f390232e2be47f05bfc"
        }
      ],
      "title": "mm/huge_memory: fix use of NULL folio in move_pages_huge_pmd()",
      "x_generator": {
        "engine": "bippy-1.2.0"
      }
    }
  },
  "cveMetadata": {
    "assignerOrgId": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
    "assignerShortName": "Linux",
    "cveId": "CVE-2026-31397",
    "datePublished": "2026-04-03T15:16:01.427Z",
    "dateReserved": "2026-03-09T15:48:24.085Z",
    "dateUpdated": "2026-08-05T12:22:06.974Z",
    "state": "PUBLISHED"
  },
  "dataType": "CVE_RECORD",
  "dataVersion": "5.2",
  "vulnerability-lookup:meta": {
    "epss": {
      "cve": "CVE-2026-31397",
      "date": "2026-09-23",
      "epss": "0.00119",
      "percentile": "0.01985"
    },
    "nvd": {
      "cve": {
        "affected": [
          {
            "affectedData": [
              {
                "defaultStatus": "unaffected",
                "product": "Linux",
                "programFiles": [
                  "mm/huge_memory.c"
                ],
                "repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
                "vendor": "Linux",
                "versions": [
                  {
                    "lessThan": "f3caaee0f9e489fd2282d4ce45791dc8aed2da62",
                    "status": "affected",
                    "version": "e3981db444a0a18d350d9f92e3f2e8d489b54211",
                    "versionType": "git"
                  },
                  {
                    "lessThan": "e3133d0986dc5a231d5419167dbac65312b28b41",
                    "status": "affected",
                    "version": "e3981db444a0a18d350d9f92e3f2e8d489b54211",
                    "versionType": "git"
                  },
                  {
                    "lessThan": "fae654083bfa409bb2244f390232e2be47f05bfc",
                    "status": "affected",
                    "version": "e3981db444a0a18d350d9f92e3f2e8d489b54211",
                    "versionType": "git"
                  }
                ]
              },
              {
                "defaultStatus": "affected",
                "product": "Linux",
                "programFiles": [
                  "mm/huge_memory.c"
                ],
                "repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
                "vendor": "Linux",
                "versions": [
                  {
                    "status": "affected",
                    "version": "6.16"
                  },
                  {
                    "lessThan": "6.16",
                    "status": "unaffected",
                    "version": "0",
                    "versionType": "semver"
                  },
                  {
                    "lessThanOrEqual": "6.18.*",
                    "status": "unaffected",
                    "version": "6.18.20",
                    "versionType": "semver"
                  },
                  {
                    "lessThanOrEqual": "6.19.*",
                    "status": "unaffected",
                    "version": "6.19.10",
                    "versionType": "semver"
                  },
                  {
                    "lessThanOrEqual": "*",
                    "status": "unaffected",
                    "version": "7.0",
                    "versionType": "original_commit_for_fix"
                  }
                ]
              }
            ],
            "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"
          }
        ],
        "configurations": [
          {
            "nodes": [
              {
                "cpeMatch": [
                  {
                    "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
                    "matchCriteriaId": "1C570CE1-BC61-4BE6-9393-FD0CA8637367",
                    "versionEndExcluding": "6.18.20",
                    "versionStartIncluding": "6.16",
                    "vulnerable": true
                  },
                  {
                    "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
                    "matchCriteriaId": "96D34333-38BE-4414-9E79-6EB764329581",
                    "versionEndExcluding": "6.19.10",
                    "versionStartIncluding": "6.19",
                    "vulnerable": true
                  },
                  {
                    "criteria": "cpe:2.3:o:linux:linux_kernel:7.0:rc1:*:*:*:*:*:*",
                    "matchCriteriaId": "F253B622-8837-4245-BCE5-A7BF8FC76A16",
                    "vulnerable": true
                  },
                  {
                    "criteria": "cpe:2.3:o:linux:linux_kernel:7.0:rc2:*:*:*:*:*:*",
                    "matchCriteriaId": "4AE85AD8-4641-4E7C-A2F4-305E2CD9EE64",
                    "vulnerable": true
                  },
                  {
                    "criteria": "cpe:2.3:o:linux:linux_kernel:7.0:rc3:*:*:*:*:*:*",
                    "matchCriteriaId": "F666C8D8-6538-46D4-B318-87610DE64C34",
                    "vulnerable": true
                  },
                  {
                    "criteria": "cpe:2.3:o:linux:linux_kernel:7.0:rc4:*:*:*:*:*:*",
                    "matchCriteriaId": "02259FDA-961B-47BC-AE7F-93D7EC6E90C2",
                    "vulnerable": true
                  }
                ],
                "negate": false,
                "operator": "OR"
              }
            ]
          }
        ],
        "cveTags": [],
        "descriptions": [
          {
            "lang": "en",
            "value": "In the Linux kernel, the following vulnerability has been resolved:\n\nmm/huge_memory: fix use of NULL folio in move_pages_huge_pmd()\n\nmove_pages_huge_pmd() handles UFFDIO_MOVE for both normal THPs and huge\nzero pages.  For the huge zero page path, src_folio is explicitly set to\nNULL, and is used as a sentinel to skip folio operations like lock and\nrmap.\n\nIn the huge zero page branch, src_folio is NULL, so folio_mk_pmd(NULL,\npgprot) passes NULL through folio_pfn() and page_to_pfn().  With\nSPARSEMEM_VMEMMAP this silently produces a bogus PFN, installing a PMD\npointing to non-existent physical memory.  On other memory models it is a\nNULL dereference.\n\nUse page_folio(src_page) to obtain the valid huge zero folio from the\npage, which was obtained from pmd_page() and remains valid throughout.\n\nAfter commit d82d09e48219 (\"mm/huge_memory: mark PMD mappings of the huge\nzero folio special\"), moved huge zero PMDs must remain special so\nvm_normal_page_pmd() continues to treat them as special mappings.\n\nmove_pages_huge_pmd() currently reconstructs the destination PMD in the\nhuge zero page branch, which drops PMD state such as pmd_special() on\narchitectures with CONFIG_ARCH_HAS_PTE_SPECIAL.  As a result,\nvm_normal_page_pmd() can treat the moved huge zero PMD as a normal page\nand corrupt its refcount.\n\nInstead of reconstructing the PMD from the folio, derive the destination\nentry from src_pmdval after pmdp_huge_clear_flush(), then handle the PMD\nmetadata the same way move_huge_pmd() does for moved entries by marking it\nsoft-dirty and clearing uffd-wp."
          },
          {
            "lang": "es",
            "value": "En el kernel de Linux, la siguiente vulnerabilidad ha sido resuelta:\n\nmm/huge_memory: corrige el uso de folio NULL en move_pages_huge_pmd()\n\nmove_pages_huge_pmd() maneja UFFDIO_MOVE tanto para THPs normales como para p\u00e1ginas cero enormes. Para la ruta de la p\u00e1gina cero enorme, src_folio se establece expl\u00edcitamente en NULL, y se usa como un centinela para omitir operaciones de folio como lock y rmap.\n\nEn la rama de la p\u00e1gina cero enorme, src_folio es NULL, por lo que folio_mk_pmd(NULL, pgprot) pasa NULL a trav\u00e9s de folio_pfn() y page_to_pfn(). Con SPARSEMEM_VMEMMAP esto produce silenciosamente un PFN err\u00f3neo, instalando un PMD que apunta a memoria f\u00edsica inexistente. En otros modelos de memoria es una desreferencia NULL.\n\nUsar page_folio(src_page) para obtener el folio cero enorme v\u00e1lido de la p\u00e1gina, que se obtuvo de pmd_page() y permanece v\u00e1lido en todo momento.\n\nDespu\u00e9s del commit d82d09e48219 (\u0027mm/huge_memory: marcar las asignaciones PMD del folio cero enorme como especiales\u0027), los PMD cero enormes movidos deben permanecer especiales para que vm_normal_page_pmd() contin\u00fae trat\u00e1ndolos como asignaciones especiales.\n\nmove_pages_huge_pmd() actualmente reconstruye el PMD de destino en la rama de la p\u00e1gina cero enorme, lo que elimina el estado del PMD como pmd_special() en arquitecturas con CONFIG_ARCH_HAS_PTE_SPECIAL. Como resultado, vm_normal_page_pmd() puede tratar el PMD cero enorme movido como una p\u00e1gina normal y corromper su refcount.\n\nEn lugar de reconstruir el PMD a partir del folio, derivar la entrada de destino de src_pmdval despu\u00e9s de pmdp_huge_clear_flush(), luego manejar los metadatos del PMD de la misma manera que move_huge_pmd() lo hace para las entradas movidas, marc\u00e1ndolo como soft-dirty y borrando uffd-wp."
          }
        ],
        "id": "CVE-2026-31397",
        "lastModified": "2026-07-24T22:10:00.140",
        "metrics": {
          "cvssMetricV31": [
            {
              "cvssData": {
                "attackComplexity": "LOW",
                "attackVector": "LOCAL",
                "availabilityImpact": "HIGH",
                "baseScore": 7.8,
                "baseSeverity": "HIGH",
                "confidentialityImpact": "HIGH",
                "integrityImpact": "HIGH",
                "privilegesRequired": "LOW",
                "scope": "UNCHANGED",
                "userInteraction": "NONE",
                "vectorString": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
                "version": "3.1"
              },
              "exploitabilityScore": 1.8,
              "impactScore": 5.9,
              "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
              "type": "Secondary"
            }
          ]
        },
        "published": "2026-04-03T16:16:38.093",
        "references": [
          {
            "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
            "tags": [
              "Patch"
            ],
            "url": "https://git.kernel.org/stable/c/e3133d0986dc5a231d5419167dbac65312b28b41"
          },
          {
            "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
            "tags": [
              "Patch"
            ],
            "url": "https://git.kernel.org/stable/c/f3caaee0f9e489fd2282d4ce45791dc8aed2da62"
          },
          {
            "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
            "tags": [
              "Patch"
            ],
            "url": "https://git.kernel.org/stable/c/fae654083bfa409bb2244f390232e2be47f05bfc"
          }
        ],
        "sourceIdentifier": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
        "vulnStatus": "Analyzed",
        "weaknesses": [
          {
            "description": [
              {
                "lang": "en",
                "value": "CWE-476"
              }
            ],
            "source": "nvd@nist.gov",
            "type": "Primary"
          }
        ]
      }
    },
    "redhat_vex": {
      "aggregate_severity": "None",
      "current_release_date": "2026-06-28T07:24:55+00:00",
      "cve": "CVE-2026-31397",
      "id": "CVE-2026-31397",
      "initial_release_date": "2026-04-03T00:00:00+00:00",
      "product_status:known_not_affected": "274",
      "source": "Red Hat CSAF VEX",
      "status": "final",
      "title": "kernel: mm/huge_memory: fix use of NULL folio in move_pages_huge_pmd()",
      "url": "https://security.access.redhat.com/data/csaf/v2/vex/2026/cve-2026-31397.json",
      "version": "3"
    }
  }
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.

Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…

Related by attack behaviour

Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.


Loading…