summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorYang Erkun <yangerkun@huawei.com>2024-10-21 22:23:41 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-12-09 10:33:08 +0100
commit1cecfdbc6bfc89c516d286884c7f29267b95de2b (patch)
tree0aff588f9286f97c2ed643702aa4800fc5448676 /fs
parent2eb355346c5a2d767dfb21b3d1c4ea2d56cedb63 (diff)
downloadlinux-1cecfdbc6bfc89c516d286884c7f29267b95de2b.tar.gz
linux-1cecfdbc6bfc89c516d286884c7f29267b95de2b.tar.bz2
linux-1cecfdbc6bfc89c516d286884c7f29267b95de2b.zip
nfsd: make sure exp active before svc_export_show
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: <TASK> 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 <yangerkun@huawei.com> Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfsd/export.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 2964bdae6392..d4d3ec58047e 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -1385,9 +1385,12 @@ static int e_show(struct seq_file *m, void *p)
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);
}