⬢ DragonFlyBSD Kernel Audit
DF-4304 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/netif/bfe/if_bfe.c
+++ b/sys/dev/netif/bfe/if_bfe.c
@@ -1064,6 +1064,16 @@
 	chipidx = CSR_READ_4(sc, BFE_DMATX_STAT) & BFE_STAT_CDMASK;
 	chipidx /= sizeof(struct bfe_desc);
 
+	/* The 12-bit field encodes offsets 0..4095 -> indices 0..511,
+	 * but the ring holds BFE_TX_LIST_CNT (511) descriptors.  An
+	 * out-of-range index (e.g. from a wedged/errant DMA engine)
+	 * would make the cleanup walk below non-terminating while
+	 * holding the serializer in interrupt context.  */
+	if (chipidx >= BFE_TX_LIST_CNT) {
+		if_printf(ifp, "tx dma status bogus (cd=%u)\n", chipidx);
+		return;
+	}
+
 	i = sc->bfe_tx_cons;
 
 	/* Go through the mbufs and free those that have been transmitted */
@@ -1106,6 +1116,13 @@
 	status = CSR_READ_4(sc, BFE_DMARX_STAT);
 	current = (status & BFE_STAT_CDMASK) / sizeof(struct bfe_desc);
 
+	/* See bfe_txeof(): index 511 is encodable but not a valid ring
+	 * index; walking toward it never terminates.  */
+	if (current >= BFE_RX_LIST_CNT) {
+		if_printf(ifp, "rx dma status bogus (cd=%u)\n", current);
+		return;
+	}
+
 	while (current != cons) {
 		r = &sc->bfe_rx_ring[cons];
 		bus_dmamap_sync(sc->bfe_rxbuf_tag, r->bfe_map,