mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs.git
synced 2026-10-30 13:52:50 +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 <[email protected]>
Reviewed-by: Eric Dumazet <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Jakub Kicinski <[email protected]>
This commit is contained in:
1 parent
dabffd0854
commit
6996a2d2d0
1 file changed
+14
-9
+14
-9
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user