mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2024-12-29 09:13:38 +00:00
SUNRPC: make sure cache entry active before cache_show
The function `c_show` was called with protection from RCU. This only ensures that `cp` will not be freed. Therefore, the reference count for `cp` can drop to zero, which will trigger a refcount use-after-free warning when `cache_get` is called. To resolve this issue, use `cache_get_rcu` to ensure that `cp` remains active. ------------[ cut here ]------------ refcount_t: addition on 0; use-after-free. WARNING: CPU: 7 PID: 822 at lib/refcount.c:25 refcount_warn_saturate+0xb1/0x120 CPU: 7 UID: 0 PID: 822 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> c_show+0x2fc/0x380 [sunrpc] seq_read_iter+0x589/0x770 seq_read+0x1e5/0x270 proc_reg_read+0xe1/0x140 vfs_read+0x125/0x530 ksys_read+0xc1/0x160 do_syscall_64+0x5f/0x170 entry_SYSCALL_64_after_hwframe+0x76/0x7e Cc: stable@vger.kernel.org # v4.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>
This commit is contained in:
parent
be8f982c36
commit
2862eee078
@ -1427,7 +1427,9 @@ static int c_show(struct seq_file *m, void *p)
|
|||||||
seq_printf(m, "# expiry=%lld refcnt=%d flags=%lx\n",
|
seq_printf(m, "# expiry=%lld refcnt=%d flags=%lx\n",
|
||||||
convert_to_wallclock(cp->expiry_time),
|
convert_to_wallclock(cp->expiry_time),
|
||||||
kref_read(&cp->ref), cp->flags);
|
kref_read(&cp->ref), cp->flags);
|
||||||
cache_get(cp);
|
if (!cache_get_rcu(cp))
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (cache_check(cd, cp, NULL))
|
if (cache_check(cd, cp, NULL))
|
||||||
/* cache_check does a cache_put on failure */
|
/* cache_check does a cache_put on failure */
|
||||||
seq_puts(m, "# ");
|
seq_puts(m, "# ");
|
||||||
|
Loading…
Reference in New Issue
Block a user