Author: glebius
Date: Thu Sep  4 09:15:44 2014
New Revision: 271089
URL: http://svnweb.freebsd.org/changeset/base/271089

Log:
  Improve r265338. When inserting mbufs into TCP reassembly queue,
  try to collapse adjacent pieces using m_catpkt(). In best case
  scenario it copies data and frees mbufs, making mbuf exhaustion
  attack harder.
  
  Suggested by:         Jonathan Looney <jonlooney gmail.com>
  Security:             Hardens against remote mbuf exhaustion attack.
  Sponsored by:         Netflix
  Sponsored by:         Nginx, Inc.

Modified:
  head/sys/netinet/tcp_reass.c

Modified: head/sys/netinet/tcp_reass.c
==============================================================================
--- head/sys/netinet/tcp_reass.c        Thu Sep  4 09:07:14 2014        
(r271088)
+++ head/sys/netinet/tcp_reass.c        Thu Sep  4 09:15:44 2014        
(r271089)
@@ -214,16 +214,29 @@ tcp_reass(struct tcpcb *tp, struct tcphd
                mq = nq;
        }
 
-       /* Insert the new segment queue entry into place. */
+       /*
+        * Insert the new segment queue entry into place.  Try to collapse
+        * mbuf chains if segments are adjacent.
+        */
        if (mp) {
-               m->m_nextpkt = mp->m_nextpkt;
-               mp->m_nextpkt = m;
+               if (M_TCPHDR(mp)->th_seq + mp->m_pkthdr.len == th->th_seq)
+                       m_catpkt(mp, m);
+               else {
+                       m->m_nextpkt = mp->m_nextpkt;
+                       mp->m_nextpkt = m;
+                       m->m_pkthdr.pkt_tcphdr = th;
+               }
        } else {
-               m->m_nextpkt = tp->t_segq;
-               tp->t_segq = m ;
+               mq = tp->t_segq;
+               tp->t_segq = m;
+               if (mq && th->th_seq + *tlenp == M_TCPHDR(mq)->th_seq) {
+                       m->m_nextpkt = mq->m_nextpkt;
+                       m_catpkt(m, mq);
+               } else
+                       m->m_nextpkt = mq;
+               m->m_pkthdr.pkt_tcphdr = th;
        }
-       m->m_pkthdr.pkt_tcphdr = th;
-       tp->t_segqlen += m->m_pkthdr.len;
+       tp->t_segqlen += *tlenp;
 
 present:
        /*
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to