[PATCH v2 05/10] nfsd: check client ownership when cancelling a copy-notify stateid
From: Jeff Layton
Date: Thu Jul 09 2026 - 14:59:39 EST
On the OFFLOAD_CANCEL path (clp != NULL), manage_cpntf_state() freed the
target cpntf state without checking ownership. The lookup key
st->si_opaque.so_id is allocated cyclically (guessable) and the embedded
clientid is the fixed per-net nn->s2s_cp_cl_id, so any authenticated
NFSv4.2 client could cancel and free another client's copy-notify
stateid.
Compare the creating clientid recorded in state->cp_p_clid against the
requesting client's cl_clientid and return nfserr_bad_stateid on a
mismatch instead of freeing the entry.
Fixes: ce0887ac96d3 ("NFSD add nfs4 inter ssc to nfsd4_copy")
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx>
---
fs/nfsd/nfs4state.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 1ef015cbc055..76c0e08711df 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -7916,10 +7916,22 @@ __be32 manage_cpntf_state(struct nfsd_net *nn, stateid_t *st,
state = NULL;
goto unlock;
}
- if (!clp)
+ if (!clp) {
refcount_inc(&state->cp_stateid.cs_count);
- else
+ } else if (memcmp(&clp->cl_clientid, &state->cp_p_clid,
+ sizeof(clientid_t))) {
+ /*
+ * OFFLOAD_CANCEL: only the client that created the
+ * copy-notify stateid may cancel it. so_id values are
+ * cyclic and guessable, so without this check any
+ * authenticated client could free another client's
+ * cpntf state.
+ */
+ state = NULL;
+ goto unlock;
+ } else {
_free_cpntf_state_locked(nn, state);
+ }
}
unlock:
spin_unlock(&nn->s2s_cp_lock);
--
2.55.0