[PATCH] nfsd: don't access freed memory when cannot grant a write delegation

From: Haruka Kuze

Date: Sun Nov 01 2026 - 16:22:20 EST


From: Haruka Kuze <harukak@xxxxxxxxxxx>

nfs4_open_delegation() hashes the delegation before the call to
nfsd4_add_rdaccess_to_wrdeleg() and nfs4_delegation_stat(), both of which
can sleep, and it calls destroy_delegation() from the error path after
dropping the caller's reference.

Moreover, a DELEGRETURN from same client can unhash the delegation and
drop the hash reference in this window, so nfs4_put_stid() frees it and
destroy_delegation() then reads freed memory.

Call destroy_delegation() before dropping the caller reference.

Fixes: c5967721e106 ("NFSD: handle GETATTR conflict with write delegation")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Haruka Kuze <harukak@xxxxxxxxxxx>
---
fs/nfsd/nfs4state.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 1de6c6d757c3..b13d05fe8993 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -7300,8 +7300,8 @@ nfs4_open_delegation(struct svc_rqst *rqstp, struct nfsd4_open *open,
f = rcu_dereference_protected(dp->dl_stid.sc_file->fi_deleg_file, 1)->nf_file;
if (!nfsd4_add_rdaccess_to_wrdeleg(rqstp, open, fh, stp) ||
!nfs4_delegation_stat(dp, currentfh, &stat)) {
- nfs4_put_stid(&dp->dl_stid);
destroy_delegation(dp);
+ nfs4_put_stid(&dp->dl_stid);
goto out_no_deleg;
}
open->op_delegate_type = deleg_ts ? OPEN_DELEGATE_WRITE_ATTRS_DELEG :
--
2.55.0