diff mbox series

[2/3] SUNRPC: make sure cache entry active before cache_show

Message ID 20241021142343.3857891-3-yangerkun@huaweicloud.com (mailing list archive)
State New
Headers show
Series bugfix for c_show/e_show | expand

Commit Message

yangerkun Oct. 21, 2024, 2:23 p.m. UTC
From: Yang Erkun <yangerkun@huawei.com>

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

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Yang Erkun <yangerkun@huawei.com>
---
 net/sunrpc/cache.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

Comments

Chuck Lever Oct. 21, 2024, 5:11 p.m. UTC | #1
On Mon, Oct 21, 2024 at 10:23:42PM +0800, Yang Erkun wrote:
> From: Yang Erkun <yangerkun@huawei.com>
> 
> 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
> 
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")

Instead, how about:

Cc: stable@vger.kernel.org # v4.20+


> Signed-off-by: Yang Erkun <yangerkun@huawei.com>
> ---
>  net/sunrpc/cache.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
> index 1bd3e531b0e0..059f6ef1ad18 100644
> --- a/net/sunrpc/cache.c
> +++ b/net/sunrpc/cache.c
> @@ -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, "# ");
> -- 
> 2.39.2
>
diff mbox series

Patch

diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index 1bd3e531b0e0..059f6ef1ad18 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -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, "# ");