Use-after-free / memory safety race due to memory cgroup release

MEDIUM
torvalds/linux
Commit: f995da5341c1
Affected: v7.0-rc5 and earlier (pre-patch kernels; this commit f995da... provides the protection)
2026-04-25 13:08 UTC

Description

The patch adds an RCU-protected path around accessing the memory cgroup from a folio in count_memcg_folio_events(). Previously, the code could read a memcg pointer (folio_memcg) and use it without preventing concurrent release of the memcg, creating a potential use-after-free or memory-safety race when a folio’s associated memory cgroup is released while being observed. The fix guards the access with folio_memcg_charged(folio) and an RCU read-side critical section, ensuring the memcg cannot be freed while its pointer is being used for event counting. This addresses a race condition that could have security implications if exploited during future LRU folio reparenting or memcg releases.

Proof of Concept

POC (conceptual, executable kernel PoC would require a controlled kernel environment): Prerequisites: - A kernel built without this patch (pre-change) running on a test system. - A folio that is charged to a memory cgroup (memcg). - A memory cgroup created and assigned to the folio, with a known memcg pointer accessible via folio_memcg(folio). Steps to reproduce (race scenario pre-patch): 1) In one thread (T1), repeatedly call count_memcg_folio_events(folio, idx, nr) for a folio that is charged to a memcg. 2) In another thread (T2), concurrently release the memcg backing that folio (e.g., perform mem_cgroup_put(memcg) or trigger the memcg release path) so that the memcg could be freed while T1 is reading it. 3) Observe a potential use-after-free or crash in T1 when count_memcg_events() accesses the memcg pointer that T2 freed. Expected result on affected (pre-patch) kernels: - A window exists where count_memcg_folio_events() may access a memcg that has been released/freed, leading to UAF or memory corruption. Expected result on patched kernels: - The access to folio_memcg() occurs under an RCU read lock and after confirming folio is charged, preventing use-after-free by ensuring the memcg cannot be freed while being read. Note: Implementing a reliable PoC requires kernel-module/kernel-internal hooks to create, couple, and release folio/memcg objects under controlled timing; the above outlines the race and how the patch mitigates it.

Commit Details

Author: Muchun Song

Date: 2026-03-05 11:52 UTC

Message:

mm: memcontrol: prevent memory cgroup release in count_memcg_folio_events() In the near future, a folio will no longer pin its corresponding memory cgroup. To ensure safety, it will only be appropriate to hold the rcu read lock or acquire a reference to the memory cgroup returned by folio_memcg(), thereby preventing it from being released. In the current patch, the rcu read lock is employed to safeguard against the release of the memory cgroup in count_memcg_folio_events(). This serves as a preparatory measure for the reparenting of the LRU pages. Link: https://lore.kernel.org/dea6aa0389367f7fd6b715c8837a2cf7506bd889.1772711148.git.zhengqi.arch@bytedance.com Signed-off-by: Muchun Song <songmuchun@bytedance.com> Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com> Reviewed-by: Harry Yoo <harry.yoo@oracle.com> Acked-by: Johannes Weiner <hannes@cmpxchg.org> Acked-by: Shakeel Butt <shakeel.butt@linux.dev> Cc: Allen Pais <apais@linux.microsoft.com> Cc: Axel Rasmussen <axelrasmussen@google.com> Cc: Baoquan He <bhe@redhat.com> Cc: Chengming Zhou <chengming.zhou@linux.dev> Cc: Chen Ridong <chenridong@huawei.com> Cc: David Hildenbrand <david@kernel.org> Cc: Hamza Mahfooz <hamzamahfooz@linux.microsoft.com> Cc: Hugh Dickins <hughd@google.com> Cc: Imran Khan <imran.f.khan@oracle.com> Cc: Kamalesh Babulal <kamalesh.babulal@oracle.com> Cc: Lance Yang <lance.yang@linux.dev> Cc: Liam Howlett <Liam.Howlett@oracle.com> Cc: Lorenzo Stoakes (Oracle) <ljs@kernel.org> Cc: Michal Hocko <mhocko@suse.com> Cc: Michal Koutný <mkoutny@suse.com> Cc: Mike Rapoport <rppt@kernel.org> Cc: Muchun Song <muchun.song@linux.dev> Cc: Nhat Pham <nphamcs@gmail.com> Cc: Roman Gushchin <roman.gushchin@linux.dev> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Usama Arif <usamaarif642@gmail.com> Cc: Vlastimil Babka <vbabka@kernel.org> Cc: Wei Xu <weixugc@google.com> Cc: Yosry Ahmed <yosry@kernel.org> Cc: Yuanchu Xie <yuanchu@google.com> Cc: Zi Yan <ziy@nvidia.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

Triage Assessment

Vulnerability Type: Memory safety / race condition (potential use-after-free)

Confidence: MEDIUM

Reasoning:

The patch adds an RCU protection around accessing the memory cgroup from a folio in count_memcg_folio_events(), preventing the memory cgroup from being released concurrently while it is being accessed. This addresses a potential race / use-after-free scenario related to memory cgroup release, which can have security implications if exploited. It is framed as a safety fix to ensure correctness during future reparenting of LRU pages.

Verification Assessment

Vulnerability Type: Use-after-free / memory safety race due to memory cgroup release

Confidence: MEDIUM

Affected Versions: v7.0-rc5 and earlier (pre-patch kernels; this commit f995da... provides the protection)

Code Diff

diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index 4454f03a4acf4a..ef26ba087844c2 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -975,10 +975,15 @@ void count_memcg_events(struct mem_cgroup *memcg, enum vm_event_item idx, static inline void count_memcg_folio_events(struct folio *folio, enum vm_event_item idx, unsigned long nr) { - struct mem_cgroup *memcg = folio_memcg(folio); + struct mem_cgroup *memcg; - if (memcg) - count_memcg_events(memcg, idx, nr); + if (!folio_memcg_charged(folio)) + return; + + rcu_read_lock(); + memcg = folio_memcg(folio); + count_memcg_events(memcg, idx, nr); + rcu_read_unlock(); } static inline void count_memcg_events_mm(struct mm_struct *mm,
← Back to Alerts View on GitHub →