Author: erj
Date: Tue Mar 19 17:49:03 2019
New Revision: 345303
URL: https://svnweb.freebsd.org/changeset/base/345303

Log:
  iflib: prevent possible infinite loop in iflib_encap
  
  From Jake:
  iflib_encap calls bus_dmamap_load_mbuf_sg. Upon it returning EFBIG, an
  m_collapse and an m_defrag are attempted to shrink the mbuf cluster to
  fit within the DMA segment limitations.
  
  However, if we call m_defrag, and then bus_dmamap_load_mbuf_sg returns
  EFBIG on the now defragmented mbuf, we will continuously re-call
  bus_dmamap_load_mbuf_sg over and over.
  
  This happens because m_head isn't NULL, and remap is >1, so we don't try
  to m_collapse or m_defrag again. The only way we exit the loop is if
  m_head is NULL. However, m_head can't be modified by the call to
  bus_dmamap_load_mbuf_sg, because we don't pass it as a double pointer.
  
  I believe this will be an incredibly rare occurrence, because it is
  unlikely that bus_dmamap_load_mbuf_sg will actually fail on the second
  defragment with an EFBIG error. However, it still seems like
  a possibility that we should account for.
  
  Fix the exit check to ensure that if remap is >1, we will also exit,
  even if m_head is not NULL.
  
  Submitted by: Jacob Keller <jacob.e.kel...@intel.com>
  Reviewed by:  shurd@, gallatin@
  MFC after:    1 week
  Sponsored by: Intel Corporation
  Differential Revision:        https://reviews.freebsd.org/D19468

Modified:
  head/sys/net/iflib.c

Modified: head/sys/net/iflib.c
==============================================================================
--- head/sys/net/iflib.c        Tue Mar 19 17:38:54 2019        (r345302)
+++ head/sys/net/iflib.c        Tue Mar 19 17:49:03 2019        (r345303)
@@ -3276,9 +3276,14 @@ defrag:
                                txq->ift_mbuf_defrag++;
                                m_head = m_defrag(*m_headp, M_NOWAIT);
                        }
-                       remap++;
-                       if (__predict_false(m_head == NULL))
+                       /*
+                        * remap should never be >1 unless 
bus_dmamap_load_mbuf_sg
+                        * failed to map an mbuf that was run through m_defrag
+                        */
+                       MPASS(remap <= 1);
+                       if (__predict_false(m_head == NULL || remap > 1))
                                goto defrag_failed;
+                       remap++;
                        *m_headp = m_head;
                        goto retry;
                        break;
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to