In the Linux kernel, the following vulnerability has been resolved:
mm: shrinker: fix shrinker_info teardown race with expansion
expandshrinkerinfo() iterates all visible memcgs under shrinkermutex, including memcgs that have not finished ->cssonline() yet.
Once pn->shrinkerinfo has been published, teardown must stay serialized with expandshrinkerinfo() until that memcg is either fully online or no longer visible to iteration. Today allocshrinkerinfo() breaks that rule by dropping shrinkermutex before freeing a partially initialized shrinker_info array, which may cause the following race:
CPU0 CPU1 ==== ====
csscreate --> listaddtailrcu(&css->sibling, &parentcss->children); onlinecss --> memcgroupcssonline --> allocshrinkerinfo --> alloc node0 info rcuassignpointer(C->node0->shrinkerinfo, old0) alloc node1 info -> FAIL -> goto err mutexunlock(shrinkermutex)
shrinker_alloc()
--> shrinker_memcg_alloc
--> mutex_lock(shrinker_mutex)
expand_shrinker_info
--> mem_cgroup_iter see the memcg
expand_one_shrinker_info
--> old0 = C->node0->shrinker_info
memcpy(new->unit, old0->unit, ...);
free_shrinker_info
--> kvfree(old0);
/* double free !! */
kvfree_rcu(old0, rcu);
The same problem exists later in memcgroupcssonline(). If allocshrinkerinfo() succeeds but a subsequent objcg allocation fails, the freeobjcg -> freeshrinkerinfo() unwind path tears down the already published pn->shrinkerinfo arrays without shrinkermutex. The expandoneshrinkerinfo() can race with that teardown in the same way, leading to use-after-free or double-free of the old shrinkerinfo.
Fix this by serializing shrinkerinfo teardown with shrinkermutex, and by keeping allocshrinkerinfo() error cleanup inside the locked section.
{
"cna_assigner": "Linux",
"osv_generated_from": "https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/64xxx/CVE-2026-64418.json"
}