Author: lstewart
Date: Sun Nov 27 02:32:08 2011
New Revision: 228016
URL: http://svn.freebsd.org/changeset/base/228016

Log:
  Plug a TCP reassembly UMA zone leak introduced in r226113 by only using the
  backup stack queue entry when the zone is exhausted, otherwise we leak a zone
  allocation each time we plug a hole in the reassembly queue.
  
  Reported by:  many on freebsd-stable@ (thread: "TCP Reassembly Issues")
  Tested by:    many on freebsd-stable@ (thread: "TCP Reassembly Issues")
  Reviewed by:  bz (very brief sanity check)
  MFC after:    3 days

Modified:
  head/sys/netinet/tcp_reass.c

Modified: head/sys/netinet/tcp_reass.c
==============================================================================
--- head/sys/netinet/tcp_reass.c        Sun Nov 27 00:09:59 2011        
(r228015)
+++ head/sys/netinet/tcp_reass.c        Sun Nov 27 02:32:08 2011        
(r228016)
@@ -233,23 +233,28 @@ tcp_reass(struct tcpcb *tp, struct tcphd
         * when the zone is exhausted. Otherwise we may get stuck.
         */
        te = uma_zalloc(V_tcp_reass_zone, M_NOWAIT);
-       if (te == NULL && th->th_seq != tp->rcv_nxt) {
-               TCPSTAT_INC(tcps_rcvmemdrop);
-               m_freem(m);
-               *tlenp = 0;
-               if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL, NULL))) 
{
-                       log(LOG_DEBUG, "%s; %s: global zone limit reached, "
-                           "segment dropped\n", s, __func__);
-                       free(s, M_TCPLOG);
-               }
-               return (0);
-       } else if (th->th_seq == tp->rcv_nxt) {
-               bzero(&tqs, sizeof(struct tseg_qent));
-               te = &tqs;
-               if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL, NULL))) 
{
-                       log(LOG_DEBUG, "%s; %s: global zone limit reached, "
-                           "using stack for missing segment\n", s, __func__);
-                       free(s, M_TCPLOG);
+       if (te == NULL) {
+               if (th->th_seq != tp->rcv_nxt) {
+                       TCPSTAT_INC(tcps_rcvmemdrop);
+                       m_freem(m);
+                       *tlenp = 0;
+                       if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL,
+                           NULL))) {
+                               log(LOG_DEBUG, "%s; %s: global zone limit "
+                                   "reached, segment dropped\n", s, __func__);
+                               free(s, M_TCPLOG);
+                       }
+                       return (0);
+               } else {
+                       bzero(&tqs, sizeof(struct tseg_qent));
+                       te = &tqs;
+                       if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL,
+                           NULL))) {
+                               log(LOG_DEBUG,
+                                   "%s; %s: global zone limit reached, using "
+                                   "stack for missing segment\n", s, __func__);
+                               free(s, M_TCPLOG);
+                       }
                }
        }
        tp->t_segqlen++;
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to