svn commit: r345303 - head/sys/net

Eric Joyner erj at FreeBSD.org
Tue Mar 19 17:49:06 UTC 2019


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.keller at 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;


More information about the svn-src-all mailing list