CVE-2026-89966 Overview
CVE-2026-89966 is a NULL pointer dereference vulnerability in the Linux kernel's HugeTLB Contiguous Memory Allocator (CMA) subsystem. The flaw resides in the hugetlb_cma_alloc_frozen_folio() function within mm/hugetlb_cma. When alloc_buddy_hugetlb_folio_with_mpol() falls back to allocating across all nodes, it can pass a NULL nodemask to alloc_fresh_hugetlb_folio(). For gigantic-order allocations, this NULL value propagates down to hugetlb_cma_alloc_frozen_folio(), which dereferences it through node_isset() and for_each_node_mask() macros, triggering a kernel panic.
Critical Impact
An unprivileged local user can crash the kernel by requesting a gigantic hugepage allocation with MPOL_PREFERRED_MANY on systems where CMA is configured on only a subset of NUMA nodes.
Affected Products
- Linux kernel (mainline) — mm/hugetlb_cma subsystem
- Linux kernel builds with CONFIG_CMA and HugeTLB gigantic page support enabled
- Multi-NUMA-node systems where hugetlb_cma is restricted to a subset of nodes
Discovery Timeline
- 2026-09-16 - CVE-2026-89966 published to NVD
- 2026-09-16 - Last updated in NVD database
Technical Details for CVE-2026-89966
Vulnerability Analysis
The vulnerability is a NULL pointer dereference [CWE-476] in the Linux kernel memory management code path for gigantic hugepages backed by CMA. Two separate defects converge to produce the crash. First, hugetlb_cma_alloc_frozen_folio() attempts allocations on hugetlb_cma[nid] without verifying that nid is included in the caller's nodemask, breaking cpuset and memory-policy constraints. Second, and more severely, the function dereferences the nodemask pointer through node_isset(nid, *nodemask) and for_each_node_mask(node, *nodemask) without first checking whether the pointer is NULL.
When alloc_buddy_hugetlb_folio_with_mpol() invokes the fallback path to allocate from all nodes, it passes NULL as the nodemask argument. For gigantic-order requests, this NULL propagates through alloc_fresh_hugetlb_folio() and alloc_gigantic_frozen_folio() before reaching the vulnerable dereference site.
Root Cause
The root cause is a missing NULL check combined with a missing nodemask membership check in hugetlb_cma_alloc_frozen_folio(). The function assumed callers always provided a valid nodemask, but the buddy allocator's fallback logic legitimately passes NULL to signal "all nodes." The fix defaults a NULL nodemask to cpuset_current_mems_allowed and encloses allocation attempts inside the cpuset seqcount retry loop so concurrent cpuset changes trigger a retry with the updated mask.
Attack Vector
A local unprivileged user triggers the panic by mapping a 1GB hugepage region using mmap() with MAP_HUGETLB | MAP_HUGE_1GB | MAP_NORESERVE, then calling mbind() with MPOL_PREFERRED_MANY and a nodemask restricting allocation to a node without CMA configured. A subsequent page fault (for example via memset()) drives the allocator into the vulnerable path. The crash manifests as:
BUG: kernel NULL pointer dereference, address: 0000000000000000
RIP: 0010:hugetlb_cma_alloc_frozen_folio+0x75/0x120
Call Trace:
only_alloc_fresh_hugetlb_folio.isra.0+0x2c/0x160
alloc_surplus_hugetlb_folio+0x6d/0x100
alloc_hugetlb_folio+0x3c5/0x660
hugetlb_no_page+0x3d9/0x650
Detection Methods for CVE-2026-89966
Indicators of Compromise
- Kernel oops messages referencing hugetlb_cma_alloc_frozen_folio+0x75/0x120 in dmesg or /var/log/kern.log.
- Unexpected node reboots or panics preceded by processes calling mbind() with MPOL_PREFERRED_MANY against hugepage-backed mappings.
- Repeated alloc_hugetlb_folio failures correlated with 1GB hugepage requests on multi-NUMA systems.
Detection Strategies
- Audit kernel crash dumps and kdump captures for the hugetlb_cma_alloc_frozen_folio frame in the panic backtrace.
- Monitor for unprivileged processes issuing mbind() syscalls with MPOL_PREFERRED_MANY combined with MAP_HUGE_1GB mappings via eBPF or auditd.
- Correlate host availability alerts with hugepage subsystem errors reported through /sys/kernel/mm/hugepages.
Monitoring Recommendations
- Aggregate kernel logs into a centralized data lake and alert on NULL pointer dereference events containing hugetlb_cma symbols.
- Track NUMA node CMA reservation state via /proc/meminfo and /sys/kernel/mm/hugepages to identify hosts matching the vulnerable configuration.
- Enable kdump on production hosts using gigantic hugepages so crashes produce actionable postmortem data.
How to Mitigate CVE-2026-89966
Immediate Actions Required
- Apply the upstream kernel patches referenced below and reboot affected hosts at the earliest maintenance window.
- Inventory Linux hosts that boot with hugetlb_cma= restricted to a subset of NUMA nodes and prioritize them for patching.
- Restrict mbind() and hugepage allocation privileges where feasible until patches are deployed.
Patch Information
Upstream fixes are available in the mainline tree. See Kernel Patch 10f616e and Kernel Patch 7b8a8ae. The patches add a NULL check on the nodemask, default it to cpuset_current_mems_allowed, add a node_isset() membership check, and wrap allocation attempts in the cpuset seqcount retry loop.
Workarounds
- Configure hugetlb_cma on all NUMA nodes rather than a subset to avoid triggering the fallback path.
- Avoid booting with gigantic hugepage CMA reservations (default_hugepagesz=1G hugepagesz=1G) where not strictly required.
- Constrain workloads that call mbind() with MPOL_PREFERRED_MANY to cpusets aligned with CMA-enabled nodes.
# Example: reserve 1GB CMA on all NUMA nodes instead of only node 1
# Edit /etc/default/grub and update GRUB_CMDLINE_LINUX:
GRUB_CMDLINE_LINUX="hugetlb_cma=0:1G,1:1G default_hugepagesz=1G hugepagesz=1G hugepages=0"
# Regenerate grub configuration and reboot
sudo grub-mkconfig -o /boot/grub/grub.cfg
sudo reboot
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

