summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjtl <jtl@FreeBSD.org>2016-05-06 01:26:58 +0000
committerjtl <jtl@FreeBSD.org>2016-05-06 01:26:58 +0000
commitfdef3ab0211b87d886c8a87fe46be53c0642ee0c (patch)
tree147cfb0105d56f137b7bd090d40693109a5a70dd
parent5cba75d7c70f66075115953d248d0636c4d4085b (diff)
downloadFreeBSD-src-fdef3ab0211b87d886c8a87fe46be53c0642ee0c.zip
FreeBSD-src-fdef3ab0211b87d886c8a87fe46be53c0642ee0c.tar.gz
MFC r298408:
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.
-rw-r--r--sys/netinet/tcp_input.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 32133ae..435383d 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -2733,6 +2733,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);
@@ -2802,13 +2805,19 @@ process_ACK:
SOCKBUF_LOCK(&so->so_snd);
if (acked > so->so_snd.sb_cc) {
- tp->snd_wnd -= so->so_snd.sb_cc;
+ if (tp->snd_wnd >= so->so_snd.sb_cc)
+ tp->snd_wnd -= so->so_snd.sb_cc;
+ else
+ tp->snd_wnd = 0;
mfree = sbcut_locked(&so->so_snd,
(int)so->so_snd.sb_cc);
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. */
OpenPOWER on IntegriCloud