]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
fs/mbcache: cancel shrink work before destroying the cache
authorHyungJung Joo <jhj140711@gmail.com>
Tue, 17 Mar 2026 05:45:56 +0000 (14:45 +0900)
committerChristian Brauner <brauner@kernel.org>
Tue, 17 Mar 2026 14:36:06 +0000 (15:36 +0100)
mb_cache_destroy() calls shrinker_free() and then frees all cache
entries and the cache itself, but it does not cancel the pending
c_shrink_work work item first.

If mb_cache_entry_create() schedules c_shrink_work via schedule_work()
and the work item is still pending or running when mb_cache_destroy()
runs, mb_cache_shrink_worker() will access the cache after its memory
has been freed, causing a use-after-free.

This is only reachable by a privileged user (root or CAP_SYS_ADMIN)
who can trigger the last put of a mounted ext2/ext4/ocfs2 filesystem.

Cancel the work item with cancel_work_sync() before calling
shrinker_free(), ensuring the worker has finished and will not be
rescheduled before the cache is torn down.

Fixes: c2f3140fe2ec ("mbcache2: limit cache size")
Signed-off-by: Hyungjung Joo <jhj140711@gmail.com>
Link: https://patch.msgid.link/20260317054556.1821600-1-jhj140711@gmail.com
Signed-off-by: Christian Brauner <brauner@kernel.org>
fs/mbcache.c

index e60a840999aa98315f7a6dd038fe7ae2eed749d5..90b0564c62d0b052a729bad62cd6ded34ae39d43 100644 (file)
@@ -408,6 +408,7 @@ void mb_cache_destroy(struct mb_cache *cache)
 {
        struct mb_cache_entry *entry, *next;
 
+       cancel_work_sync(&cache->c_shrink_work);
        shrinker_free(cache->c_shrink);
 
        /*