⬢ DragonFlyBSD Kernel Audit
DF-4498 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/netif/sbsh/if_sbsh.c
+++ b/sys/dev/netif/sbsh/if_sbsh.c
@@ -665,8 +665,11 @@ encap_frame(struct sbsh_softc *sc, struct mbuf *m_head)
 	done = 0;
 	do {
 		if (m->m_len < 5 || cur_tbd == ((sc->head_tdesc - 1) & 0x7f)) {
 			if ((m_head = repack(sc, m_head)) != NULL)
 				goto look_for_nonzero;
 			else
+				/* drop the frame instead of leaking it */
+				m_freem(m_head);
 				return;
 		}
 
@@ -699,6 +702,11 @@ static struct mbuf *
 repack(struct sbsh_softc *sc, struct mbuf *m)
 {
 	struct mbuf  *m_new;
 
+	/* A repacked packet smaller than 5 bytes would re-trigger the
+	 * repack condition in encap_frame() forever (infinite alloc/free
+	 * spin while holding if_serializer). Drop such frames instead. */
+	if (m->m_pkthdr.len < 5)
+		return (NULL);
+
 	MGETHDR(m_new, M_NOWAIT, MT_DATA);
 	if (!m_new) {
 		if_printf (&sc->arpcom.ac_if,
 			   "unable to get mbuf.\n");