From: Greg Kroah-Hartman Date: Tue, 23 Jul 2024 17:55:38 +0000 (+0200) Subject: 6.1-stable patches X-Git-Tag: v6.10.1~2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=968f4745c285c2a2c637b516c27d2ab732fc61f9;p=thirdparty%2Fkernel%2Fstable-queue.git 6.1-stable patches added patches: cachefiles-fix-slab-use-after-free-in-cachefiles_withdraw_cookie.patch cachefiles-fix-slab-use-after-free-in-fscache_withdraw_volume.patch netfs-fscache-export-fscache_put_volume-and-add-fscache_try_get_volume.patch --- diff --git a/queue-6.1/cachefiles-fix-slab-use-after-free-in-cachefiles_withdraw_cookie.patch b/queue-6.1/cachefiles-fix-slab-use-after-free-in-cachefiles_withdraw_cookie.patch new file mode 100644 index 00000000000..ee5470c5b07 --- /dev/null +++ b/queue-6.1/cachefiles-fix-slab-use-after-free-in-cachefiles_withdraw_cookie.patch @@ -0,0 +1,164 @@ +From stable+bounces-60614-greg=kroah.com@vger.kernel.org Fri Jul 19 15:46:33 2024 +From: libaokun@huaweicloud.com +Date: Fri, 19 Jul 2024 21:43:38 +0800 +Subject: cachefiles: fix slab-use-after-free in cachefiles_withdraw_cookie() +To: stable@vger.kernel.org +Cc: gregkh@linuxfoundation.org, sashal@kernel.org, patches@lists.linux.dev, hsiangkao@linux.alibaba.com, yangerkun@huawei.com, libaokun1@huawei.com, Hou Tao , Christian Brauner +Message-ID: <20240719134338.1642739-3-libaokun@huaweicloud.com> + +From: Baokun Li + +[ Upstream commit 5d8f805789072ea7fd39504694b7bd17e5f751c4 ] + +We got the following issue in our fault injection stress test: + +================================================================== +BUG: KASAN: slab-use-after-free in cachefiles_withdraw_cookie+0x4d9/0x600 +Read of size 8 at addr ffff888118efc000 by task kworker/u78:0/109 + +CPU: 13 PID: 109 Comm: kworker/u78:0 Not tainted 6.8.0-dirty #566 +Call Trace: + + kasan_report+0x93/0xc0 + cachefiles_withdraw_cookie+0x4d9/0x600 + fscache_cookie_state_machine+0x5c8/0x1230 + fscache_cookie_worker+0x91/0x1c0 + process_one_work+0x7fa/0x1800 + [...] + +Allocated by task 117: + kmalloc_trace+0x1b3/0x3c0 + cachefiles_acquire_volume+0xf3/0x9c0 + fscache_create_volume_work+0x97/0x150 + process_one_work+0x7fa/0x1800 + [...] + +Freed by task 120301: + kfree+0xf1/0x2c0 + cachefiles_withdraw_cache+0x3fa/0x920 + cachefiles_put_unbind_pincount+0x1f6/0x250 + cachefiles_daemon_release+0x13b/0x290 + __fput+0x204/0xa00 + task_work_run+0x139/0x230 + do_exit+0x87a/0x29b0 + [...] +================================================================== + +Following is the process that triggers the issue: + + p1 | p2 +------------------------------------------------------------ + fscache_begin_lookup + fscache_begin_volume_access + fscache_cache_is_live(fscache_cache) +cachefiles_daemon_release + cachefiles_put_unbind_pincount + cachefiles_daemon_unbind + cachefiles_withdraw_cache + fscache_withdraw_cache + fscache_set_cache_state(cache, FSCACHE_CACHE_IS_WITHDRAWN); + cachefiles_withdraw_objects(cache) + fscache_wait_for_objects(fscache) + atomic_read(&fscache_cache->object_count) == 0 + fscache_perform_lookup + cachefiles_lookup_cookie + cachefiles_alloc_object + refcount_set(&object->ref, 1); + object->volume = volume + fscache_count_object(vcookie->cache); + atomic_inc(&fscache_cache->object_count) + cachefiles_withdraw_volumes + cachefiles_withdraw_volume + fscache_withdraw_volume + __cachefiles_free_volume + kfree(cachefiles_volume) + fscache_cookie_state_machine + cachefiles_withdraw_cookie + cache = object->volume->cache; + // cachefiles_volume UAF !!! + +After setting FSCACHE_CACHE_IS_WITHDRAWN, wait for all the cookie lookups +to complete first, and then wait for fscache_cache->object_count == 0 to +avoid the cookie exiting after the volume has been freed and triggering +the above issue. Therefore call fscache_withdraw_volume() before calling +cachefiles_withdraw_objects(). + +This way, after setting FSCACHE_CACHE_IS_WITHDRAWN, only the following two +cases will occur: +1) fscache_begin_lookup fails in fscache_begin_volume_access(). +2) fscache_withdraw_volume() will ensure that fscache_count_object() has + been executed before calling fscache_wait_for_objects(). + +Fixes: fe2140e2f57f ("cachefiles: Implement volume support") +Suggested-by: Hou Tao +Signed-off-by: Baokun Li +Link: https://lore.kernel.org/r/20240628062930.2467993-4-libaokun@huaweicloud.com +Signed-off-by: Christian Brauner +Signed-off-by: Baokun Li +Signed-off-by: Greg Kroah-Hartman +--- + fs/cachefiles/cache.c | 35 ++++++++++++++++++++++++++++++++++- + fs/cachefiles/volume.c | 1 - + 2 files changed, 34 insertions(+), 2 deletions(-) + +--- a/fs/cachefiles/cache.c ++++ b/fs/cachefiles/cache.c +@@ -313,7 +313,39 @@ static void cachefiles_withdraw_objects( + } + + /* +- * Withdraw volumes. ++ * Withdraw fscache volumes. ++ */ ++static void cachefiles_withdraw_fscache_volumes(struct cachefiles_cache *cache) ++{ ++ struct list_head *cur; ++ struct cachefiles_volume *volume; ++ struct fscache_volume *vcookie; ++ ++ _enter(""); ++retry: ++ spin_lock(&cache->object_list_lock); ++ list_for_each(cur, &cache->volumes) { ++ volume = list_entry(cur, struct cachefiles_volume, cache_link); ++ ++ if (atomic_read(&volume->vcookie->n_accesses) == 0) ++ continue; ++ ++ vcookie = fscache_try_get_volume(volume->vcookie, ++ fscache_volume_get_withdraw); ++ if (vcookie) { ++ spin_unlock(&cache->object_list_lock); ++ fscache_withdraw_volume(vcookie); ++ fscache_put_volume(vcookie, fscache_volume_put_withdraw); ++ goto retry; ++ } ++ } ++ spin_unlock(&cache->object_list_lock); ++ ++ _leave(""); ++} ++ ++/* ++ * Withdraw cachefiles volumes. + */ + static void cachefiles_withdraw_volumes(struct cachefiles_cache *cache) + { +@@ -381,6 +413,7 @@ void cachefiles_withdraw_cache(struct ca + pr_info("File cache on %s unregistering\n", fscache->name); + + fscache_withdraw_cache(fscache); ++ cachefiles_withdraw_fscache_volumes(cache); + + /* we now have to destroy all the active objects pertaining to this + * cache - which we do by passing them off to thread pool to be +--- a/fs/cachefiles/volume.c ++++ b/fs/cachefiles/volume.c +@@ -133,7 +133,6 @@ void cachefiles_free_volume(struct fscac + + void cachefiles_withdraw_volume(struct cachefiles_volume *volume) + { +- fscache_withdraw_volume(volume->vcookie); + cachefiles_set_volume_xattr(volume); + __cachefiles_free_volume(volume); + } diff --git a/queue-6.1/cachefiles-fix-slab-use-after-free-in-fscache_withdraw_volume.patch b/queue-6.1/cachefiles-fix-slab-use-after-free-in-fscache_withdraw_volume.patch new file mode 100644 index 00000000000..79dc8fde4d9 --- /dev/null +++ b/queue-6.1/cachefiles-fix-slab-use-after-free-in-fscache_withdraw_volume.patch @@ -0,0 +1,171 @@ +From stable+bounces-60615-greg=kroah.com@vger.kernel.org Fri Jul 19 15:46:32 2024 +From: libaokun@huaweicloud.com +Date: Fri, 19 Jul 2024 21:43:37 +0800 +Subject: cachefiles: fix slab-use-after-free in fscache_withdraw_volume() +To: stable@vger.kernel.org +Cc: gregkh@linuxfoundation.org, sashal@kernel.org, patches@lists.linux.dev, hsiangkao@linux.alibaba.com, yangerkun@huawei.com, libaokun1@huawei.com, Christian Brauner +Message-ID: <20240719134338.1642739-2-libaokun@huaweicloud.com> + +From: Baokun Li + +[ Upstream commit 522018a0de6b6fcce60c04f86dfc5f0e4b6a1b36 ] + +We got the following issue in our fault injection stress test: + +================================================================== +BUG: KASAN: slab-use-after-free in fscache_withdraw_volume+0x2e1/0x370 +Read of size 4 at addr ffff88810680be08 by task ondemand-04-dae/5798 + +CPU: 0 PID: 5798 Comm: ondemand-04-dae Not tainted 6.8.0-dirty #565 +Call Trace: + kasan_check_range+0xf6/0x1b0 + fscache_withdraw_volume+0x2e1/0x370 + cachefiles_withdraw_volume+0x31/0x50 + cachefiles_withdraw_cache+0x3ad/0x900 + cachefiles_put_unbind_pincount+0x1f6/0x250 + cachefiles_daemon_release+0x13b/0x290 + __fput+0x204/0xa00 + task_work_run+0x139/0x230 + +Allocated by task 5820: + __kmalloc+0x1df/0x4b0 + fscache_alloc_volume+0x70/0x600 + __fscache_acquire_volume+0x1c/0x610 + erofs_fscache_register_volume+0x96/0x1a0 + erofs_fscache_register_fs+0x49a/0x690 + erofs_fc_fill_super+0x6c0/0xcc0 + vfs_get_super+0xa9/0x140 + vfs_get_tree+0x8e/0x300 + do_new_mount+0x28c/0x580 + [...] + +Freed by task 5820: + kfree+0xf1/0x2c0 + fscache_put_volume.part.0+0x5cb/0x9e0 + erofs_fscache_unregister_fs+0x157/0x1b0 + erofs_kill_sb+0xd9/0x1c0 + deactivate_locked_super+0xa3/0x100 + vfs_get_super+0x105/0x140 + vfs_get_tree+0x8e/0x300 + do_new_mount+0x28c/0x580 + [...] +================================================================== + +Following is the process that triggers the issue: + + mount failed | daemon exit +------------------------------------------------------------ + deactivate_locked_super cachefiles_daemon_release + erofs_kill_sb + erofs_fscache_unregister_fs + fscache_relinquish_volume + __fscache_relinquish_volume + fscache_put_volume(fscache_volume, fscache_volume_put_relinquish) + zero = __refcount_dec_and_test(&fscache_volume->ref, &ref); + cachefiles_put_unbind_pincount + cachefiles_daemon_unbind + cachefiles_withdraw_cache + cachefiles_withdraw_volumes + list_del_init(&volume->cache_link) + fscache_free_volume(fscache_volume) + cache->ops->free_volume + cachefiles_free_volume + list_del_init(&cachefiles_volume->cache_link); + kfree(fscache_volume) + cachefiles_withdraw_volume + fscache_withdraw_volume + fscache_volume->n_accesses + // fscache_volume UAF !!! + +The fscache_volume in cache->volumes must not have been freed yet, but its +reference count may be 0. So use the new fscache_try_get_volume() helper +function try to get its reference count. + +If the reference count of fscache_volume is 0, fscache_put_volume() is +freeing it, so wait for it to be removed from cache->volumes. + +If its reference count is not 0, call cachefiles_withdraw_volume() with +reference count protection to avoid the above issue. + +Fixes: fe2140e2f57f ("cachefiles: Implement volume support") +Signed-off-by: Baokun Li +Link: https://lore.kernel.org/r/20240628062930.2467993-3-libaokun@huaweicloud.com +Signed-off-by: Christian Brauner +Signed-off-by: Baokun Li +Signed-off-by: Greg Kroah-Hartman +--- + fs/cachefiles/cache.c | 10 ++++++++++ + include/trace/events/fscache.h | 4 ++++ + 2 files changed, 14 insertions(+) + +--- a/fs/cachefiles/cache.c ++++ b/fs/cachefiles/cache.c +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + #include "internal.h" + + /* +@@ -319,12 +320,20 @@ static void cachefiles_withdraw_volumes( + _enter(""); + + for (;;) { ++ struct fscache_volume *vcookie = NULL; + struct cachefiles_volume *volume = NULL; + + spin_lock(&cache->object_list_lock); + if (!list_empty(&cache->volumes)) { + volume = list_first_entry(&cache->volumes, + struct cachefiles_volume, cache_link); ++ vcookie = fscache_try_get_volume(volume->vcookie, ++ fscache_volume_get_withdraw); ++ if (!vcookie) { ++ spin_unlock(&cache->object_list_lock); ++ cpu_relax(); ++ continue; ++ } + list_del_init(&volume->cache_link); + } + spin_unlock(&cache->object_list_lock); +@@ -332,6 +341,7 @@ static void cachefiles_withdraw_volumes( + break; + + cachefiles_withdraw_volume(volume); ++ fscache_put_volume(vcookie, fscache_volume_put_withdraw); + } + + _leave(""); +--- a/include/trace/events/fscache.h ++++ b/include/trace/events/fscache.h +@@ -35,12 +35,14 @@ enum fscache_volume_trace { + fscache_volume_get_cookie, + fscache_volume_get_create_work, + fscache_volume_get_hash_collision, ++ fscache_volume_get_withdraw, + fscache_volume_free, + fscache_volume_new_acquire, + fscache_volume_put_cookie, + fscache_volume_put_create_work, + fscache_volume_put_hash_collision, + fscache_volume_put_relinquish, ++ fscache_volume_put_withdraw, + fscache_volume_see_create_work, + fscache_volume_see_hash_wake, + fscache_volume_wait_create_work, +@@ -120,12 +122,14 @@ enum fscache_access_trace { + EM(fscache_volume_get_cookie, "GET cook ") \ + EM(fscache_volume_get_create_work, "GET creat") \ + EM(fscache_volume_get_hash_collision, "GET hcoll") \ ++ EM(fscache_volume_get_withdraw, "GET withd") \ + EM(fscache_volume_free, "FREE ") \ + EM(fscache_volume_new_acquire, "NEW acq ") \ + EM(fscache_volume_put_cookie, "PUT cook ") \ + EM(fscache_volume_put_create_work, "PUT creat") \ + EM(fscache_volume_put_hash_collision, "PUT hcoll") \ + EM(fscache_volume_put_relinquish, "PUT relnq") \ ++ EM(fscache_volume_put_withdraw, "PUT withd") \ + EM(fscache_volume_see_create_work, "SEE creat") \ + EM(fscache_volume_see_hash_wake, "SEE hwake") \ + E_(fscache_volume_wait_create_work, "WAIT crea") diff --git a/queue-6.1/netfs-fscache-export-fscache_put_volume-and-add-fscache_try_get_volume.patch b/queue-6.1/netfs-fscache-export-fscache_put_volume-and-add-fscache_try_get_volume.patch new file mode 100644 index 00000000000..927131366b4 --- /dev/null +++ b/queue-6.1/netfs-fscache-export-fscache_put_volume-and-add-fscache_try_get_volume.patch @@ -0,0 +1,92 @@ +From stable+bounces-60613-greg=kroah.com@vger.kernel.org Fri Jul 19 15:46:31 2024 +From: libaokun@huaweicloud.com +Date: Fri, 19 Jul 2024 21:43:36 +0800 +Subject: netfs, fscache: export fscache_put_volume() and add fscache_try_get_volume() +To: stable@vger.kernel.org +Cc: gregkh@linuxfoundation.org, sashal@kernel.org, patches@lists.linux.dev, hsiangkao@linux.alibaba.com, yangerkun@huawei.com, libaokun1@huawei.com, Christian Brauner +Message-ID: <20240719134338.1642739-1-libaokun@huaweicloud.com> + +From: Baokun Li + +[ Upstream commit 85b08b31a22b481ec6528130daf94eee4452e23f ] + +Export fscache_put_volume() and add fscache_try_get_volume() +helper function to allow cachefiles to get/put fscache_volume +via linux/fscache-cache.h. + +Signed-off-by: Baokun Li +Link: https://lore.kernel.org/r/20240628062930.2467993-2-libaokun@huaweicloud.com +Signed-off-by: Christian Brauner +Stable-dep-of: 522018a0de6b ("cachefiles: fix slab-use-after-free in fscache_withdraw_volume()") +Stable-dep-of: 5d8f80578907 ("cachefiles: fix slab-use-after-free in cachefiles_withdraw_cookie()") +Signed-off-by: Baokun Li +Signed-off-by: Greg Kroah-Hartman +--- + fs/fscache/internal.h | 2 -- + fs/fscache/volume.c | 14 ++++++++++++++ + include/linux/fscache-cache.h | 6 ++++++ + 3 files changed, 20 insertions(+), 2 deletions(-) + +--- a/fs/fscache/internal.h ++++ b/fs/fscache/internal.h +@@ -145,8 +145,6 @@ extern const struct seq_operations fscac + + struct fscache_volume *fscache_get_volume(struct fscache_volume *volume, + enum fscache_volume_trace where); +-void fscache_put_volume(struct fscache_volume *volume, +- enum fscache_volume_trace where); + bool fscache_begin_volume_access(struct fscache_volume *volume, + struct fscache_cookie *cookie, + enum fscache_access_trace why); +--- a/fs/fscache/volume.c ++++ b/fs/fscache/volume.c +@@ -27,6 +27,19 @@ struct fscache_volume *fscache_get_volum + return volume; + } + ++struct fscache_volume *fscache_try_get_volume(struct fscache_volume *volume, ++ enum fscache_volume_trace where) ++{ ++ int ref; ++ ++ if (!__refcount_inc_not_zero(&volume->ref, &ref)) ++ return NULL; ++ ++ trace_fscache_volume(volume->debug_id, ref + 1, where); ++ return volume; ++} ++EXPORT_SYMBOL(fscache_try_get_volume); ++ + static void fscache_see_volume(struct fscache_volume *volume, + enum fscache_volume_trace where) + { +@@ -420,6 +433,7 @@ void fscache_put_volume(struct fscache_v + fscache_free_volume(volume); + } + } ++EXPORT_SYMBOL(fscache_put_volume); + + /* + * Relinquish a volume representation cookie. +--- a/include/linux/fscache-cache.h ++++ b/include/linux/fscache-cache.h +@@ -19,6 +19,7 @@ + enum fscache_cache_trace; + enum fscache_cookie_trace; + enum fscache_access_trace; ++enum fscache_volume_trace; + + enum fscache_cache_state { + FSCACHE_CACHE_IS_NOT_PRESENT, /* No cache is present for this name */ +@@ -97,6 +98,11 @@ extern void fscache_withdraw_cookie(stru + + extern void fscache_io_error(struct fscache_cache *cache); + ++extern struct fscache_volume * ++fscache_try_get_volume(struct fscache_volume *volume, ++ enum fscache_volume_trace where); ++extern void fscache_put_volume(struct fscache_volume *volume, ++ enum fscache_volume_trace where); + extern void fscache_end_volume_access(struct fscache_volume *volume, + struct fscache_cookie *cookie, + enum fscache_access_trace why); diff --git a/queue-6.1/series b/queue-6.1/series index 38544555740..600650fa83f 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -100,3 +100,6 @@ bluetooth-l2cap-fix-deadlock.patch of-irq-disable-interrupt-map-parsing-for-pasemi-nemo.patch wifi-cfg80211-wext-set-ssids-null-for-passive-scans.patch wifi-mac80211-disable-softirqs-for-queued-frame-handling.patch +netfs-fscache-export-fscache_put_volume-and-add-fscache_try_get_volume.patch +cachefiles-fix-slab-use-after-free-in-fscache_withdraw_volume.patch +cachefiles-fix-slab-use-after-free-in-cachefiles_withdraw_cookie.patch