CVE-2026-46093
Description
In the Linux kernel, the following vulnerability has been resolved:
mm/vmalloc: take vmap_purge_lock in shrinker
decay_va_pool_node() can be invoked concurrently from two paths: __purge_vmap_area_lazy() when pools are being purged, and the shrinker via vmap_node_shrink_scan().
However, decay_va_pool_node() is not safe to run concurrently, and the shrinker path currently lacks serialization, leading to races and possible leaks.
Protect decay_va_pool_node() by taking vmap_purge_lock in the shrinker path to ensure serialization with purge users.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
A race condition in Linux kernel's vmalloc shrinker lacks serialization, causing memory leaks; fixed by taking vmap_purge_lock.
Vulnerability
In the Linux kernel, decay_va_pool_node() is invoked from two paths: __purge_vmap_area_lazy() (pool purging) and the shrinker via vmap_node_shrink_scan(). This function is not safe for concurrent execution, yet the shrinker path lacked serialization. This leads to races and potential memory leaks. The issue affects Linux kernel versions prior to the commit [1].
Exploitation
An attacker must be able to trigger concurrent execution of pool purging and shrinker operations. This could be achieved by inducing memory pressure to invoke the shrinker while purging operations are ongoing. The exact steps depend on system configuration, but the race window is present.
Impact
A race condition can cause memory leaks or corruption within the vmalloc subsystem. This may lead to system instability, denial of service, or potentially other undefined behavior.
Mitigation
The fix is included in Linux kernel commit [1], which takes vmap_purge_lock in the shrinker path to ensure serialization. Users should update to a kernel version containing this commit. No workaround is available.
AI Insight generated on May 27, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
2Patches
6687ccdf58216mm/vmalloc: take vmap_purge_lock in shrinker
1 file changed · +1 −1
mm/vmalloc.c+1 −1 modifieddiff --git a/mm/vmalloc.c b/mm/vmalloc.c index e2f526ad7abba6..c5368e171411dc 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -5255,6 +5255,7 @@ vmap_node_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) { struct vmap_node *vn; + guard(mutex)(&vmap_purge_lock); for_each_vmap_node(vn) decay_va_pool_node(vn, true); -- cgit 1.3-korg
12f2341b4c23mm/vmalloc: take vmap_purge_lock in shrinker
1 file changed · +1 −1
mm/vmalloc.c+1 −1 modifieddiff --git a/mm/vmalloc.c b/mm/vmalloc.c index 61caa55a44027b..676851d5cfe771 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -5416,6 +5416,7 @@ vmap_node_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) { struct vmap_node *vn; + guard(mutex)(&vmap_purge_lock); for_each_vmap_node(vn) decay_va_pool_node(vn, true); -- cgit 1.3-korg
ec05f51f1e65mm/vmalloc: take vmap_purge_lock in shrinker
1 file changed · +1 −1
mm/vmalloc.c+1 −1 modifieddiff --git a/mm/vmalloc.c b/mm/vmalloc.c index 61caa55a44027b..676851d5cfe771 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -5416,6 +5416,7 @@ vmap_node_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) { struct vmap_node *vn; + guard(mutex)(&vmap_purge_lock); for_each_vmap_node(vn) decay_va_pool_node(vn, true); -- cgit 1.3-korg
687ccdf58216mm/vmalloc: take vmap_purge_lock in shrinker
1 file changed · +1 −1
mm/vmalloc.c+1 −1 modifieddiff --git a/mm/vmalloc.c b/mm/vmalloc.c index e2f526ad7abba6..c5368e171411dc 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -5255,6 +5255,7 @@ vmap_node_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) { struct vmap_node *vn; + guard(mutex)(&vmap_purge_lock); for_each_vmap_node(vn) decay_va_pool_node(vn, true); -- cgit 1.3-korg
ec05f51f1e65mm/vmalloc: take vmap_purge_lock in shrinker
1 file changed · +1 −1
mm/vmalloc.c+1 −1 modifieddiff --git a/mm/vmalloc.c b/mm/vmalloc.c index 61caa55a44027b..676851d5cfe771 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -5416,6 +5416,7 @@ vmap_node_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) { struct vmap_node *vn; + guard(mutex)(&vmap_purge_lock); for_each_vmap_node(vn) decay_va_pool_node(vn, true); -- cgit 1.3-korg
12f2341b4c23mm/vmalloc: take vmap_purge_lock in shrinker
1 file changed · +1 −1
mm/vmalloc.c+1 −1 modifieddiff --git a/mm/vmalloc.c b/mm/vmalloc.c index 61caa55a44027b..676851d5cfe771 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -5416,6 +5416,7 @@ vmap_node_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) { struct vmap_node *vn; + guard(mutex)(&vmap_purge_lock); for_each_vmap_node(vn) decay_va_pool_node(vn, true); -- cgit 1.3-korg
Vulnerability mechanics
Root cause
"Missing mutex serialization in the shrinker path allows concurrent calls to decay_va_pool_node() from the shrinker and the purge path, causing races and potential memory leaks."
Attack vector
An attacker can trigger memory pressure to invoke the shrinker via vmap_node_shrink_scan() while the kernel concurrently runs __purge_vmap_area_lazy() to purge vmap pools. Because decay_va_pool_node() is not safe to run concurrently and the shrinker path lacked the vmap_purge_lock, these two execution paths can race, leading to corruption of vmap pool data structures and possible memory leaks. No special privileges or network access are required — the attacker only needs to be able to drive memory pressure on the system.
Affected code
The vulnerable code is in `mm/vmalloc.c` in the function `vmap_node_shrink_scan()`, which iterates over vmap nodes and calls `decay_va_pool_node()` for each node. The function `decay_va_pool_node()` is also called from `__purge_vmap_area_lazy()` in the same file.
What the fix does
The patch adds a single line — `guard(mutex)(&vmap_purge_lock);` — at the beginning of `vmap_node_shrink_scan()` in `mm/vmalloc.c` [patch_id=2659763]. This ensures that when the shrinker calls `decay_va_pool_node()`, it holds the same `vmap_purge_lock` that the purge path (`__purge_vmap_area_lazy()`) already acquires, serializing all concurrent invocations of `decay_va_pool_node()`. The fix is minimal and targeted: it adds the missing lock acquisition without changing any other logic.
Preconditions
- inputThe attacker must be able to trigger memory pressure on the system to invoke the shrinker.
- configThe kernel must have been built with the vmap shrinker enabled (introduced by commit 7679ba6b36db).
Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
3News mentions
0No linked articles in our index yet.