⬢ DragonFlyBSD Kernel Audit
DF-4106 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/netif/vge/if_vge.c b/sys/dev/netif/vge/if_vge.c
index f090bba..1111111 100644
--- a/sys/dev/netif/vge/if_vge.c
+++ b/sys/dev/netif/vge/if_vge.c
@@ -1283,6 +1283,24 @@ vge_rxeof(struct vge_softc *sc, int count)
 		 * accumulate the buffers.
 		 */
 		if (rxstat & VGE_RXPKT_SOF) {
+			/*
+			 * Replenish the descriptor BEFORE linking the
+			 * current mbuf into the head chain.  If the
+			 * allocation fails, keep the current mbuf in this
+			 * descriptor (like the EOF path below) instead of
+			 * leaving it referenced by BOTH the head chain and
+			 * vge_rx_mbuf[] (double free in vge_stop / use
+			 * after free on the next walk of this slot).
+			 */
+			if (vge_newbuf(sc, i, NULL)) {
+				if (sc->vge_head != NULL)
+					m_freem(sc->vge_head);
+				sc->vge_head = sc->vge_tail = NULL;
+				IFNET_STAT_INC(ifp, ierrors, 1);
+				vge_newbuf(sc, i, m);
+				VGE_RX_DESC_INC(i);
+				continue;
+			}
 			m->m_len = MCLBYTES - VGE_ETHER_ALIGN;
 			if (sc->vge_head == NULL) {
 				sc->vge_head = sc->vge_tail = m;
@@ -1291,7 +1309,6 @@ vge_rxeof(struct vge_softc *sc, int count)
 				sc->vge_tail->m_next = m;
 				sc->vge_tail = m;
 			}
-			vge_newbuf(sc, i, NULL);
 			VGE_RX_DESC_INC(i);
 			continue;
 		}