From ba32fcfff9c95bd7b3fddcf6117664e1961a3b44 Mon Sep 17 00:00:00 2001 From: Gleb Smirnoff Date: Thu, 4 Sep 2014 09:15:44 +0000 Subject: [PATCH] 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 Security: Hardens against remote mbuf exhaustion attack. Sponsored by: Netflix Sponsored by: Nginx, Inc. --- sys/netinet/tcp_reass.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c index 14f0e93fe176..d7efe1d34f70 100644 --- a/sys/netinet/tcp_reass.c +++ b/sys/netinet/tcp_reass.c @@ -214,16 +214,29 @@ tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m) 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: /*