]> git.itanic.dy.fi Git - linux-stable/commit
tcp: Fix NEW_SYN_RECV handling in inet_twsk_purge()
authorEric Dumazet <edumazet@google.com>
Fri, 8 Mar 2024 20:01:21 +0000 (12:01 -0800)
committerSasha Levin <sashal@kernel.org>
Tue, 26 Mar 2024 22:17:31 +0000 (18:17 -0400)
commit8862534197adf6c86cb18bf4928b6ee052792f8b
treeb21964977283e33e82644d1c4249751990d85d21
parent3a21028f11f7b2d9bec9fddab55722542ed3d78e
tcp: Fix NEW_SYN_RECV handling in inet_twsk_purge()

[ Upstream commit 1c4e97dd2d3c9a3e84f7e26346aa39bc426d3249 ]

inet_twsk_purge() uses rcu to find TIME_WAIT and NEW_SYN_RECV
objects to purge.

These objects use SLAB_TYPESAFE_BY_RCU semantic and need special
care. We need to use refcount_inc_not_zero(&sk->sk_refcnt).

Reuse the existing correct logic I wrote for TIME_WAIT,
because both structures have common locations for
sk_state, sk_family, and netns pointer.

If after the refcount_inc_not_zero() the object fields longer match
the keys, use sock_gen_put(sk) to release the refcount.

Then we can call inet_twsk_deschedule_put() for TIME_WAIT,
inet_csk_reqsk_queue_drop_and_put() for NEW_SYN_RECV sockets,
with BH disabled.

Then we need to restart the loop because we had drop rcu_read_lock().

Fixes: 740ea3c4a0b2 ("tcp: Clean up kernel listener's reqsk in inet_twsk_purge()")
Link: https://lore.kernel.org/netdev/CANn89iLvFuuihCtt9PME2uS1WJATnf5fKjDToa1WzVnRzHnPfg@mail.gmail.com/T/#u
Signed-off-by: Eric Dumazet <edumazet@google.com>
Link: https://lore.kernel.org/r/20240308200122.64357-2-kuniyu@amazon.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/ipv4/inet_timewait_sock.c