Re: [PATCH v5 08/21] nfsd: use RCU to protect fi_deleg_file
From: Chuck Lever
Date: Mon Jun 08 2026 - 13:06:24 EST
On Fri, May 22, 2026, at 3:42 PM, Jeff Layton wrote:
> fi_deleg_file can be NULLed by put_deleg_file() when fi_delegees drops
> to zero during delegation teardown (e.g. DELEGRETURN). Concurrent
> accesses from workqueue callbacks -- such as CB_NOTIFY -- can
> dereference a NULL pointer if they race with this teardown.
> diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
> index 3efc53f0dde6..bd0517dfe881 100644
> --- a/fs/nfsd/nfs4state.c
> +++ b/fs/nfsd/nfs4state.c
> @@ -1212,7 +1212,9 @@ static void put_deleg_file(struct nfs4_file *fp)
>
> spin_lock(&fp->fi_lock);
> if (--fp->fi_delegees == 0) {
> - swap(nf, fp->fi_deleg_file);
> + nf = rcu_dereference_protected(fp->fi_deleg_file,
> + lockdep_is_held(&fp->fi_lock));
> + rcu_assign_pointer(fp->fi_deleg_file, NULL);
Nit: For consistency, the above could be
RCU_INIT_POINTER(fp->fi_deleg_file, NULL);
> swap(rnf, fp->fi_rdeleg_file);
> }
> spin_unlock(&fp->fi_lock);
> @@ -9722,7 +9729,7 @@ nfsd_get_dir_deleg(struct nfsd4_compound_state
> *cstate,
> }
>
> /* Something failed. Drop the lease and clean up the stid */
> - kernel_setlease(fp->fi_deleg_file->nf_file, F_UNLCK, NULL, (void **)&dp);
> + kernel_setlease(nf->nf_file, F_UNLCK, NULL, (void **)&dp);
> out_put_stid:
> nfs4_put_stid(&dp->dl_stid);
> out_delegees:
We might want:
kernel_setlease(rcu_dereference_protected(fp->fi_deleg_file, 1)->nf_file,
F_UNLCK, NULL, (void **)&dp);
instead, to avoid the Sashiko-reported UAF finding.
--
Chuck Lever