Re: 'refcount_t: addition on 0; use-after-free.' and 'refcount_t: underflow; use-after-free.' at fetching files via nfs (Talos II, kernel 6.13.8)

From: Trond Myklebust
Date: Thu Mar 27 2025 - 19:27:11 EST


On Thu, 2025-03-27 at 23:46 +0100, Erhard Furtner wrote:
> Greetings!
>
> Noticed that nfs 'refcount_t: addition on 0; use-after-free.' and
> 'refcount_t: underflow; use-after-free.' after some hours of building
> packages on my Talos II. It fetches the source tarballs from my other
> system via a shared nfs 4 partition.
>
> [...]
> ------------[ cut here ]------------
> refcount_t: addition on 0; use-after-free.
> WARNING: CPU: 33 PID: 50221 at lib/refcount.c:25
> refcount_warn_saturate+0x194/0x230
> Modules linked in: md5 md5_ppc sha512_generic cmac cifs cifs_arc4
> nls_ucs2_utils cifs_md4 rpcsec_gss_krb5 auth_rpcgss nfsv4
> dns_resolver nfs lockd grace sunrpc af_packet input_leds evdev
> cfg80211 rfkill hid_generic usbhid hid radeon xhci_pci
> drm_suballoc_helper xhci_hcd i2c_algo_bit backlight drm_ttm_helper
> ctr ofpart ttm xts cbc aes_generic libaes usbcore powernv_flash
> vmx_crypto drm_display_helper gf128mul ibmpowernv mtd at24 usb_common
> hwmon regmap_i2c opal_prd zram powernv_cpufreq loop fuse dm_mod
> configfs
> CPU: 33 UID: 250 PID: 50221 Comm: emerge Tainted: G                T 
> 6.13.8-gentoo-P9 #1
> Tainted: [T]=RANDSTRUCT
> Hardware name: T2P9D01 REV 1.01 POWER9 0x4e1202 opal:skiboot-bc106a0
> PowerNV
> NIP:  c000000000818de4 LR: c000000000818de0 CTR: 0000000000000000
> REGS: c0000000c5d4b770 TRAP: 0700   Tainted: G                T  
> (6.13.8-gentoo-P9)
> MSR:  900000000082b032 <SF,HV,VSX,EE,FP,ME,IR,DR,RI>  CR: 44044222 
> XER: 0000000a
> CFAR: c000000000134398 IRQMASK: 0
> GPR00: c000000000818de0 c0000000c5d4ba10 c00000000112f100
> 000000000000002a
> GPR04: 00000000fffeffff c0000000c5d4b7b8 c0000000c5d4b7b0
> 00000007fd0b8000
> GPR08: 0000000000000027 c0000007ff1bc210 0000000000000001
> 0000000044044222
> GPR12: c0002007fae88228 c0000007fffe9600 ffffffffffffffff
> 0000000000000001
> GPR16: 00003fff8ed79c40 0000000000000000 00003fff8ddf4bd0
> 00003fff8ed79c38
> GPR20: 00003fff8ed79c40 00003fff8eb92840 00003fff8ed79c48
> 00000000000000a7
> GPR24: 00003fff8ea50f20 00003fffcd0853b8 0000000000000001
> c000000581df4878
> GPR28: c000000021935088 c0000000cbb2f7a0 c0000004c0c374e8
> c0000000cbb2f740
> NIP [c000000000818de4] refcount_warn_saturate+0x194/0x230
> LR [c000000000818de0] refcount_warn_saturate+0x190/0x230
> Call Trace:
> [c0000000c5d4ba10] [c000000000818de0]
> refcount_warn_saturate+0x190/0x230 (unreliable)
> [c0000000c5d4ba70] [c00800000e1ec578]
> nfs_start_delegation_return_locked+0x140/0x160 [nfsv4]
> [c0000000c5d4bab0] [c00800000e1ee20c]
> nfs4_inode_return_delegation+0x24/0xf0 [nfsv4]
> [c0000000c5d4bae0] [c00800000c9ad088] nfs_complete_unlink+0x80/0x250
> [nfs]
> [c0000000c5d4bb30] [c00800000c9955bc] nfs_dentry_iput+0x54/0xe0 [nfs]
> [c0000000c5d4bb60] [c000000000488a98] dentry_unlink_inode+0xe8/0x1e0
> [c0000000c5d4bb90] [c0000000004898f0] __dentry_kill+0xb0/0x280
> [c0000000c5d4bbd0] [c000000000489bf8] dput+0x138/0x290
> [c0000000c5d4bc10] [c00000000045efe0] __fput+0x170/0x3c0
> [c0000000c5d4bc60] [c000000000458c28] sys_close+0x48/0xa0
> [c0000000c5d4bc90] [c000000000029204]
> system_call_exception+0x1a4/0x370
> [c0000000c5d4be50] [c00000000000c270]
> system_call_vectored_common+0xf0/0x280

Does the following patch fix the issue for you?

Cheers
Trond

8<---------------------------------------------------------------
From 6084ce26e633c17115a692120ceaa956487dd325 Mon Sep 17 00:00:00 2001
Message-ID: <6084ce26e633c17115a692120ceaa956487dd325.1743117804.git.trond.myklebust@xxxxxxxxxxxxxxx>
From: Trond Myklebust <trond.myklebust@xxxxxxxxxxxxxxx>
Date: Thu, 27 Mar 2025 19:20:53 -0400
Subject: [PATCH] NFSv4: Check for delegation validity in
nfs_start_delegation_return_locked()

Check that the delegation is still attached after taking the spin lock
in nfs_start_delegation_return_locked().

Signed-off-by: Trond Myklebust <trond.myklebust@xxxxxxxxxxxxxxx>
---
fs/nfs/delegation.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 325ba0663a6d..8bdbc4dca89c 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -307,7 +307,8 @@ nfs_start_delegation_return_locked(struct nfs_inode *nfsi)
if (delegation == NULL)
goto out;
spin_lock(&delegation->lock);
- if (!test_and_set_bit(NFS_DELEGATION_RETURNING, &delegation->flags)) {
+ if (delegation->inode &&
+ !test_and_set_bit(NFS_DELEGATION_RETURNING, &delegation->flags)) {
clear_bit(NFS_DELEGATION_RETURN_DELAYED, &delegation->flags);
/* Refcount matched in nfs_end_delegation_return() */
ret = nfs_get_delegation(delegation);
--
2.49.0


--
Trond Myklebust
Linux NFS client maintainer, Hammerspace
trond.myklebust@xxxxxxxxxxxxxxx