DragonFlyBSD Kernel Audit
DF-0591 / fix.diff
← back to finding ↓ download raw
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);
 }