{"id":29101,"date":"2026-09-25T20:31:52","date_gmt":"2026-09-25T12:31:52","guid":{"rendered":"https:\/\/www.54iter.cn\/?vuln=cve-2026-97945"},"modified":"2026-09-25T20:31:52","modified_gmt":"2026-09-25T12:31:52","slug":"cve-2026-97945","status":"publish","type":"vuln","link":"https:\/\/www.54iter.cn\/?vuln=cve-2026-97945","title":{"rendered":"CVE-2026-97945 &#8211; In the Linux kernel, the following vulnerability has been resolved:\n\nx86\/mm: Fix user-spac"},"content":{"rendered":"<p>In the Linux kernel, the following vulnerability has been resolved:<\/p>\n<p>x86\/mm: Fix user-space data loss with MADV_FREE and THP<\/p>\n<p>Some of users of Polars (a data analytics library) have lost production<br \/>\ndata from this bug. They seem to have just the right combination of<br \/>\nhuge pages, MADV_FREE and heavy reclaim pressure.<\/p>\n<p>pmd_modify() masks the old value with (_HPAGE_CHG_MASK &amp; ~_PAGE_DIRTY),<br \/>\nsilently discarding the hardware dirty bit.  The subsequent<br \/>\npmd_mksaveddirty() call is supposed to transfer _PAGE_DIRTY into<br \/>\n_PAGE_SAVED_DIRTY when write-protecting, but the dirty bit was already<br \/>\nstripped from the value, so there is nothing left to transfer.<\/p>\n<p>Contrast with pte_modify(), which keeps _PAGE_DIRTY_BITS in its mask,<br \/>\nand pud_modify(), which keeps _HPAGE_CHG_MASK untouched: pmd_modify()<br \/>\nis the odd one out.  Any pmd_modify() on a writable, dirty PMD loses<br \/>\nthe dirty state.<\/p>\n<p>One visible consequence is data loss with MADV_FREE on PMD-mapped THP:<\/p>\n<p>    memset(buf, 0x5A, size);          \/\/ PMD-mapped THP, PMD dirty<br \/>\n    madvise(buf, size, MADV_FREE);    \/\/ PMD cleaned but left writable,<br \/>\n                                      \/\/ folio marked lazyfree<br \/>\n    memset(buf, 0x5A, size);          \/\/ hardware sets _PAGE_DIRTY again<br \/>\n    mprotect(buf, size, PROT_READ);   \/\/ pmd_modify() drops the dirty bit<br \/>\n    mprotect(buf, size, PROT_READ|PROT_WRITE);<br \/>\n    \/\/ &#8230; memory pressure &#8230;<\/p>\n<p>Reclaim (e.g. under memcg pressure) then finds the lazyfree folio with<br \/>\nno dirty bit set anywhere and frees it in<br \/>\n__discard_anon_folio_pmd_locked(), even though the data was rewritten<br \/>\nafter MADV_FREE; subsequent reads fault in fresh zero pages.  NUMA<br \/>\nhinting alone can trigger the same loss, as do_huge_pmd_numa_page()<br \/>\nrestores the PMD through pmd_modify() as well.<\/p>\n<p>PMD-mapped file THPs are affected too: mprotect()\/NUMA hinting dropping<br \/>\nthe dirty bit means rewritten data is never written back.<\/p>\n<p>Fix it by keeping _PAGE_DIRTY in the preserved mask, exactly like<br \/>\npte_modify() and pud_modify() do.  The existing<br \/>\npmd_mksaveddirty()\/pmd_clear_saveddirty() pair then performs the<br \/>\nhardware-dirty  saved-dirty transition based on the write bit,<br \/>\npreserving the shadow-stack encoding rules.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the Linux kernel, the following vulnerability has been resolved:<\/p>\n<p>x86\/mm: Fix user-space data loss with MADV_FREE and THP<\/p>\n<p>Some of users of Polars (a data analytics library) have lost production<br \/>\nda<\/p>\n","protected":false},"template":"","meta":[],"categories":[],"tags":[],"class_list":["post-29101","vuln","type-vuln","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=\/wp\/v2\/vuln\/29101","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=\/wp\/v2\/vuln"}],"about":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=\/wp\/v2\/types\/vuln"}],"wp:attachment":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=29101"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=29101"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=29101"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}