mirror of
https://github.com/torvalds/linux.git
synced 2026-09-13 23:50:02 +02:00
tcp: fix icsk_ack.ato bitfield overflow
On cross-region connections we observed delayed ACKs suddenly turning into immediate ACKs plus a TCP_MAX_QUICKACKS burst, as if the connection had just received its first data segment. Commit95b9a87c6a("tcp: record last received ipv6 flowlabel") squeezed icsk_ack.ato into 8 bits, sized for TCP_DELACK_MAX. But both writers still bound ato by icsk_rto, which can be well above 255 jiffies, so the bitfield assignment silently wraps mod 256: repeated delack timer misses double ato up to icsk_rto, storing 320 as 64 and 256 as 0, and ato == 0 is the "first data packet" sentinel in tcp_event_data_recv(). Clamp both writers to TCP_DELACK_MAX, which the static_assert already guarantees to fit and tcp_send_delayed_ack() effectively caps ato at anyway. Fixes:95b9a87c6a("tcp: record last received ipv6 flowlabel") Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev> Reviewed-by: Neal Cardwell <ncardwell@google.com> Link: https://patch.msgid.link/20260807014437.36687-1-jiayuan.chen@linux.dev Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
883b56ae58
commit
60837e4b84
|
|
@ -1039,9 +1039,9 @@ static void tcp_event_data_recv(struct sock *sk, struct sk_buff *skb)
|
|||
/* The fastest case is the first. */
|
||||
icsk->icsk_ack.ato = (icsk->icsk_ack.ato >> 1) + TCP_ATO_MIN / 2;
|
||||
} else if (m < icsk->icsk_ack.ato) {
|
||||
icsk->icsk_ack.ato = (icsk->icsk_ack.ato >> 1) + m;
|
||||
if (icsk->icsk_ack.ato > icsk->icsk_rto)
|
||||
icsk->icsk_ack.ato = icsk->icsk_rto;
|
||||
icsk->icsk_ack.ato = min3((icsk->icsk_ack.ato >> 1) + (u32)m,
|
||||
icsk->icsk_rto,
|
||||
(u32)TCP_DELACK_MAX);
|
||||
} else if (m > icsk->icsk_rto) {
|
||||
/* Too long gap. Apparently sender failed to
|
||||
* restart window, so that we send ACKs quickly.
|
||||
|
|
|
|||
|
|
@ -334,7 +334,9 @@ void tcp_delack_timer_handler(struct sock *sk)
|
|||
if (inet_csk_ack_scheduled(sk)) {
|
||||
if (!inet_csk_in_pingpong_mode(sk)) {
|
||||
/* Delayed ACK missed: inflate ATO. */
|
||||
icsk->icsk_ack.ato = min_t(u32, icsk->icsk_ack.ato << 1, icsk->icsk_rto);
|
||||
icsk->icsk_ack.ato = min3((u32)icsk->icsk_ack.ato << 1,
|
||||
icsk->icsk_rto,
|
||||
(u32)TCP_DELACK_MAX);
|
||||
} else {
|
||||
/* Delayed ACK missed: leave pingpong mode and
|
||||
* deflate ATO.
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user