]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
SUNRPC: make sure cache entry active before cache_show
authorYang Erkun <yangerkun@huawei.com>
Mon, 21 Oct 2024 14:23:42 +0000 (22:23 +0800)
committerChuck Lever <chuck.lever@oracle.com>
Tue, 19 Nov 2024 01:23:05 +0000 (20:23 -0500)
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>
net/sunrpc/cache.c

index 1bd3e531b0e09002a64f20244e05afc186875157..059f6ef1ad1898de24f8eb5614b7545c2fa4dcf1 100644 (file)
@@ -1427,7 +1427,9 @@ static int c_show(struct seq_file *m, void *p)
                seq_printf(m, "# expiry=%lld refcnt=%d flags=%lx\n",
                           convert_to_wallclock(cp->expiry_time),
                           kref_read(&cp->ref), cp->flags);
-       cache_get(cp);
+       if (!cache_get_rcu(cp))
+               return 0;
+
        if (cache_check(cd, cp, NULL))
                /* cache_check does a cache_put on failure */
                seq_puts(m, "# ");