mirror of
https://github.com/torvalds/linux.git
synced 2026-06-01 19:13:47 +02:00
net/handshake: Close the submit-side sock_hold race
handshake_req_submit() publishes the request via
handshake_req_hash_add() and __add_pending_locked(), drops
hn_lock, and calls handshake_genl_notify() (which can sleep)
before taking sock_hold() on req->hr_sk. A fast tlshd ACCEPT
followed by DONE can drive handshake_complete()'s sock_put()
into the window between the spin_unlock and the late
sock_hold(); on a system where the consumer's fd held the
only sk reference, the late sock_hold() then operates on an
sk whose refcount has reached zero.
The preceding two patches install an explicit file reference
on struct handshake_req. That file pins sock->file, which
pins the embedded struct socket, which defers inet_release()'s
sock_put(). As long as hr_file is held, sk cannot reach refcount
zero from the consumer side, and the submit-side sock_hold()
with its matching sock_put() calls in handshake_complete() and
handshake_req_cancel() is now redundant.
Drop all three. The file reference already keeps each request's
socket alive, and the lifetime story is contained in a single
get_file()/fput() pair.
Fixes: 3b3009ea8a ("net/handshake: Create a NETLINK service for handling handshake requests")
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Reviewed-by: Hannes Reinecke <hare@kernel.org>
Link: https://patch.msgid.link/20260525-handshake-file-pin-v3-6-66c616906ead@oracle.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
parent
f4251190e5
commit
5da98f55b1
|
|
@ -301,13 +301,6 @@ int handshake_req_submit(struct socket *sock, struct handshake_req *req,
|
|||
goto out_err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pin struct sock so sk_destruct does not run until the
|
||||
* handshake completion path releases it; struct socket is
|
||||
* held separately via hr_file above.
|
||||
*/
|
||||
sock_hold(req->hr_sk);
|
||||
|
||||
trace_handshake_submit(net, req, req->hr_sk);
|
||||
return 0;
|
||||
|
||||
|
|
@ -337,9 +330,6 @@ void handshake_complete(struct handshake_req *req, int status,
|
|||
trace_handshake_complete(net, req, sk, status);
|
||||
req->hr_proto->hp_done(req, status, info);
|
||||
|
||||
/* Handshake request is no longer pending */
|
||||
sock_put(sk);
|
||||
|
||||
fput(file);
|
||||
}
|
||||
}
|
||||
|
|
@ -387,8 +377,6 @@ bool handshake_req_cancel(struct sock *sk)
|
|||
out_true:
|
||||
trace_handshake_cancel(net, req, sk);
|
||||
|
||||
/* Handshake request is no longer pending */
|
||||
sock_put(sk);
|
||||
fput(req->hr_file);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user