Under certain conditions, a stale icsk_probes_tstamp can lead to an unexpected connection abort during a zero-window state. The exact sequence leading to the timeout is as follows: 1. A zero window occurs. icsk_probes_tstamp is set. 2. The window opens slightly. tcp_ack_probe() is called because there are no in-flight packets. However, icsk_probes_tstamp is not cleared because the window is not large enough to fit the tcp_send_head. 3. Packets been sent, and RTO is armed which overrides the probe timer. 4. Subsequent ACKs consistently acknowledge packets and the window never fully closes. Because there are now in-flight packets, tcp_ack_probe() is never called again. 5. As a result, icsk_probes_tstamp is never updated despite the connection no longer in the zero-window state. 6. Much later, another zero window occurs. When probe timer triggers, tcp_probe_timer() evaluates the extremely old icsk_probes_tstamp and immediately aborts the connection due to TCP_USER_TIMEOUT. Fix this by explicitly clearing icsk_probes_tstamp in tcp_ack() whenever prior_packets is non-zero, ensuring that the probe timestamp is reset when exit zero-window state. Fixes: 9d9b1ee0b2d1 ("tcp: fix TCP_USER_TIMEOUT with zero window") Signed-off-by: Zhi Cheng --- net/ipv4/tcp_input.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index de9f68a9c0cf..02de64881b76 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -4365,6 +4365,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) tp->rcv_tstamp = tcp_jiffies32; if (!prior_packets) goto no_queue; + icsk->icsk_probes_tstamp = 0; /* See if we can take anything off of the retransmit queue. */ flag |= tcp_clean_rtx_queue(sk, skb, prior_fack, prior_snd_una, -- 2.47.3