[PATCH net v2 6/7] net/handshake: Close the submit-side sock_hold race
Chuck Lever <[email protected]> Thu, 21 May 2026 10:47:12 -0400
| Newsgroups | dev.linux.lists.kernel-tls-handshake,org.infradead.lists.linux-nvme,org.kernel.vger.netdev |
|---|---|
| Message-ID | <[email protected]> |
From: Chuck Lever <[email protected]> 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. Submit's pinning is strictly the file reference acquired earlier in the function, and the lifetime story is contained in a single get_file()/fput() pair. Fixes: 3b3009ea8abb ("net/handshake: Create a NETLINK service for handling handshake requests") Signed-off-by: Chuck Lever <[email protected]> Reviewed-by: Hannes Reinecke <[email protected]> --- net/handshake/request.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/net/handshake/request.c b/net/handshake/request.c index d24b55af1a0a..1c669c1602b5 100644 --- a/net/handshake/request.c +++ b/net/handshake/request.c @@ -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; @@ -335,9 +328,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); } } @@ -385,8 +375,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; } -- 2.54.0