CVE-2026-74632: mm/huge_memory: fix huge_zero_pfn race

Published Aug 22, 2026
·
Updated

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

mm/hugememory: fix hugezeropfn race

Patch series "mm/hugememory: fix hugezeropfn race", v2.

There is a subtle race in the reference-counted hugezerofolio implementation.

The fast path atomic logic fails to account for the fact that the shrinker (which drops the final hugezerorefcount pin) can overwrite hugezeropfn with the ~0UL sentinel value in shrinkhugezerofolioscan() after a racing gethugezerofolio() installed a valid value there.

This results in hugezerofolio being correctly set but hugezeropfn being set incorrectly and thus ishugezeropfn() and consequently ishugezeropmd() will misidentify the huge zero folio as being an ordinary THP folio.

This can result in the huge zero folio being split and otherwise treated incorrectly.

The solution to this is very subtle as there is an atomic fast path, and thus ordering in weakly ordered architectures has to be treated very carefully.

The first commit fixes the issue by introducing a spinlock around hugezero[pfn, folio, refcount] write, with careful consideration paid to load/store ordering in the fast path. It is placed first and kept as small as possible so that it can be backported on its own.

The second commit is a pure cleanup which reworks the CONFIGPERSISTENTHUGEZEROFOLIO logic to better separate the persistent logic from the dynamically allocated one.

This patch (of 2):

If !CONFIGPERSISTENTHUGEZEROFOLIO, the hugezerofolio is refcounted by hugezerorefcount and returned by mmgethugezerofolio().

When the caller is done with the huge zero page, its reference count is decremented. Only a shrinker can set the reference count to zero.

A race can unfortunately occur between a shrinker decrementing the reference count to zero and a concurrent page fault.

This is because shrinkhugezerofolioscan() might, if very unlucky, be preempted between setting hugezerorefcount to zero and writing an invalid value.

During this time gethugezerofolio() could write to hugezeropfn before shrinkhugezerofolioscan() resumes.

In this event the huge zero folio will be persistently misidentified causing the THP code path to be entered inappropriately for the huge zero folio:

CPU 0 CPU 1 =======================================|================================= shrinkhugezerofolioscan() | atomiccmpxchg() sets refcount to 0 | xchg() sets hugezerofolio to NULL | gethugezerofolio() | | atomicincnotzero() -> zero preempted for a long time | Allocate new huge zero folio | | Write valid hugezerofolio v | Write valid hugezeropfn Overwrite hugezeropfn with ~0UL <--- Invalid overwrite!

This results in ishugezeropfn() and ishugezeropmd() incorrectly returning false for a huge zero page which could result in issues like the huge zero folio being incorrectly split.

Note that the issue is with hugezeropfn not hugezerofolio, as gethugezerofolio() uses cmpxchg() gated on hugezerofolio being NULL with a retry loop and shrinkhugezerofolioscan() uses xchg() to set hugezerofolio.

Fix the issue by introducing a spinlock, hugezerolock, to prevent concurrent write of hugezerofolio, hugezeropfn and hugezerorefcount.

There needs to be significant care taken here to ensure correctness:

The fast path in gethugezerofolio() uses atomicincnotzero(), which is outside of the critical section, and means huge zero allocation is gated on zero hugezerorefcount.

The fast path doesn't use hugezerolock, so the critical section is irrelevant to it.

So invariants are required - hugezerorefcount MUST:

Only be set in the hugezerolock critical section to ensure serialisation of hugezeropfn, hugezerofolio and ---truncated---

Affected Software

1 affected component
Linux Linux kernel

Event History

Aug 22, 2026
CVE Published
via MITRE·03:32 PM
Data Sourced
via MITRE·03:32 PM
Description
Data Sourced
via NVD·04:16 PM
Description

Frequently Asked Questions

1

What runtime condition is required for this race to occur?

The race requires get_huge_zero_folio() to install a valid huge_zero_pfn value while the shrinker concurrently drops the final huge_zero_refcount pin and writes the ~0UL sentinel to huge_zero_pfn.

2

What is the practical effect if the race is triggered?

The kernel can retain a correctly set huge_zero_folio while huge_zero_pfn is incorrect. Subsequent is_huge_zero_pfn() and is_huge_zero_pmd() checks can misidentify it as an ordinary transparent huge page folio, allowing it to be split or otherwise handled incorrectly.

3

What changes address the issue?

The fix introduces a spinlock around writes to huge_zero_pfn, huge_zero_folio, and huge_zero_refcount, with ordering safeguards for the atomic fast path on weakly ordered architectures.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203