[PATCH net-next v3 3/4] udp: Preserve destination address info after abort
From: Jordan Rife <hidden>
Date: 2026-03-30 21:57:15
Also in:
bpf
Subsystem:
networking [general], the rest, user datagram protocol (udp) · Maintainers:
"David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds, Willem de Bruijn
For explicit disconnections using connect(AF_UNSPEC) behavior remains unchanged while udp_abort now avoids clearing inet_daddr and inet_dport. This is safe to do without changing behavior elsewhere, since lookups only consult these fields if the socket is currently connected (sk_state == TCP_ESTABLISHED). The behavior of getpeername doesn't change w.r.t. aborted sockets, since it returns -ENOTCONN as long as sk_state == TCP_CLOSE. Behavior of BPF socket iterators and /proc/net/udp /do/ change with both now seeing the non-cleared daddr+dport pair after an abort. Behavior of BPF socket lookup helpers which invoke __udp*_lib_lookup don't change, since the result of compute_score should be the same as before. Reported-by: Yusuke Suzuki <redacted> Signed-off-by: Jordan Rife <redacted> --- net/ipv4/udp.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 6e5ba2ce9314..043496a249ca 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c@@ -2207,7 +2207,7 @@ static int udp_connect(struct sock *sk, struct sockaddr_unsized *uaddr, return res; } -int __udp_disconnect(struct sock *sk, int flags) +static int ___udp_disconnect(struct sock *sk, int flags, bool clear_dest) { struct inet_sock *inet = inet_sk(sk); /*
@@ -2215,8 +2215,10 @@ int __udp_disconnect(struct sock *sk, int flags) */ sk->sk_state = TCP_CLOSE; - inet->inet_daddr = 0; - inet->inet_dport = 0; + if (clear_dest) { + inet->inet_daddr = 0; + inet->inet_dport = 0; + } sock_rps_reset_rxhash(sk); sk->sk_bound_dev_if = 0; if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK)) {
@@ -2233,14 +2235,19 @@ int __udp_disconnect(struct sock *sk, int flags) sk_dst_reset(sk); return 0; } + +int __udp_disconnect(struct sock *sk, int flags) +{ + return ___udp_disconnect(sk, flags, true); +} EXPORT_SYMBOL(__udp_disconnect); -static int udp_disconnect_unhash4(struct sock *sk, int flags) +static int udp_disconnect_unhash4(struct sock *sk, int flags, bool clear_dest) { struct udp_table *udptable = udp_get_table_prot(sk); udp_unhash4(udptable, sk); - __udp_disconnect(sk, flags); + ___udp_disconnect(sk, flags, clear_dest); return 0; }
@@ -2248,7 +2255,7 @@ static int udp_disconnect_unhash4(struct sock *sk, int flags) int udp_disconnect(struct sock *sk, int flags) { lock_sock(sk); - udp_disconnect_unhash4(sk, flags); + udp_disconnect_unhash4(sk, flags, true); release_sock(sk); return 0; }
@@ -3264,7 +3271,7 @@ int udp_abort(struct sock *sk, int err) sk->sk_err = err; sk_error_report(sk); - udp_disconnect_unhash4(sk, 0); + udp_disconnect_unhash4(sk, 0, false); out: if (!has_current_bpf_ctx())
--
2.53.0.1118.gaef5881109-goog