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; }