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