⬢ DragonFlyBSD Kernel Audit
DF-4326 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/netif/sf/if_sf.c
+++ b/sys/dev/netif/sf/if_sf.c
@@ -933,6 +933,18 @@ sf_rxeof(struct sf_softc *sc)
 	while (cmpconsidx != cmpprodidx) {
 		struct mbuf		*m0;
 
 		cur_rx = &sc->sf_ldata->sf_rx_clist[cmpconsidx];
+
+		/*
+		 * sf_endidx is an 11-bit buffer-descriptor index
+		 * DMA-written by the NIC, but the RX buffer ring only
+		 * has SF_RX_DLIST_CNT (256) entries.  An out-of-range
+		 * value must not reach the descriptor dereference:
+		 * sf_newbuf() below would write {mbuf pointer, DMA
+		 * address, valid bit} up to ~28KB past the ring,
+		 * i.e. past the whole contigmalloc'd sf_list_data
+		 * block.  Drop the completion and resynchronize.
+		 */
+		if (cur_rx->sf_endidx >= SF_RX_DLIST_CNT) {
+			kprintf("sf%d: bogus RX endidx %u, resetting\n",
+			    sc->sf_unit, (unsigned)cur_rx->sf_endidx);
+			ifp->if_flags &= ~IFF_RUNNING;
+			sf_init(sc);
+			return;
+		}
 		desc = &sc->sf_ldata->sf_rx_dlist_big[cur_rx->sf_endidx];
 		m = desc->sf_mbuf;
 		SF_INC(cmpconsidx, SF_RX_CLIST_CNT);