From b8c2cd15e9579ea72f18155572673b8bd45ff454 Mon Sep 17 00:00:00 2001 From: "Jonathan T. Looney" Date: Thu, 21 Apr 2016 15:06:53 +0000 Subject: [PATCH] Prevent underflows in tp->snd_wnd if the remote side ACKs more than tp->snd_wnd. This can happen, for example, when the remote side responds to a window probe by ACKing the one byte it contains. Differential Revision: https://reviews.freebsd.org/D5625 Reviewed by: hiren Obtained from: Juniper Networks (earlier version) MFC after: 2 weeks Sponsored by: Juniper Networks --- sys/netinet/tcp_input.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 7134ce441f81..324b0da76933 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -2754,6 +2754,9 @@ process_ACK: INP_WLOCK_ASSERT(tp->t_inpcb); acked = BYTES_THIS_ACK(tp, th); + KASSERT(acked >= 0, ("%s: acked unexepectedly negative " + "(tp->snd_una=%u, th->th_ack=%u, tp=%p, m=%p)", __func__, + tp->snd_una, th->th_ack, tp, m)); TCPSTAT_INC(tcps_rcvackpack); TCPSTAT_ADD(tcps_rcvackbyte, acked); @@ -2823,13 +2826,19 @@ process_ACK: SOCKBUF_LOCK(&so->so_snd); if (acked > sbavail(&so->so_snd)) { - tp->snd_wnd -= sbavail(&so->so_snd); + if (tp->snd_wnd >= sbavail(&so->so_snd)) + tp->snd_wnd -= sbavail(&so->so_snd); + else + tp->snd_wnd = 0; mfree = sbcut_locked(&so->so_snd, (int)sbavail(&so->so_snd)); ourfinisacked = 1; } else { mfree = sbcut_locked(&so->so_snd, acked); - tp->snd_wnd -= acked; + if (tp->snd_wnd >= (u_long) acked) + tp->snd_wnd -= acked; + else + tp->snd_wnd = 0; ourfinisacked = 0; } /* NB: sowwakeup_locked() does an implicit unlock. */