DragonFlyBSD Kernel Audit
DF-1249 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/netif/dc/if_dc.c b/sys/dev/netif/dc/if_dc.c
--- a/sys/dev/netif/dc/if_dc.c
+++ b/sys/dev/netif/dc/if_dc.c
@@ -2406,7 +2406,7 @@
 	struct dc_desc		*c = NULL;
 	struct mbuf		*m = NULL;
 	unsigned char		*ptr;
-	int			i, total_len;
+	int			i, total_len, nfrags;
 	u_int32_t		rxstat = 0;
 
 	i = sc->dc_pnic_rx_bug_save;
@@ -2414,11 +2414,17 @@
 	ptr = sc->dc_pnic_rx_buf;
 	bzero(ptr, DC_RXLEN * 5);
 
-	/* Copy all the bytes from the bogus buffers. */
+	/* Copy all the bytes from the bogus buffers.
+	 * dc_pnic_rx_buf holds at most DC_RXLEN*5 bytes (5 fragments);
+	 * cap the loop so a misbehaving PNIC producing more fragments
+	 * cannot overflow the salvage buffer. */
+	nfrags = 0;
 	while (1) {
 		c = &sc->dc_ldata->dc_rx_list[i];
 		rxstat = c->dc_status;
 		m = sc->dc_cdata.dc_rx_chain[i];
+		if (++nfrags > 5)
+			break;
 		bcopy(mtod(m, char *), ptr, DC_RXLEN);
 		ptr += DC_RXLEN;
 		/* If this is the last buffer, break out. */