Description
In the Linux kernel, the following vulnerability has been resolved:

x86/mm: Fix user-space data loss with MADV_FREE and THP

Some of users of Polars (a data analytics library) have lost production
data from this bug. They seem to have just the right combination of
huge pages, MADV_FREE and heavy reclaim pressure.

pmd_modify() masks the old value with (_HPAGE_CHG_MASK & ~_PAGE_DIRTY),
silently discarding the hardware dirty bit. The subsequent
pmd_mksaveddirty() call is supposed to transfer _PAGE_DIRTY into
_PAGE_SAVED_DIRTY when write-protecting, but the dirty bit was already
stripped from the value, so there is nothing left to transfer.

Contrast with pte_modify(), which keeps _PAGE_DIRTY_BITS in its mask,
and pud_modify(), which keeps _HPAGE_CHG_MASK untouched: pmd_modify()
is the odd one out. Any pmd_modify() on a writable, dirty PMD loses
the dirty state.

One visible consequence is data loss with MADV_FREE on PMD-mapped THP:

memset(buf, 0x5A, size); // PMD-mapped THP, PMD dirty
madvise(buf, size, MADV_FREE); // PMD cleaned but left writable,
// folio marked lazyfree
memset(buf, 0x5A, size); // hardware sets _PAGE_DIRTY again
mprotect(buf, size, PROT_READ); // pmd_modify() drops the dirty bit
mprotect(buf, size, PROT_READ|PROT_WRITE);
// ... memory pressure ...

Reclaim (e.g. under memcg pressure) then finds the lazyfree folio with
no dirty bit set anywhere and frees it in
__discard_anon_folio_pmd_locked(), even though the data was rewritten
after MADV_FREE; subsequent reads fault in fresh zero pages. NUMA
hinting alone can trigger the same loss, as do_huge_pmd_numa_page()
restores the PMD through pmd_modify() as well.

PMD-mapped file THPs are affected too: mprotect()/NUMA hinting dropping
the dirty bit means rewritten data is never written back.

Fix it by keeping _PAGE_DIRTY in the preserved mask, exactly like
pte_modify() and pud_modify() do. The existing
pmd_mksaveddirty()/pmd_clear_saveddirty() pair then performs the
hardware-dirty <-> saved-dirty transition based on the write bit,
preserving the shadow-stack encoding rules.
Published: 2026-09-25
Score: n/a
EPSS: n/a
KEV: No
Impact: Data loss and integrity violation
Action: Assess Impact
AI Analysis

Impact

A flaw in the Linux kernel’s handling of page state during MADV_FREE and THP operations causes user-space data to be discarded when the kernel clears the dirty bit on a page- middle directory (PMD). This bug leads to loss of data that has been written after a MADV_FREE call, a memory pressure reclaim, or a NUMA hint, resulting in integrity violations for applications that rely on those pages. The technical root is that the implementation of pmd_modify() masks away the hardware‑dirty flag, preventing the subsequent pmd_mksaveddirty() routine from saving the dirty bit. Because the dirty flag is never restored, the kernel may reclaim the page as clean and free it, discarding any user modifications. Although the bug is data‑integrity focused rather than disclosure or unauthorized access, local users on a system running an affected kernel can inadvertently corrupt or lose important data by triggering the conditions that activate the flaw.

Affected Systems

The vulnerability affects all Linux kernel versions before the posted patch, regardless of distribution. No specific version range is listed, so any system running a pre‑patch kernel may be at risk. The affected component is the kernel’s virtual memory manager for the x86 architecture, specifically the handling of PMD entries during page protection and freeing operations. Administrators should verify whether their kernel includes the commit that fixes the issue and consider the risk for applications using THP and MADV_FREE.

Risk and Exploitability

The CVSS score is not provided, and the EPSS score is unavailable, but the vulnerability is not listed in the CISA KEV catalog. The flaw requires local access to code that forces memory pressure or uses the described system calls; therefore it is unlikely to be exposed as a remote exploit. The condition is highly specific, suggesting a moderate risk to systems that routinely use THP and aggressively reclaim memory. The missing dirty flag may lead to silent data loss, making detection difficult. The best mitigation is to ensure the kernel has the fixed patch applied before any exploitation can occur.

