mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 03:04:51 +01:00
udp: Unhash auto-bound connected sk from 4-tuple hash table when disconnected.
Let's say we bind() an UDP socket to the wildcard address with a
non-zero port, connect() it to an address, and disconnect it from
the address.
bind() sets SOCK_BINDPORT_LOCK on sk->sk_userlocks (but not
SOCK_BINDADDR_LOCK), and connect() calls udp_lib_hash4() to put
the socket into the 4-tuple hash table.
Then, __udp_disconnect() calls sk->sk_prot->rehash(sk).
It computes a new hash based on the wildcard address and moves
the socket to a new slot in the 4-tuple hash table, leaving a
garbage in the chain that no packet hits.
Let's remove such a socket from 4-tuple hash table when disconnected.
Note that udp_sk(sk)->udp_portaddr_hash needs to be udpated after
udp_hash4_dec(hslot2) in udp_unhash4().
Fixes: 78c91ae2c6 ("ipv4/udp: Add 4-tuple hash for connected socket")
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20260227035547.3321327-1-kuniyu@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
dabffd0854
commit
6996a2d2d0
1 changed files with 14 additions and 9 deletions
|
|
@ -2287,7 +2287,6 @@ void udp_lib_rehash(struct sock *sk, u16 newhash, u16 newhash4)
|
|||
udp_sk(sk)->udp_port_hash);
|
||||
hslot2 = udp_hashslot2(udptable, udp_sk(sk)->udp_portaddr_hash);
|
||||
nhslot2 = udp_hashslot2(udptable, newhash);
|
||||
udp_sk(sk)->udp_portaddr_hash = newhash;
|
||||
|
||||
if (hslot2 != nhslot2 ||
|
||||
rcu_access_pointer(sk->sk_reuseport_cb)) {
|
||||
|
|
@ -2321,19 +2320,25 @@ void udp_lib_rehash(struct sock *sk, u16 newhash, u16 newhash4)
|
|||
if (udp_hashed4(sk)) {
|
||||
spin_lock_bh(&hslot->lock);
|
||||
|
||||
udp_rehash4(udptable, sk, newhash4);
|
||||
if (hslot2 != nhslot2) {
|
||||
spin_lock(&hslot2->lock);
|
||||
udp_hash4_dec(hslot2);
|
||||
spin_unlock(&hslot2->lock);
|
||||
if (inet_rcv_saddr_any(sk)) {
|
||||
udp_unhash4(udptable, sk);
|
||||
} else {
|
||||
udp_rehash4(udptable, sk, newhash4);
|
||||
if (hslot2 != nhslot2) {
|
||||
spin_lock(&hslot2->lock);
|
||||
udp_hash4_dec(hslot2);
|
||||
spin_unlock(&hslot2->lock);
|
||||
|
||||
spin_lock(&nhslot2->lock);
|
||||
udp_hash4_inc(nhslot2);
|
||||
spin_unlock(&nhslot2->lock);
|
||||
spin_lock(&nhslot2->lock);
|
||||
udp_hash4_inc(nhslot2);
|
||||
spin_unlock(&nhslot2->lock);
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_bh(&hslot->lock);
|
||||
}
|
||||
|
||||
udp_sk(sk)->udp_portaddr_hash = newhash;
|
||||
}
|
||||
}
|
||||
EXPORT_IPV6_MOD(udp_lib_rehash);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue