From: Greg Kroah-Hartman Date: Fri, 6 Dec 2024 12:36:15 +0000 (+0100) Subject: 5.4-stable patches X-Git-Tag: v6.6.64~19 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4421118d59fa3e15ad14c7a91a0f9262a49af0ee;p=thirdparty%2Fkernel%2Fstable-queue.git 5.4-stable patches added patches: dm-thin-add-missing-destroy_work_on_stack.patch nfsd-fix-nfs4_openowner-leak-when-concurrent-nfsd4_open-occur.patch nfsd-make-sure-exp-active-before-svc_export_show.patch --- diff --git a/queue-5.4/dm-thin-add-missing-destroy_work_on_stack.patch b/queue-5.4/dm-thin-add-missing-destroy_work_on_stack.patch new file mode 100644 index 00000000000..421c32cf5f6 --- /dev/null +++ b/queue-5.4/dm-thin-add-missing-destroy_work_on_stack.patch @@ -0,0 +1,31 @@ +From e74fa2447bf9ed03d085b6d91f0256cc1b53f1a8 Mon Sep 17 00:00:00 2001 +From: Yuan Can +Date: Wed, 6 Nov 2024 09:03:12 +0800 +Subject: dm thin: Add missing destroy_work_on_stack() + +From: Yuan Can + +commit e74fa2447bf9ed03d085b6d91f0256cc1b53f1a8 upstream. + +This commit add missed destroy_work_on_stack() operations for pw->worker in +pool_work_wait(). + +Fixes: e7a3e871d895 ("dm thin: cleanup noflush_work to use a proper completion") +Cc: stable@vger.kernel.org +Signed-off-by: Yuan Can +Signed-off-by: Mikulas Patocka +Signed-off-by: Greg Kroah-Hartman +--- + drivers/md/dm-thin.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/md/dm-thin.c ++++ b/drivers/md/dm-thin.c +@@ -2477,6 +2477,7 @@ static void pool_work_wait(struct pool_w + init_completion(&pw->complete); + queue_work(pool->wq, &pw->worker); + wait_for_completion(&pw->complete); ++ destroy_work_on_stack(&pw->worker); + } + + /*----------------------------------------------------------------*/ diff --git a/queue-5.4/nfsd-fix-nfs4_openowner-leak-when-concurrent-nfsd4_open-occur.patch b/queue-5.4/nfsd-fix-nfs4_openowner-leak-when-concurrent-nfsd4_open-occur.patch new file mode 100644 index 00000000000..40412ae1245 --- /dev/null +++ b/queue-5.4/nfsd-fix-nfs4_openowner-leak-when-concurrent-nfsd4_open-occur.patch @@ -0,0 +1,195 @@ +From 98100e88dd8865999dc6379a3356cd799795fe7b Mon Sep 17 00:00:00 2001 +From: Yang Erkun +Date: Tue, 5 Nov 2024 19:03:14 +0800 +Subject: nfsd: fix nfs4_openowner leak when concurrent nfsd4_open occur + +From: Yang Erkun + +commit 98100e88dd8865999dc6379a3356cd799795fe7b upstream. + +The action force umount(umount -f) will attempt to kill all rpc_task even +umount operation may ultimately fail if some files remain open. +Consequently, if an action attempts to open a file, it can potentially +send two rpc_task to nfs server. + + NFS CLIENT +thread1 thread2 +open("file") +... +nfs4_do_open + _nfs4_do_open + _nfs4_open_and_get_state + _nfs4_proc_open + nfs4_run_open_task + /* rpc_task1 */ + rpc_run_task + rpc_wait_for_completion_task + + umount -f + nfs_umount_begin + rpc_killall_tasks + rpc_signal_task + rpc_task1 been wakeup + and return -512 + _nfs4_do_open // while loop + ... + nfs4_run_open_task + /* rpc_task2 */ + rpc_run_task + rpc_wait_for_completion_task + +While processing an open request, nfsd will first attempt to find or +allocate an nfs4_openowner. If it finds an nfs4_openowner that is not +marked as NFS4_OO_CONFIRMED, this nfs4_openowner will released. Since +two rpc_task can attempt to open the same file simultaneously from the +client to server, and because two instances of nfsd can run +concurrently, this situation can lead to lots of memory leak. +Additionally, when we echo 0 to /proc/fs/nfsd/threads, warning will be +triggered. + + NFS SERVER +nfsd1 nfsd2 echo 0 > /proc/fs/nfsd/threads + +nfsd4_open + nfsd4_process_open1 + find_or_alloc_open_stateowner + // alloc oo1, stateid1 + nfsd4_open + nfsd4_process_open1 + find_or_alloc_open_stateowner + // find oo1, without NFS4_OO_CONFIRMED + release_openowner + unhash_openowner_locked + list_del_init(&oo->oo_perclient) + // cannot find this oo + // from client, LEAK!!! + alloc_stateowner // alloc oo2 + + nfsd4_process_open2 + init_open_stateid + // associate oo1 + // with stateid1, stateid1 LEAK!!! + nfs4_get_vfs_file + // alloc nfsd_file1 and nfsd_file_mark1 + // all LEAK!!! + + nfsd4_process_open2 + ... + + write_threads + ... + nfsd_destroy_serv + nfsd_shutdown_net + nfs4_state_shutdown_net + nfs4_state_destroy_net + destroy_client + __destroy_client + // won't find oo1!!! + nfsd_shutdown_generic + nfsd_file_cache_shutdown + kmem_cache_destroy + for nfsd_file_slab + and nfsd_file_mark_slab + // bark since nfsd_file1 + // and nfsd_file_mark1 + // still alive + +======================================================================= +BUG nfsd_file (Not tainted): Objects remaining in nfsd_file on +__kmem_cache_shutdown() +----------------------------------------------------------------------- + +Slab 0xffd4000004438a80 objects=34 used=1 fp=0xff11000110e2ad28 +flags=0x17ffffc0000240(workingset|head|node=0|zone=2|lastcpupid=0x1fffff) +CPU: 4 UID: 0 PID: 757 Comm: sh Not tainted 6.12.0-rc6+ #19 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS +1.16.1-2.fc37 04/01/2014 +Call Trace: + + dump_stack_lvl+0x53/0x70 + slab_err+0xb0/0xf0 + __kmem_cache_shutdown+0x15c/0x310 + kmem_cache_destroy+0x66/0x160 + nfsd_file_cache_shutdown+0xac/0x210 [nfsd] + nfsd_destroy_serv+0x251/0x2a0 [nfsd] + nfsd_svc+0x125/0x1e0 [nfsd] + write_threads+0x16a/0x2a0 [nfsd] + nfsctl_transaction_write+0x74/0xa0 [nfsd] + vfs_write+0x1ae/0x6d0 + ksys_write+0xc1/0x160 + do_syscall_64+0x5f/0x170 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + +Disabling lock debugging due to kernel taint +Object 0xff11000110e2ac38 @offset=3128 +Allocated in nfsd_file_do_acquire+0x20f/0xa30 [nfsd] age=1635 cpu=3 +pid=800 + nfsd_file_do_acquire+0x20f/0xa30 [nfsd] + nfsd_file_acquire_opened+0x5f/0x90 [nfsd] + nfs4_get_vfs_file+0x4c9/0x570 [nfsd] + nfsd4_process_open2+0x713/0x1070 [nfsd] + nfsd4_open+0x74b/0x8b0 [nfsd] + nfsd4_proc_compound+0x70b/0xc20 [nfsd] + nfsd_dispatch+0x1b4/0x3a0 [nfsd] + svc_process_common+0x5b8/0xc50 [sunrpc] + svc_process+0x2ab/0x3b0 [sunrpc] + svc_handle_xprt+0x681/0xa20 [sunrpc] + nfsd+0x183/0x220 [nfsd] + kthread+0x199/0x1e0 + ret_from_fork+0x31/0x60 + ret_from_fork_asm+0x1a/0x30 + +Add nfs4_openowner_unhashed to help found unhashed nfs4_openowner, and +break nfsd4_open process to fix this problem. + +Cc: stable@vger.kernel.org # v5.4+ +Reviewed-by: Jeff Layton +Signed-off-by: Yang Erkun +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + fs/nfsd/nfs4state.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +--- a/fs/nfsd/nfs4state.c ++++ b/fs/nfsd/nfs4state.c +@@ -1456,6 +1456,14 @@ static void release_open_stateid(struct + free_ol_stateid_reaplist(&reaplist); + } + ++static bool nfs4_openowner_unhashed(struct nfs4_openowner *oo) ++{ ++ lockdep_assert_held(&oo->oo_owner.so_client->cl_lock); ++ ++ return list_empty(&oo->oo_owner.so_strhash) && ++ list_empty(&oo->oo_perclient); ++} ++ + static void unhash_openowner_locked(struct nfs4_openowner *oo) + { + struct nfs4_client *clp = oo->oo_owner.so_client; +@@ -4266,6 +4274,12 @@ retry: + spin_lock(&oo->oo_owner.so_client->cl_lock); + spin_lock(&fp->fi_lock); + ++ if (nfs4_openowner_unhashed(oo)) { ++ mutex_unlock(&stp->st_mutex); ++ stp = NULL; ++ goto out_unlock; ++ } ++ + retstp = nfsd4_find_existing_open(fp, open); + if (retstp) + goto out_unlock; +@@ -5077,6 +5091,11 @@ nfsd4_process_open2(struct svc_rqst *rqs + + if (!stp) { + stp = init_open_stateid(fp, open); ++ if (!stp) { ++ status = nfserr_jukebox; ++ goto out; ++ } ++ + if (!open->op_stp) + new_stp = true; + } diff --git a/queue-5.4/nfsd-make-sure-exp-active-before-svc_export_show.patch b/queue-5.4/nfsd-make-sure-exp-active-before-svc_export_show.patch new file mode 100644 index 00000000000..9134eee734e --- /dev/null +++ b/queue-5.4/nfsd-make-sure-exp-active-before-svc_export_show.patch @@ -0,0 +1,60 @@ +From be8f982c369c965faffa198b46060f8853e0f1f0 Mon Sep 17 00:00:00 2001 +From: Yang Erkun +Date: Mon, 21 Oct 2024 22:23:41 +0800 +Subject: nfsd: make sure exp active before svc_export_show + +From: Yang Erkun + +commit be8f982c369c965faffa198b46060f8853e0f1f0 upstream. + +The function `e_show` was called with protection from RCU. This only +ensures that `exp` will not be freed. Therefore, the reference count for +`exp` can drop to zero, which will trigger a refcount use-after-free +warning when `exp_get` is called. To resolve this issue, use +`cache_get_rcu` to ensure that `exp` remains active. + +------------[ cut here ]------------ +refcount_t: addition on 0; use-after-free. +WARNING: CPU: 3 PID: 819 at lib/refcount.c:25 +refcount_warn_saturate+0xb1/0x120 +CPU: 3 UID: 0 PID: 819 Comm: cat Not tainted 6.12.0-rc3+ #1 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS +1.16.1-2.fc37 04/01/2014 +RIP: 0010:refcount_warn_saturate+0xb1/0x120 +... +Call Trace: + + e_show+0x20b/0x230 [nfsd] + seq_read_iter+0x589/0x770 + seq_read+0x1e5/0x270 + vfs_read+0x125/0x530 + ksys_read+0xc1/0x160 + do_syscall_64+0x5f/0x170 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + +Fixes: bf18f163e89c ("NFSD: Using exp_get for export getting") +Cc: stable@vger.kernel.org # 4.20+ +Signed-off-by: Yang Erkun +Reviewed-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + fs/nfsd/export.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/fs/nfsd/export.c ++++ b/fs/nfsd/export.c +@@ -1223,9 +1223,12 @@ static int e_show(struct seq_file *m, vo + return 0; + } + +- exp_get(exp); ++ if (!cache_get_rcu(&exp->h)) ++ return 0; ++ + if (cache_check(cd, &exp->h, NULL)) + return 0; ++ + exp_put(exp); + return svc_export_show(m, cd, cp); + } diff --git a/queue-5.4/series b/queue-5.4/series index ccf6ea1527e..5badb470ac6 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -214,3 +214,6 @@ clk-qcom-gcc-qcs404-fix-initial-rate-of-gpll3.patch ad7780-fix-division-by-zero-in-ad7780_write_raw.patch util_macros.h-fix-rework-find_closest-macros.patch i3c-master-fix-miss-free-init_dyn_addr-at-i3c_master_put_i3c_addrs.patch +dm-thin-add-missing-destroy_work_on_stack.patch +nfsd-make-sure-exp-active-before-svc_export_show.patch +nfsd-fix-nfs4_openowner-leak-when-concurrent-nfsd4_open-occur.patch