{"id":28965,"date":"2026-09-25T20:31:37","date_gmt":"2026-09-25T12:31:37","guid":{"rendered":"https:\/\/www.54iter.cn\/?vuln=cve-2026-97533"},"modified":"2026-09-25T20:31:37","modified_gmt":"2026-09-25T12:31:37","slug":"cve-2026-97533","status":"publish","type":"vuln","link":"https:\/\/www.54iter.cn\/?vuln=cve-2026-97533","title":{"rendered":"CVE-2026-97533 &#8211; In the Linux kernel, the following vulnerability has been resolved:\n\nx86\/mm\/pat: Acquire i"},"content":{"rendered":"<p>In the Linux kernel, the following vulnerability has been resolved:<\/p>\n<p>x86\/mm\/pat: Acquire init_mm read lock on attribute changes to avoid UAF<\/p>\n<p>A previous commit protected against races between ptdump and CPA collapse,<br \/>\nhowever one still exists between attribute changes and collapse as reported<br \/>\nby Denis V. Lunev (linked).<\/p>\n<p>When an attribute change arises, a lockless page table walker obtains a PTE<br \/>\nentry, which is later written to via set_pte_atomic():<\/p>\n<p>  &#8230;<br \/>\n  -&gt; change_page_attr_set_clr()<br \/>\n  -&gt; __change_page_attr_set_clr()<br \/>\n  -&gt; __change_page_attr()<br \/>\n\t-&gt; _lookup_address_cpa()<br \/>\n\t-&gt; lookup_address_in_pgd_attr()<br \/>\n\t-&gt; [ lockless page table walker ]<br \/>\n  -&gt; set_pte_atomic()<\/p>\n<p>There is nothing preventing a concurrent CPA collapse which can free the<br \/>\nPTE that was retrieved here, resulting in a use-after-free.<\/p>\n<p>With the mmap write lock taken on init_mm over CPA collapse, resolve this<br \/>\nrace by acquiring an mmap read lock on init_mm over<br \/>\n__change_page_attr_set_clr().<\/p>\n<p>This locks across the whole operation over which the walk and the PTE<br \/>\nentry write occurs, solving the race.<\/p>\n<p>It is safe to do this here, as no spinlocks are held upon entry to<br \/>\n__change_page_attr_set_clr().<\/p>\n<p>However, the lock must not be held over an allocation, as allocation can<br \/>\ntrigger reclaim and shrinkers may call into CPA recursively, making<br \/>\ndeadlocks possible (init_mm -&gt; &#8230; -&gt; fs_reclaim -&gt; init_mm).<\/p>\n<p>A page table is allocated when a huge page needs to be split:<\/p>\n<p>  -&gt; change_page_attr_set_clr()<br \/>\n  -&gt; __change_page_attr_set_clr()<br \/>\n  -&gt; __change_page_attr()<br \/>\n  -&gt; split_large_page()<br \/>\n  [ pagetable_alloc() ]<br \/>\n  -&gt; __split_large_page()<\/p>\n<p>Avoid deadlocks by dropping the mmap lock across pagetable_alloc() in<br \/>\nsplit_large_page() and track whether this is needed by adding a new<br \/>\n&#8216;init_mm_read_locked&#8217; flag to struct cpa_data.<\/p>\n<p>This is safe as __split_large_page() (called with locks re-established)<br \/>\nrevalidates that the page table entry is the same as it was prior to the<br \/>\nlocks being dropped and __change_page_attr() repeats the entire page table<br \/>\nwalk whenever a split occurs, so concurrent split and collapse are<br \/>\naccounted for.<\/p>\n<p>Concurrent ptdump is also safe as the lock is only dropped over page table<br \/>\nallocation during which time the page table has not yet been modified.<\/p>\n<p>The CPA_COLLAPSE flag is only set by set_memory_rox(), which exclusively<br \/>\noperates upon vmalloc ranges, and on x86 only within the module mapping<br \/>\nspace.<\/p>\n<p>This is important, because some callers directly invoke<br \/>\n__change_page_attr_set_clr(), bypassing this lock. However, none of these<br \/>\noperate within the module mapping space.<\/p>\n<p>  * cpa_process_alias() &#8211; a recursive helper called by<br \/>\n    __change_page_attr_set_clr().<br \/>\n  * __set_memory_enc_pgtable() &#8211; operates on the direct mapping and (via<br \/>\n    __vmbus_establish_gpadl()) the vmalloc mapping space.<br \/>\n  * __set_pages_[n]p() &#8211; called by set_direct_map_[invalid, default,<br \/>\n    valid]_noflush(), __kernel_map_pages() &#8211; operates on the direct map.<br \/>\n  * kernel_[un]map_pages_in_pgd() &#8211; operates on EFI ranges.<\/p>\n<p>This work is based upon Denis V. Lunev&#8217;s excellent analysis of the bug<br \/>\nwith gratitude.<\/p>\n<p>[ dhansen: move to imperative voice in changelog ]<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the Linux kernel, the following vulnerability has been resolved:<\/p>\n<p>x86\/mm\/pat: Acquire init_mm read lock on attribute changes to avoid UAF<\/p>\n<p>A previous commit protected against races between ptdump a<\/p>\n","protected":false},"template":"","meta":[],"categories":[],"tags":[],"class_list":["post-28965","vuln","type-vuln","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=\/wp\/v2\/vuln\/28965","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=28965"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=28965"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=28965"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}