mirror of
https://github.com/torvalds/linux.git
synced 2026-09-24 06:24:02 +02:00
NFSD: Prevent client use-after-free during NFSv4.0 revoked-state cleanup
nfs40_clean_admin_revoked() takes a stateid reference under
clp->cl_lock, drops nn->client_lock, and calls
nfsd4_drop_revoked_stid(), which dereferences the stateid's client
through s->sc_client->cl_lock. The stateid reference does not pin the
client, so a teardown racing the dropped lock can free the client
while nfsd4_drop_revoked_stid() is still using it.
This cleanup runs from the laundromat, so a periodic sweep can race
force_expire_client() driven by a write to the clients/<id>/ctl file.
Skip a client that is already expiring and otherwise pin it with
cl_rpc_users under client_lock before dropping the lock, matching
nfsd4_revoke_states().
Fixes: d688d8585e ("nfsd: allow admin-revoked NFSv4.0 state to be freed.")
Cc: stable@vger.kernel.org
Reviewed-by: NeilBrown <neil@brown.name>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Link: https://patch.msgid.link/20260709-cel-v4-5-1d519d9be0cb@kernel.org
Signed-off-by: Chuck Lever <cel@kernel.org>
This commit is contained in:
parent
2108de5356
commit
7b4f8a1586
|
|
@ -7452,16 +7452,22 @@ static void nfs40_clean_admin_revoked(struct nfsd_net *nn,
|
|||
|
||||
if (atomic_read(&clp->cl_admin_revoked) == 0)
|
||||
continue;
|
||||
if (is_client_expired(clp))
|
||||
continue;
|
||||
|
||||
spin_lock(&clp->cl_lock);
|
||||
idr_for_each_entry_ul(&clp->cl_stateids, stid, tmp, id)
|
||||
if (stid->sc_status & SC_STATUS_ADMIN_REVOKED) {
|
||||
refcount_inc(&stid->sc_count);
|
||||
atomic_inc(&clp->cl_rpc_users);
|
||||
spin_unlock(&nn->client_lock);
|
||||
/* this function drops ->cl_lock */
|
||||
nfsd4_drop_revoked_stid(stid);
|
||||
nfs4_put_stid(stid);
|
||||
spin_lock(&nn->client_lock);
|
||||
if (atomic_dec_and_test(&clp->cl_rpc_users) &&
|
||||
is_client_expired(clp))
|
||||
wake_up_all(&expiry_wq);
|
||||
goto retry;
|
||||
}
|
||||
spin_unlock(&clp->cl_lock);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user