Author: jtl
Date: Thu Apr 21 15:06:53 2016
New Revision: 298408
URL: https://svnweb.freebsd.org/changeset/base/298408

Log:
  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

Modified:
  head/sys/netinet/tcp_input.c

Modified: head/sys/netinet/tcp_input.c
==============================================================================
--- head/sys/netinet/tcp_input.c        Thu Apr 21 15:02:57 2016        
(r298407)
+++ head/sys/netinet/tcp_input.c        Thu Apr 21 15:06:53 2016        
(r298408)
@@ -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. */
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to