CVE-2026-98225
Executive Summary
CVE-2026-98225 is a Linux kernel memory-management defect in the shrinker subsystem that is triggered only when the kernel is booted with the cgroup.memory=nokmem option. Under that configuration, memcg-aware shrinker IDs are never allocated, yet a memcg-aware data path (deferred_split_folio()) still supplies a real memcg to __list_lru_add(), which calls set_shrinker_bit() with an index that appears valid but is out of range. The result is a kernel WARN_ON_ONCE() bounds-check trip on the first transparent huge page (THP) queued in a cgroup — a denial-of-service/log-noise impact, not a memory-corruption primitive, because the WARN keeps the out-of-bounds unit[] read from occurring. Impact is confined to systems running the nokmem boot option; the flaw is not remotely exploitable and no public exploit, PoC, or Nuclei template exists.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Technical Analysis
The vulnerability lives in the interaction between three pieces of the shrinker / list_lru / memcg plumbing:
Shrinker ID allocation is skipped under nokmem. When
cgroup.memory=nokmemis set,shrinker_memcg_alloc()bails out early and never allocates a per-shrinker memcg ID. Because the shrinker object was obtained fromkzalloc()inshrinker_alloc(), the uninitialized-on-purposeshrinker->idfield retains the value0.Zero is a plausible-looking bit index.
__list_lru_init()copiesshrinker->idintolru->shrinker_id. Since the field was never populated, the value0is written — and0is indistinguishable from a legitimate first bit index to downstream code.The shrinker info map is never expanded. Nothing calls
expand_shrinker_info()when nokmem is active, soshrinker_nr_maxstays0and every memcg is left with an empty map (map_nr_max == 0). The bitmap capacity is therefore zero while an index of0is still considered in-range by the caller.The bounds check trips on the first THP.
deferred_split_folio()passes a real memcg to__list_lru_add()regardless of whether the LRU is actually memcg-aware. On the first transparent huge page queued inside a cgroup, the kernel executesset_shrinker_bit(memcg, nid, 0). The internal bounds check inset_shrinker_bit()fails against the zero-sized map and fires:WARNING: mm/shrinker.c:212 at set_shrinker_bit+0x7d/0x90, CPU#126 Call Trace: <TASK> deferred_split_folio+0x18c/0x220 map_anon_folio_pmd_nopf+0xdd/0x130 map_anon_folio_pmd_pf+0x14/0xb0 do_huge_pmd_anonymous_page+0x1a1/0x620 __handle_mm_fault+0xea9/0x10d0 handle_mm_fault+0xe5/0x320 do_user_addr_fault+0x1cc/0x870 exc_page_fault+0x81/0x1b0 asm_exc_page_fault+0x27/0x30 </TASK>
The WARN_ON_ONCE() is explicitly described as the control that prevents the out-of-bounds unit[] read from actually happening. In other words, the faulty state (a "valid-looking" index of 0 against a zero-length map) is contained by the kernel warning machinery rather than by correct index validation. This is a robustness/defensive-programming defect — the ID "should not look valid in the first place."
The description notes that the fix is to clear the id before returning from shrinker_memcg_alloc(), and that two alternate locations could mask the symptom: dropping the id in __list_lru_init() when nokmem turns memcg_aware off, or having deferred_split_folio() pass NULL as list_lru_add_obj() does. Only the first is a root-cause fix; the others are paper-overs.
Attack surface: local only. The trigger condition is transparent huge page allocation in a memcg on a nokmem-booted kernel, which any unprivileged process that faults in anonymous memory can reach. No privilege escalation is demonstrated because the warning path terminates before the out-of-bounds read.
Exploitation Scenarios
No public PoC exists; the following chain is inferred strictly from the vulnerability class and the code paths named in the NVD description.
Reconnaissance / target identification. The attacker needs local code execution on a Linux host and must determine whether the running kernel was booted with
cgroup.memory=nokmem(visible via/proc/cmdline), whether THP is enabled (/sys/kernel/mm/transparent_hugepage/enabled), and whether the workload is cgroup-constrained. These are low-privilege, unauthenticated local checks. No network-visible banner or endpoint is involved.Triggering the specific flaw class. The defect is an improper index-validation issue (CWE-129) reached via an uninitialized-default ID. The attacker forces transparent huge page allocation inside a memory cgroup — for example, by faulting in a large anonymous mapping sized to encourage PMD-sized THP placement. The first such fault reaches
deferred_split_folio(), which hands a real memcg to__list_lru_add()even though the LRU is not memcg-aware under nokmem, invokingset_shrinker_bit()with index0against a zero-sized map.Payload / execution method (class level). There is no payload in the classic sense. The "execution" is the kernel's own memcg/THP code path; the observable effect is the
WARN_ON_ONCE()atmm/shrinker.c:212. Because the warning is one-shot (_ONCE), repeated attempts produce at most one splat per boot.Post-exploitation impact. The confirmed impact is a kernel warning and log pollution, not code execution or data disclosure. The bounds check prevents the
unit[]out-of-bounds read, so no memory-safety consequence is demonstrated. In hardened environments wherepanic_on_warn=1is set, the warning would escalate to a kernel panic and full host denial of service — this is an operational amplification, not a new primitive, and is conditional on that sysctl being enabled.
Impact Assessment
Business impact is limited and configuration-dependent. On kernels booted with cgroup.memory=nokmem, the flaw produces a spurious kernel WARN traceback whenever the first THP is queued in a cgroup. In container fleets and multi-tenant hosts, this means log noise, monitoring alert fatigue, and — where panic_on_warn=1 is enforced — unplanned node reboots and outage of every co-located workload on that host. Confidentiality and integrity impact are assessed as none: the warning path terminates before the out-of-bounds unit[] read executes, so no memory is disclosed or corrupted. Availability impact is Low under normal settings (no crash) and rises to host-wide denial of service only under the panic_on_warn policy. CVSS base vector is provided as CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:L: local attack vector, low complexity, low privileges, no user interaction, unchanged scope, no confidentiality or integrity impact, low availability impact. No CVSS score or CWE identifier was published by the vendor; EPSS is unscored. CISA KEV does not list this CVE. Affected systems are Linux servers, virtual machines, and container nodes running a kernel with the shrinker memcg code path and the nokmem option set. Blast radius is per-host; there is no cross-host propagation.
Detection Guidance
Because this fault is a kernel-internal warning with no network component or file artifact, detection is host- and telemetry-centric. Network signatures are included for completeness but are generic Linux/cgroup reconnaissance coverage, not exploit-specific.
Sigma Rule
title: Linux Kernel Shrinker Bounds Warning (CVE-2026-98225, nokmem)
id: 3b8f2c14-9a7d-4e21-b5c6-7d0e9f1a2b34
status: experimental
description: Detects the WARN_ON_ONCE in set_shrinker_bit reachable via deferred_split_folio on kernels booted with cgroup.memory=nokmem
references:
- https://nvd.nist.gov/vuln/detail/CVE-2026-98225
author: valtersit.com threat intelligence
logsource:
product: linux
service: kernel
detection:
selection_kernel:
- 'kernel: WARNING: mm/shrinker.c:212'
- 'set_shrinker_bit+0x'
- 'deferred_split_folio+0x'
selection_bootopt:
- 'cgroup.memory=nokmem'
condition: selection_kernel or (selection_bootopt and selection_kernel)
falsepositives:
- Genuine shrinker bugs unrelated to nokmem
- Other kernel WARN_ON_ONCE events in the mm subsystem
level: low
tags:
- attack.impact
- attack.t1499
YARA Rule
rule CVE_2026_98225_Linux_Shrinker_Nokmem
{
meta:
author = "valtersit.com threat intelligence"
description = "Detects kernel log/exploit artifacts referencing the nokmem shrinker id defect"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2026-98225"
date = "2026-01-01"
hash = "n/a"
strings:
$a = "WARNING: mm/shrinker.c:212" ascii wide
$b = "set_shrinker_bit+0x" ascii wide
$c = "deferred_split_folio+0x" ascii wide
$d = "cgroup.memory=nokmem" ascii wide
$e = "shrinker_memcg_alloc" ascii wide
condition:
uint32(0) != 0x464c457f and
(any of ($a, $b, $c, $e) or all of ($d, $e))
}
Suricata IDS Rule
alert tcp $EXTERNAL_NET any -> $HOME_NET 22 (msg:"CVE-2026-98225 Linux cgroup.nokmem local host reconnaissance - SSH session setup"; flow:to_server,established; app-layer-protocol:ssh; classtype:attempted-recon; sid:900098225; rev:1; metadata:created_at 2026_01_01, cve CVE-2026-98225, affected_product Linux_Kernel;)
Elastic Detection
sequence by host.id with maxspan=60s
[ process where event.type == "start" and process.name in ("ssh", "sshd") ]
[ file where file.path == "/proc/cmdline" and event.action == "open" and
process.name != null and
(process.name in ("cat", "grep", "sh", "bash", "awk", "sed")) ]
Splunk SPL Query
index=os sourcetype=syslog ("mm/shrinker.c:212" OR "set_shrinker_bit+0x" OR "deferred_split_folio+0x")
| stats count values(host) as hosts min(_time) as first_seen max(_time) as last_seen by sourcetype
| where count >= 1
| eval cve="CVE-2026-98225", tactic="T1499", severity="low"
| table first_seen last_seen hosts count cve tactic severity
Wazuh OSSEC Rule
<group name="linux,kernel,cve_2026_98225,">
<rule id="982251" level="6">
<decoded_as>syslog</decoded_as>
<program_name>kernel</program_name>
<match>WARNING: mm/shrinker.c:212|set_shrinker_bit\+0x|deferred_split_folio\+0x</match>
<description>CVE-2026-98225: Linux kernel shrinker bounds WARN_ON_ONCE (nokmem boot option) observed</description>
<mitre>
<id>T1499</id>
</mitre>
<group>kernel_shrinker_nokmem,</group>
</rule>
</group>
Mitigation & Patch Guidance
Patch confidence: 0/4 (UNPATCHED — no patch evidence from any tracked source).
Immediate mitigations. Remove
cgroup.memory=nokmemfrom the kernel command line where it is not operationally required; without that option,shrinker_memcg_alloc()allocates a real id and the bug is unreachable. Wherenokmemmust be retained, verify thatpanic_on_warnis disabled (sysctl kernel.panic_on_warn=0) so a benign WARN cannot escalate to a host panic. Machines needing strictpanic_on_warn=1should not also setnokmem.Patch / upgrade steps. No fixed kernel version is confirmed by any tracked source. The vendor-side fix described in the NVD text is to clear
shrinker->idbefore returning fromshrinker_memcg_alloc(); a stable point release containing that change has not been identified. Until a release is confirmed, follow Linux kernel stable announcement channels and the upstreammm/shrinker.chistory directly, then apply the first stable kernel that includes the id-clearing change and reboot into it. Do not treat the alternate "paper over" changes (id drop in__list_lru_init(), NULL fromdeferred_split_folio()) as substitutes if a root-cause fix is available.Long-term hardening. Audit kernel command lines fleet-wide for
nokmemand standardize a single stance on it; document why it is set and periodically re-justify it. Instrument kernel WARN/BUG traces centrally so mm-subsystem warnings are triaged rather than ignored. Evaluatepanic_on_warnpolicies per workload class so debugging aids like this cannot turn a warning into an outage. Track mm/shrinker and mm/list_lru upstream changes as part of normal kernel-release review, and keep container hosts patched and rebooted so fixes actually take effect.
References
- NVD — CVE-2026-98225: https://nvd.nist.gov/vuln/detail/CVE-2026-98225
- Linux kernel documentation — cgroup v1/v2 memory controller and
nokmemoption: https://docs.kernel.org/admin-guide/cgroup-v2.html - Linux kernel source tree —
mm/shrinker.c,mm/list_lru.c(paths cited in the NVD description; consult upstream history for the id-clearing fix) - FIRST.org EPSS — CVE-2026-98225 (not yet scored): https://api.first.org/data/v1/epss?cve=CVE-2026-98225
- CISA Known Exploited Vulnerabilities Catalog (CVE-2026-98225 not listed): https://www.cisa.gov/known-exploited-vulnerabilities-catalog
No known threat actor campaigns and no exploit-in-the-wild evidence are associated with this CVE. No public PoC, exploit code, or Nuclei template exists as of this writing.
What is this? Security researchers use these exact search queries on Shodan.io (a search engine for internet-connected devices) to find vulnerable systems globally. You can copy these dorks to see if your organization's IP space is exposed.
💣 PoC CODE AVAILABLE
Exploit code for this CVE is tracked in our database.
Access poc_code via API Pro.