Re: [PATCH net 1/7] net/handshake: Drain pending requests at net namespace exit
Hannes Reinecke <[email protected]> Tue, 19 May 2026 09:33:58 +0200
| Newsgroups | dev.linux.lists.kernel-tls-handshake,org.infradead.lists.linux-nvme,org.kernel.vger.netdev |
|---|---|
| Message-ID | <[email protected]> |
On 5/18/26 20:24, Chuck Lever wrote: > From: Chuck Lever <[email protected]> > > The arguments to list_splice_init() in handshake_net_exit() are > reversed. The call moves the local empty "requests" list onto > hn->hn_requests, leaving the local list empty, so the subsequent > drain loop runs zero iterations. Pending handshake requests that > had not yet been accepted are not torn down when the net namespace > is destroyed; each one keeps a reference on a socket file and on > the handshake_req allocation. > > Pass the source and destination in the documented order > (list_splice_init(list, head) moves list onto head) so the pending > list is transferred to the local scratch list and drained through > handshake_complete(). > > Fixing the splice direction exposes a list-corruption race. After > the splice each req->hr_list still has non-empty link pointers, > threading the stack-local scratch list rather than hn_requests. > A concurrent handshake_req_cancel() -- for example, from sunrpc's > TLS timeout on a kernel socket whose netns reference was not > taken -- finds the request through the rhashtable, calls > remove_pending(), and sees !list_empty(&req->hr_list). > __remove_pending_locked() then list_del_init()s an entry off the > scratch list while the drain iterates, corrupting it. The same > call arriving after the drain loop has run list_del() on an > entry hits LIST_POISON instead. > > Have remove_pending() check HANDSHAKE_F_NET_DRAINING under > hn_lock and report not-found when drain is in progress. The > drain has already taken ownership; handshake_complete()'s > existing test_and_set on HANDSHAKE_F_REQ_COMPLETED still > arbitrates between drain and cancel for who calls the consumer's > hp_done. Use list_del_init() rather than list_del() in the drain > so req->hr_list does not carry LIST_POISON after drain releases > the entry. > > Fixes: 3b3009ea8abb ("net/handshake: Create a NETLINK service for handling handshake requests") > Signed-off-by: Chuck Lever <[email protected]> > --- > net/handshake/netlink.c | 4 ++-- > net/handshake/request.c | 3 ++- > 2 files changed, 4 insertions(+), 3 deletions(-) > Reviewed-by: Hannes Reinecke <[email protected]> Cheers, Hannes -- Dr. Hannes Reinecke Kernel Storage Architect [email protected] +49 911 74053 688 SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich