From: Greg Kroah-Hartman Date: Fri, 14 Mar 2025 12:25:38 +0000 (+0100) Subject: 6.6-stable patches X-Git-Tag: v6.6.84~57 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=42d92a65bc91eee43207be874ba21d5bcf7efebb;p=thirdparty%2Fkernel%2Fstable-queue.git 6.6-stable patches added patches: tcp-fix-forever-orphan-socket-caused-by-tcp_abort.patch tcp-fix-races-in-tcp_abort.patch --- diff --git a/queue-6.6/series b/queue-6.6/series index 8b9c56808a..f7132f2db7 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -3,3 +3,5 @@ sched-isolation-prevent-boot-crash-when-the-boot-cpu-is-nohz_full.patch zram-fix-null-pointer-in-comp_algorithm_show.patch hrtimer-use-and-report-correct-timerslack-values-for-realtime-tasks.patch bpf-use-raw_spinlock_t-in-ringbuf.patch +tcp-fix-races-in-tcp_abort.patch +tcp-fix-forever-orphan-socket-caused-by-tcp_abort.patch diff --git a/queue-6.6/tcp-fix-forever-orphan-socket-caused-by-tcp_abort.patch b/queue-6.6/tcp-fix-forever-orphan-socket-caused-by-tcp_abort.patch new file mode 100644 index 0000000000..6b159e8196 --- /dev/null +++ b/queue-6.6/tcp-fix-forever-orphan-socket-caused-by-tcp_abort.patch @@ -0,0 +1,95 @@ +From bac76cf89816bff06c4ec2f3df97dc34e150a1c4 Mon Sep 17 00:00:00 2001 +From: Xueming Feng +Date: Mon, 26 Aug 2024 18:23:27 +0800 +Subject: tcp: fix forever orphan socket caused by tcp_abort + +From: Xueming Feng + +commit bac76cf89816bff06c4ec2f3df97dc34e150a1c4 upstream. + +We have some problem closing zero-window fin-wait-1 tcp sockets in our +environment. This patch come from the investigation. + +Previously tcp_abort only sends out reset and calls tcp_done when the +socket is not SOCK_DEAD, aka orphan. For orphan socket, it will only +purging the write queue, but not close the socket and left it to the +timer. + +While purging the write queue, tp->packets_out and sk->sk_write_queue +is cleared along the way. However tcp_retransmit_timer have early +return based on !tp->packets_out and tcp_probe_timer have early +return based on !sk->sk_write_queue. + +This caused ICSK_TIME_RETRANS and ICSK_TIME_PROBE0 not being resched +and socket not being killed by the timers, converting a zero-windowed +orphan into a forever orphan. + +This patch removes the SOCK_DEAD check in tcp_abort, making it send +reset to peer and close the socket accordingly. Preventing the +timer-less orphan from happening. + +According to Lorenzo's email in the v1 thread, the check was there to +prevent force-closing the same socket twice. That situation is handled +by testing for TCP_CLOSE inside lock, and returning -ENOENT if it is +already closed. + +The -ENOENT code comes from the associate patch Lorenzo made for +iproute2-ss; link attached below, which also conform to RFC 9293. + +At the end of the patch, tcp_write_queue_purge(sk) is removed because it +was already called in tcp_done_with_error(). + +p.s. This is the same patch with v2. Resent due to mis-labeled "changes +requested" on patchwork.kernel.org. + +Link: https://patchwork.ozlabs.org/project/netdev/patch/1450773094-7978-3-git-send-email-lorenzo@google.com/ +Fixes: c1e64e298b8c ("net: diag: Support destroying TCP sockets.") +Signed-off-by: Xueming Feng +Tested-by: Lorenzo Colitti +Reviewed-by: Jason Xing +Reviewed-by: Eric Dumazet +Link: https://patch.msgid.link/20240826102327.1461482-1-kuro@kuroa.me +Signed-off-by: Jakub Kicinski +Link: https://lore.kernel.org/lkml/Z9OZS%2Fhc+v5og6%2FU@perf/ +[youngmin: Resolved minor conflict in net/ipv4/tcp.c] +Signed-off-by: Youngmin Nam +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/tcp.c | 16 ++++++++++------ + 1 file changed, 10 insertions(+), 6 deletions(-) + +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -4620,6 +4620,13 @@ int tcp_abort(struct sock *sk, int err) + /* Don't race with userspace socket closes such as tcp_close. */ + lock_sock(sk); + ++ /* Avoid closing the same socket twice. */ ++ if (sk->sk_state == TCP_CLOSE) { ++ if (!has_current_bpf_ctx()) ++ release_sock(sk); ++ return -ENOENT; ++ } ++ + if (sk->sk_state == TCP_LISTEN) { + tcp_set_state(sk, TCP_CLOSE); + inet_csk_listen_stop(sk); +@@ -4629,15 +4636,12 @@ int tcp_abort(struct sock *sk, int err) + local_bh_disable(); + bh_lock_sock(sk); + +- if (!sock_flag(sk, SOCK_DEAD)) { +- if (tcp_need_reset(sk->sk_state)) +- tcp_send_active_reset(sk, GFP_ATOMIC); +- tcp_done_with_error(sk, err); +- } ++ if (tcp_need_reset(sk->sk_state)) ++ tcp_send_active_reset(sk, GFP_ATOMIC); ++ tcp_done_with_error(sk, err); + + bh_unlock_sock(sk); + local_bh_enable(); +- tcp_write_queue_purge(sk); + if (!has_current_bpf_ctx()) + release_sock(sk); + return 0; diff --git a/queue-6.6/tcp-fix-races-in-tcp_abort.patch b/queue-6.6/tcp-fix-races-in-tcp_abort.patch new file mode 100644 index 0000000000..a3229c63dd --- /dev/null +++ b/queue-6.6/tcp-fix-races-in-tcp_abort.patch @@ -0,0 +1,46 @@ +From 5ce4645c23cf5f048eb8e9ce49e514bababdee85 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Tue, 28 May 2024 12:52:52 +0000 +Subject: tcp: fix races in tcp_abort() + +From: Eric Dumazet + +commit 5ce4645c23cf5f048eb8e9ce49e514bababdee85 upstream. + +tcp_abort() has the same issue than the one fixed in the prior patch +in tcp_write_err(). + +In order to get consistent results from tcp_poll(), we must call +sk_error_report() after tcp_done(). + +We can use tcp_done_with_error() to centralize this logic. + +Fixes: c1e64e298b8c ("net: diag: Support destroying TCP sockets.") +Signed-off-by: Eric Dumazet +Acked-by: Neal Cardwell +Link: https://lore.kernel.org/r/20240528125253.1966136-4-edumazet@google.com +Signed-off-by: Jakub Kicinski +[youngmin: Resolved minor conflict in net/ipv4/tcp.c] +Signed-off-by: Youngmin Nam +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/tcp.c | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -4630,13 +4630,9 @@ int tcp_abort(struct sock *sk, int err) + bh_lock_sock(sk); + + if (!sock_flag(sk, SOCK_DEAD)) { +- WRITE_ONCE(sk->sk_err, err); +- /* This barrier is coupled with smp_rmb() in tcp_poll() */ +- smp_wmb(); +- sk_error_report(sk); + if (tcp_need_reset(sk->sk_state)) + tcp_send_active_reset(sk, GFP_ATOMIC); +- tcp_done(sk); ++ tcp_done_with_error(sk, err); + } + + bh_unlock_sock(sk);