git: e46c15a0f848 - main - tcp: fix the test that a duplicate ACK has no data
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 19 Jul 2025 14:31:34 UTC
The branch main has been updated by tuexen:
URL: https://cgit.FreeBSD.org/src/commit/?id=e46c15a0f848174f58bb08fed8e173a76b4c473a
commit e46c15a0f848174f58bb08fed8e173a76b4c473a
Author: Michael Tuexen <tuexen@FreeBSD.org>
AuthorDate: 2025-07-19 13:03:22 +0000
Commit: Michael Tuexen <tuexen@FreeBSD.org>
CommitDate: 2025-07-19 13:03:22 +0000
tcp: fix the test that a duplicate ACK has no data
When processing a TCP segment, data is removed from the head or
the tail. The test whether a segment has no data on it should
depend on the TCP segment before the removal. Without this,
received segments might trigger a fast retransmit even when they
should not.
Reported by: syzbot+fc97a2b5a0f7ea161161@syzkaller.appspotmail.com
Reviewed by: Peter Lei
MFC after: 3 days
Sponsored by: Netflix, Inc.
Differential Revision: https://reviews.freebsd.org/D51425
---
sys/netinet/tcp_input.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 7c032e13f37a..f0921032ef31 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -1515,7 +1515,9 @@ tcp_do_segment(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th,
struct tcpopt to;
int tfo_syn;
u_int maxseg = 0;
+ bool no_data;
+ no_data = (tlen == 0);
thflags = tcp_get_flags(th);
tp->sackhint.last_sack_ack = 0;
sack_changed = SACK_NOCHANGE;
@@ -1754,7 +1756,7 @@ tcp_do_segment(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th,
tp->ts_recent = to.to_tsval;
}
- if (tlen == 0) {
+ if (no_data) {
if (SEQ_GT(th->th_ack, tp->snd_una) &&
SEQ_LEQ(th->th_ack, tp->snd_max) &&
!IN_RECOVERY(tp->t_flags) &&
@@ -2557,7 +2559,7 @@ tcp_do_segment(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th,
if (SEQ_LEQ(th->th_ack, tp->snd_una)) {
maxseg = tcp_maxseg(tp);
- if (tlen == 0 &&
+ if (no_data &&
(tiwin == tp->snd_wnd ||
(tp->t_flags & TF_SACK_PERMIT))) {
/*
@@ -3113,8 +3115,7 @@ step6:
(tp->snd_wl1 == th->th_seq && (SEQ_LT(tp->snd_wl2, th->th_ack) ||
(tp->snd_wl2 == th->th_ack && tiwin > tp->snd_wnd))))) {
/* keep track of pure window updates */
- if (tlen == 0 &&
- tp->snd_wl2 == th->th_ack && tiwin > tp->snd_wnd)
+ if (no_data && tp->snd_wl2 == th->th_ack && tiwin > tp->snd_wnd)
TCPSTAT_INC(tcps_rcvwinupd);
tp->snd_wnd = tiwin;
tp->snd_wl1 = th->th_seq;