From: Greg Kroah-Hartman Date: Fri, 13 Mar 2026 12:46:48 +0000 (+0100) Subject: 6.1-stable patches X-Git-Tag: v6.12.77~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b0cb2c28ffb27758a715b5e47ae9d350577ba30c;p=thirdparty%2Fkernel%2Fstable-queue.git 6.1-stable patches added patches: net-tcp-accept-old-ack-during-closing.patch --- diff --git a/queue-6.1/net-tcp-accept-old-ack-during-closing.patch b/queue-6.1/net-tcp-accept-old-ack-during-closing.patch new file mode 100644 index 0000000000..4363c77ddc --- /dev/null +++ b/queue-6.1/net-tcp-accept-old-ack-during-closing.patch @@ -0,0 +1,75 @@ +From 795a7dfbc3d95e4c7c09569f319f026f8c7f5a9c Mon Sep 17 00:00:00 2001 +From: Menglong Dong +Date: Fri, 26 Jan 2024 12:05:19 +0800 +Subject: net: tcp: accept old ack during closing + +From: Menglong Dong + +commit 795a7dfbc3d95e4c7c09569f319f026f8c7f5a9c upstream. + +For now, the packet with an old ack is not accepted if we are in +FIN_WAIT1 state, which can cause retransmission. Taking the following +case as an example: + + Client Server + | | + FIN_WAIT1(Send FIN, seq=10) FIN_WAIT1(Send FIN, seq=20, ack=10) + | | + | Send ACK(seq=21, ack=11) + Recv ACK(seq=21, ack=11) + | + Recv FIN(seq=20, ack=10) + +In the case above, simultaneous close is happening, and the FIN and ACK +packet that send from the server is out of order. Then, the FIN will be +dropped by the client, as it has an old ack. Then, the server has to +retransmit the FIN, which can cause delay if the server has set the +SO_LINGER on the socket. + +Old ack is accepted in the ESTABLISHED and TIME_WAIT state, and I think +it should be better to keep the same logic. + +In this commit, we accept old ack in FIN_WAIT1/FIN_WAIT2/CLOSING/LAST_ACK +states. Maybe we should limit it to FIN_WAIT1 for now? + +Signed-off-by: Menglong Dong +Reviewed-by: Simon Horman +Reviewed-by: Eric Dumazet +Link: https://lore.kernel.org/r/20240126040519.1846345-1-menglong8.dong@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/tcp_input.c | 18 +++++++++++------- + 1 file changed, 11 insertions(+), 7 deletions(-) + +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -6630,17 +6630,21 @@ int tcp_rcv_state_process(struct sock *s + return 0; + + /* step 5: check the ACK field */ +- acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH | +- FLAG_UPDATE_TS_RECENT | +- FLAG_NO_CHALLENGE_ACK) > 0; ++ reason = tcp_ack(sk, skb, FLAG_SLOWPATH | ++ FLAG_UPDATE_TS_RECENT | ++ FLAG_NO_CHALLENGE_ACK); + +- if (!acceptable) { ++ if ((int)reason <= 0) { + if (sk->sk_state == TCP_SYN_RECV) + return 1; /* send one RST */ +- tcp_send_challenge_ack(sk); +- SKB_DR_SET(reason, TCP_OLD_ACK); +- goto discard; ++ /* accept old ack during closing */ ++ if ((int)reason < 0) { ++ tcp_send_challenge_ack(sk); ++ reason = -reason; ++ goto discard; ++ } + } ++ SKB_DR_SET(reason, NOT_SPECIFIED); + switch (sk->sk_state) { + case TCP_SYN_RECV: + tp->delivered++; /* SYN-ACK delivery isn't tracked in tcp_ack */ diff --git a/queue-6.1/series b/queue-6.1/series index 26007c35ac..c0a957dddd 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -142,3 +142,4 @@ xdp-use-modulo-operation-to-calculate-xdp-frag-tailr.patch xdp-produce-a-warning-when-calculated-tailroom-is-ne.patch tracing-add-null-pointer-check-to-trigger_data_free.patch net-sched-only-allow-act_ct-to-bind-to-clsact-ingress-qdiscs-and-shared-blocks.patch +net-tcp-accept-old-ack-during-closing.patch