DragonFlyBSD Kernel Audit
DF-1292 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/netif/age/if_age.c b/sys/dev/netif/age/if_age.c
--- a/sys/dev/netif/age/if_age.c
+++ b/sys/dev/netif/age/if_age.c
@@ -1989,7 +1989,7 @@
 	struct rx_desc *desc;
 	struct mbuf *mp, *m;
 	uint32_t status, index, vtag;
-	int count, nsegs, pktlen;
+	int count, nsegs, pktlen, segsz;
 	int rx_cons;
 
 	status = le32toh(rxrd->flags);
@@ -2021,6 +2021,14 @@
 		rxd = &sc->age_cdata.age_rxdesc[rx_cons];
 		mp = rxd->rx_m;
 		desc = rxd->rx_desc;
+		/*
+		 * Snapshot desc->len BEFORE age_newbuf() recycles the
+		 * descriptor for the next receive (which overwrites
+		 * desc->len).  Reading it afterwards yields 0 for every
+		 * non-first segment and corrupts the first mbuf's m_len.
+		 */
+		segsz = AGE_RX_BYTES(le32toh(desc->len));
+
 		/* Add a new receive buffer to the ring. */
 		if (age_newbuf(sc, rxd, 0) != 0) {
 			IFNET_STAT_INC(ifp, iqdrops, 1);
@@ -2034,7 +2042,7 @@
 
 		/* The length of the first mbuf is computed last. */
 		if (count != 0) {
-			mp->m_len = AGE_RX_BYTES(le32toh(desc->len));
+			mp->m_len = segsz;
 			pktlen += mp->m_len;
 		}