A small but consequential fix landed in the Linux kernel tree this winter to address CVE-2025-68231 — a bug in the mempool poisoning path that can trigger kernel page faults when mempools allocate
order > 0 pages on systems configured with
CONFIG_HIGHMEM. The patch corrects how the kernel maps and poisons individual subpages of a high-order allocation, preventing an out-of-bounds kernel write that had been producing reproducible OOPS messages during early init and driver initialization paths.
Background
The Linux memory-management subsystem exposes a lightweight allocator called
mempool used by several kernel subsystems where a guaranteed allocation path is important. Unlike general buddy/slab allocation, mempools are designed to ensure that critical code (for example, some block layer paths) can obtain memory even under pressure by reserving pre-allocated elements.
Mempools can be backed by different allocators:
- by the slab allocator (small objects),
- by single physical pages (order 0), or
- by high-order pages (order > 0) when a contiguous multi-page allocation is required.
To catch use-after-free or memory corruption, mempool code optionally
poisons newly-allocated elements: the kernel writes a defined pattern into memory (and later checks that pattern) so bugs can be detected early. Poisoning code must map memory into kernel virtual address space before it writes into it. That is straightforward for normal kernel pages, but it becomes tricky with
HIGHMEM systems where not all physical RAM is permanently mapped into kernel space.
HIGHMEM is a configuration option typically present on 32-bit x86 builds and on some architectures where kernel virtual address space does not permanently cover all physical memory. On HIGHMEM systems, portions of physical RAM must be temporarily mapped (kmap/kmap_local_page) to perform memory accesses. High-order allocations (order > 0) are composed of multiple contiguous pages at the physical level but still require each subpage to be individually mapped before the kernel writes to the subpage when running with HIGHMEM.
CVE-2025-68231 stems from a subtle mismatch in these assumptions: the mempool poisoning path had been mapping only the
first page of an order-N allocation, then accessing the entire multi-page region as if it were already mapped. On many systems this went unnoticed because either HIGHMEM wasn't used, or implementations never exercised mempools backed by order>0 pages on HIGHMEM machines. The kernel test robot and some developers finally caught the issue when a mempool-backed allocation used by the block integrity code triggered a page fault while the kernel attempted to memset across an unmapped subpage.
What went wrong: the technical root cause
At the heart of the bug are two related functions in mm/mempool.c (the poisoning and checking paths) that assume a contiguous virtual mapping is available for the whole element being poisoned. The original code used a single mapping call (kmap_local_page) on the first struct page of the multi-page element and then called memset or memcmp across the whole element size. On HIGHMEM machines, only the first page was actually mapped; the subsequent pages remained unmapped and were therefore not safe to access. When the kernel executed a memset over the full multi-page element it hit an unmapped page and produced a kernel page fault (an OOPS), with call traces pointing to poison_element, mempool_init_node, mempool_alloc_pages and a higher-level initcall such as bio_integrity_initfn.
The fix implemented is straightforward and precise: under CONFIG_HIGHMEM the code now iterates the high-order element one page at a time. For every subpage it:
- maps the specific page into kernel address space,
- performs the poisoning or checking activity on that page-sized window,
- unmaps the page before moving to the next.
This looped approach ensures that no kernel writes or reads touch unmapped HIGHMEM pages. The patch also contains small cleanups to maintain symmetry between poisoning and check paths and preserves the early-return behavior when KASAN or other sanitizers disable mempool poisoning.
The patch was authored and submitted as a concise change to mm/mempool.c and carried signoffs from mem-management maintainers. It also references the earlier mempool poison work that introduced the original behavior; the fix is framed as a targeted correction to how the poisoning code handles order > 0 allocations on HIGHMEM builds.
Where the bug manifests — observable symptoms
When the bug is triggered the kernel will typically produce an OOPS message similar to the following pattern (paraphrased):
- BUG: unable to handle page fault for address: <hex>
PF: supervisor write access in kernel mode
PF: error_code(0x0002) - not-present page
- EIP: memset (... — indicating the memset was performing a write
- Call trace: poison_element → mempool_init_node → mempool_alloc_pages → bio_integrity_initfn → do_one_initcall
Administrators and developers may see this during early boot or when a module or driver initializes (for example block/integrity code), since mempool initialization often happens during initcall paths. In practice the OOPS is deterministic when the code path allocates a mempool backed by order>0 pages on a system compiled with HIGHMEM support.
Scope and impact: who is affected?
The vulnerability is specific in scope and relatively narrow in real-world exposure, but it is non-trivial in the contexts where it applies.
- Affected code: the mempool poisoning and checking logic in mm/mempool.c when mempools are backed by page allocator with order > 0 and the kernel is configured with CONFIG_HIGHMEM.
- Affected systems: primarily kernels built with HIGHMEM enabled — typically 32-bit x86 kernels and certain other architectures or specialized builds. Most modern 64-bit distributions run kernels without HIGHMEM and thus are not affected by this particular HIGHMEM mapping bug.
- Affected use cases: subsystems that create mempools backed by high-order pages. In public discussions and audits, code paths like the new block code, bcache, dm-integrity (depending on configuration), and certain KASAN unit test setups were identified as users of order>0 page mempools.
- Impact: kernel panic / crash (denial of service) due to kernel-mode page fault. The bug causes an OOPS and can crash the system or put it into an unstable state. There is no public indication that this bug leads to privilege escalation or arbitrary remote code execution — the observable consequence is a kernel crash triggered by kernel code touching unmapped memory.
- Exploitability: low for remote or privilege-elevating attack chains. The fault arises in kernel-mode init and allocation code; exploitation would generally require the attacker to cause the kernel to allocate a high-order mempool element under HIGHMEM conditions. In many deployments this is either impossible or highly constrained. Nevertheless, any bug that causes kernel memory accesses at unexpected addresses creates a potential surface for exploitation if combined with other vulnerabilities; so the conservative stance is to treat it as a denial-of-service risk to affected systems and remediate accordingly.
Why this slipped through and how it was found
Two factors made this bug latent for years:
- Configuration-dependent behavior: Many kernel developers and continuous-integration environments run kernels without HIGHMEM (for example 64-bit kernels) and thus never exercise code paths that need per-subpage kmap operations. As a result, code that implicitly assumed a continuous mapping across a high-order page would not fail in the predominant testing setups.
- Limited usage patterns: Using mempools backed by order > 0 pages is less common than order-0 or slab-backed mempools. Until specific b-layer changes and more extensive tests in -next trees, these code paths were rarely stressed on HIGHMEM systems.
The issue was discovered and reported by the kernel test robot when a boot/test on a HIGHMEM configuration produced a reproducible OOPS. Developers triangulated the failure to the mempool poisoning code and proposed the targeted per-subpage mapping fix that prevents the invalid write.
The fix in plain terms
The corrective change performs these steps when poisoning or checking an order-N page element on HIGHMEM:
- Replace single kmap_local_page on the first subpage with a loop across the element’s subpages.
- For each index i in [0, (1<<order) - 1]:
- Call kmap_local_page(page + i) to map the specific subpage.
- Poison or check the page-sized range beginning at the mapped address.
- Call kunmap_local (or equivalent) to unmap the subpage.
- Keep the existing fast-paths intact for non-HIGHMEM systems, where a single mapping already covers the entire element.
The net effect is minimal code complexity increase with a large reliability improvement: the kernel now never writes into unmapped HIGHMEM subpages during mempool poisoning.
Mitigation and recommended actions
System administrators and distribution maintainers should take these practical steps:
- Install vendor kernel updates: Apply kernel updates from your distribution as soon as stable packages including the fix are available. The patch is small and has already been accepted into upstream trees and marked for inclusion in stable branches; distribution vendors will typically ship it in the next security or routine kernel update cycle.
- For custom kernels, apply the upstream patch or rebase: If you build custom kernels, merge the upstream mempool HIGHMEM fix into your source tree and rebuild. The patch touches mm/mempool.c and is intentionally narrow; it can be cherry-picked into stable branches where appropriate.
- Evaluate HIGHMEM usage: On 32-bit or embedded systems where HIGHMEM builds are used, prioritize applying the fix. On typical 64-bit servers and desktops where HIGHMEM is not enabled, this particular bug is unlikely to be present — nonetheless, staying current with kernel updates remains sound practice.
- Testing prior to production rollout: Because the trace for this bug often appears during initcalls, validate kernels in a staging environment that reproduces your system’s configuration (particularly any device-mapper, bcache, or b-integrity setups) before rolling out to production.
- Temporary workarounds (last resort):
- Rebuilding the kernel with CONFIG_HIGHMEM disabled will remove the code path, but that is not practical for systems that require HIGHMEM or are 32-bit with large RAM footprints.
- Avoiding or disabling drivers/subsystems known to create order>0 mempools (if feasible) until a patched kernel is deployed.
- Using KASAN or other sanitizers is not a workaround; indeed, mempool poisoning is intentionally a diagnostic aid and KASAN may disable the mempool poisoning fast-paths. That said, these sanitizers alter behavior in non-production ways and are not a substitute for applying the patch.
Detection and forensics guidance
If you are investigating an OOPS or crash and suspect this bug, start with these steps:
- Inspect dmesg or system logs for kernel OOPS text that contains traces into poison_element, mempool_init_node, mempool_alloc_pages or bio_integrity_initfn.
- Look for error lines that indicate a #PF (page fault) during memset or memcmp in kernel space; the memset call site in the stack trace is a strong signal.
- Search for modules or initcalls that allocate mempools on startup (block, dm-integrity, bcache, and some test units are candidates).
- Reproduce the crash in a controlled staging environment with the same kernel config (particularly HIGHMEM) to confirm the exact conditions.
- If you cannot reproduce the OOPS locally, gather a full kernel OOPS log and the exact kernel config (normally available under /proc/config.gz or preserved in boot artifacts) to assist maintainers.
Risk assessment: who should prioritize this update?
Prioritize updating if any of the following are true:
- Your environment runs 32-bit kernels or kernels compiled with CONFIG_HIGHMEM enabled.
- You use block layer features or modules that create mempools backed by order>0 pages (e.g., certain configurations of bcache, device-mapper integrity targets, or specialized block code that was revised recently).
- You operate appliances, embedded devices, or specialized hardware that build kernels with HIGHMEM and are sensitive to any kernel OOPS or instability during boot or init.
For mainstream 64-bit Linux distributions with typical kernels, the immediate risk is low, but the update should still be applied when your vendor issues it — kernel correctness issues are cumulative in risk and may interact with other fixes.
Wider lessons for kernel development and testing
CVE-2025-68231 is a reminder of several ongoing realities in kernel maintenance:
- Configuration diversity matters. Differences between HIGHMEM and non-HIGHMEM kernels expose logic that may be invisible in the majority of CI runs. Broadening automated testing matrixes to include less-common configuration combinations can catch latent defects earlier.
- High-order pages are deceptively tricky. Code that treats an order-N allocation as a single linear mapping must account for platforms where a multi-page physical allocation is not a single contiguous virtual mapping. Explicit per-subpage handling is required on HIGHMEM systems.
- Test robots play a valuable role. This bug was flagged by an automated test run. Automated tests that exercise different memory allocation modes and initialization sequences are effective at surfacing these deterministic but obscure failures.
- Small patches can have high impact. The fix is compact and surgical, showing that correctness issues can often be solved without large rewrites when the root cause is well understood.
What maintainers changed and why it’s safe
The patch author limited changes to the mempool poisoning and checking code, adding conditional compilation (#ifdef CONFIG_HIGHMEM) so non-HIGHMEM builds keep the current fast-path. This containment reduces risk in a few ways:
- Non-HIGHMEM kernels preserve existing behavior and performance.
- The per-page loop is the canonical way to handle temporary kmap-based access on HIGHMEM, so it follows established kernel patterns for correctness.
- The change was reviewed and accepted by relevant maintainers and reviewers who audited the implications for KASAN and other sanitizer interactions.
- Because mempool poisoning is a defensive mechanism (not a performance-critical hot path in most cases), a small per-subpage loop under HIGHMEM is unlikely to regress performance in meaningful ways.
Conclusion
CVE-2025-68231 corrects a focused correctness bug in the mempool poisoning logic that could cause kernel page faults on systems built with HIGHMEM when mempools allocate high-order pages. The vulnerability’s practical impact is primarily denial-of-service due to kernel OOPSes during init or driver setup, and the affected population is mostly kernels compiled with HIGHMEM (commonly 32-bit builds) or specialized setups that allocate order>0 mempools.
The fix is small, well-scoped, and has already been merged into upstream trees and prepared for stable propagation; the recommended action for administrators and maintainers is straightforward: apply vendor updates or upstream patches promptly, especially for HIGHMEM-based systems and storage stacks that use mempools with order > 0. Beyond the immediate remediation, this issue highlights the importance of broad configuration testing and careful handling of high-order allocations on systems where not all physical memory is permanently mapped into kernel space.
Key takeaways:
- CVE-2025-68231 is a kernel correctness bug in mempool poisoning for order>0 pages on HIGHMEM builds.
- Symptom: deterministic kernel OOPS (page fault during memset in kernel space).
- Exposure: denial-of-service for systems with HIGHMEM and code paths that use high-order mempools.
- Remediation: apply the upstream/stable kernel patch or vendor kernel update; for custom kernels, merge the small mm/mempool.c fix and rebuild.
Source: MSRC
Security Update Guide - Microsoft Security Response Center