Generated by OpenCVE AI on September 25, 2026 at 14:56 UTC.

Remediation

No vendor fix or workaround currently provided.

OpenCVE Recommended Actions

  • Apply the latest Linux kernel that includes the commit fixing the dirty–bit handling issue.
  • If an immediate kernel upgrade is infeasible, disable transparent huge pages by setting /sys/kernel/mm/transparent_hugepage/enabled to "never", which removes the vulnerability path for THP use cases.
  • Avoid using MADV_FREE or mprotect together with THP on systems that may experience high memory pressure until the kernel patch is applied.

Generated by OpenCVE AI on September 25, 2026 at 14:56 UTC.

Tracking

Sign in to view the affected projects.

Advisories

No advisories yet.

History

Fri, 25 Sep 2026 15:15:00 +0000

Type Values Removed Values Added
Weaknesses CWE-665

Fri, 25 Sep 2026 10:30:00 +0000

Type Values Removed Values Added
Description In the Linux kernel, the following vulnerability has been resolved: x86/mm: Fix user-space data loss with MADV_FREE and THP Some of users of Polars (a data analytics library) have lost production data from this bug. They seem to have just the right combination of huge pages, MADV_FREE and heavy reclaim pressure. pmd_modify() masks the old value with (_HPAGE_CHG_MASK & ~_PAGE_DIRTY), silently discarding the hardware dirty bit. The subsequent pmd_mksaveddirty() call is supposed to transfer _PAGE_DIRTY into _PAGE_SAVED_DIRTY when write-protecting, but the dirty bit was already stripped from the value, so there is nothing left to transfer. Contrast with pte_modify(), which keeps _PAGE_DIRTY_BITS in its mask, and pud_modify(), which keeps _HPAGE_CHG_MASK untouched: pmd_modify() is the odd one out. Any pmd_modify() on a writable, dirty PMD loses the dirty state. One visible consequence is data loss with MADV_FREE on PMD-mapped THP: memset(buf, 0x5A, size); // PMD-mapped THP, PMD dirty madvise(buf, size, MADV_FREE); // PMD cleaned but left writable, // folio marked lazyfree memset(buf, 0x5A, size); // hardware sets _PAGE_DIRTY again mprotect(buf, size, PROT_READ); // pmd_modify() drops the dirty bit mprotect(buf, size, PROT_READ|PROT_WRITE); // ... memory pressure ... Reclaim (e.g. under memcg pressure) then finds the lazyfree folio with no dirty bit set anywhere and frees it in __discard_anon_folio_pmd_locked(), even though the data was rewritten after MADV_FREE; subsequent reads fault in fresh zero pages. NUMA hinting alone can trigger the same loss, as do_huge_pmd_numa_page() restores the PMD through pmd_modify() as well. PMD-mapped file THPs are affected too: mprotect()/NUMA hinting dropping the dirty bit means rewritten data is never written back. Fix it by keeping _PAGE_DIRTY in the preserved mask, exactly like pte_modify() and pud_modify() do. The existing pmd_mksaveddirty()/pmd_clear_saveddirty() pair then performs the hardware-dirty <-> saved-dirty transition based on the write bit, preserving the shadow-stack encoding rules.
Title x86/mm: Fix user-space data loss with MADV_FREE and THP
First Time appeared Linux
Linux linux Kernel
CPEs cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*
Vendors & Products Linux
Linux linux Kernel
References

Subscriptions

Linux Linux Kernel
cve-icon MITRE

Status: PUBLISHED

Assigner: Linux

Published:

Updated: 2026-09-25T10:22:55.981Z

Reserved: 2026-09-25T10:18:58.204Z

Link: CVE-2026-97945

cve-icon Vulnrichment

No data.

cve-icon NVD

Status : Received

Published: 2026-09-25T11:17:21.983

Modified: 2026-09-25T11:17:21.983

Link: CVE-2026-97945

cve-icon Redhat

No data.

cve-icon OpenCVE Enrichment

Updated: 2026-09-25T15:00:20Z

Weaknesses