aboutsummaryrefslogtreecommitdiff
path: root/sys/net/iflib.c
diff options
context:
space:
mode:
authorEric Joyner <erj@FreeBSD.org>2019-03-19 17:49:03 +0000
committerEric Joyner <erj@FreeBSD.org>2019-03-19 17:49:03 +0000
commit3e8d1bae5f49aab7132bd3f4be24867f18d5b103 (patch)
tree9d988efb8bb53a70bc2b452c174349f4960fb722 /sys/net/iflib.c
parent938b7a44d9a71a0fe8e408ec37508f3065edc83e (diff)
downloadsrc-3e8d1bae5f49aab7132bd3f4be24867f18d5b103.tar.gz
src-3e8d1bae5f49aab7132bd3f4be24867f18d5b103.zip
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@intel.com> Reviewed by: shurd@, gallatin@ MFC after: 1 week Sponsored by: Intel Corporation Differential Revision: https://reviews.freebsd.org/D19468
Notes
Notes: svn path=/head/; revision=345303
Diffstat (limited to 'sys/net/iflib.c')
-rw-r--r--sys/net/iflib.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/sys/net/iflib.c b/sys/net/iflib.c
index b803c4b3ca1f..694dd9b632fb 100644
--- a/sys/net/iflib.c
+++ b/sys/net/iflib.c
@@ -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;