DF-0591 / fix.diff
diff --git a/sys/netgraph/bridge/ng_bridge.c b/sys/netgraph/bridge/ng_bridge.c --- a/sys/netgraph/bridge/ng_bridge.c +++ b/sys/netgraph/bridge/ng_bridge.c @@ -673,6 +673,10 @@ if (++i == priv->numLinks - 1) { /* last link */ m2 = m; meta2 = meta; + /* m is now owned by m2; clear so the post-loop + * cleanup does not double-free it. */ + m = NULL; + meta = NULL; } else { m2 = m_dup(m, M_NOWAIT); /* XXX m_copypacket() */ if (m2 == NULL) { @@ -691,7 +695,7 @@ /* Update stats */ destLink->stats.xmitPackets++; - destLink->stats.xmitOctets += m->m_pkthdr.len; + destLink->stats.xmitOctets += m2->m_pkthdr.len; switch (manycast) { case 0: /* unicast */ break; @@ -706,6 +710,15 @@ /* Send packet */ NG_SEND_DATA(error, destLink->hook, m2, meta2); } + + /* + * If the fan-out loop never consumed the original mbuf (e.g. numLinks + * == 1, so the loop guard i < numLinks - 1 == i < 0 was false on the + * first iteration), free it here. Without this, the single-link case + * leaks one mbuf per packet. + */ + if (m != NULL) + NG_FREE_DATA(m, meta); return (error); } |