nfsd: set SC_STATUS_FREED in nfsd4_drop_revoked_stid for delegations

nfsd4_drop_revoked_stid() handles FREE_STATEID for admin-revoked
delegations but does not set SC_STATUS_FREED before releasing cl_lock.
revoke_delegation() uses this flag to detect whether FREE_STATEID has
already processed the delegation -- without it, the freed delegation is
added to cl_revoked via list_add(), producing a use-after-free when
cl_revoked is later traversed in __destroy_client().

The SC_STATUS_REVOKED path in nfsd4_free_stateid() (line 7983) already
sets SC_STATUS_FREED correctly. Apply the same pattern to the
SC_STATUS_ADMIN_REVOKED path in nfsd4_drop_revoked_stid().

Fixes: 8dd91e8d31 ("nfsd: fix race between laundromat and free_stateid")
Cc: stable@vger.kernel.org
Signed-off-by: Zhenghang Xiao <kipreyyy@gmail.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Link: https://patch.msgid.link/20260526104554.46262-1-kipreyyy@gmail.com
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
This commit is contained in:
Zhenghang Xiao
2026-08-03 09:14:35 -04:00
committed by Chuck Lever
parent 5859cc01fe
commit 650d370cfb
+1
View File
@@ -5172,6 +5172,7 @@ static void nfsd4_drop_revoked_stid(struct nfs4_stid *s)
case SC_TYPE_DELEG:
dp = delegstateid(s);
list_del_init(&dp->dl_recall_lru);
s->sc_status |= SC_STATUS_FREED;
spin_unlock(&cl->cl_lock);
nfs4_put_stid(s);
break;