⬢ DragonFlyBSD Kernel Audit
DF-3934 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/netif/age/if_age.c
+++ b/sys/dev/netif/age/if_age.c
@@ -1877,10 +1877,12 @@ age_intr(void *xsc)
     cmb = sc->age_rdata.age_cmb_block;
 
     bus_dmamap_sync(sc->age_cdata.age_cmb_block_tag,
 	sc->age_cdata.age_cmb_block_map, BUS_DMASYNC_POSTREAD);
     status = le32toh(cmb->intr_status);
     if ((status & AGE_INTRS) == 0)
 	goto done;
 again:
-    sc->age_tpd_cons = (le32toh(cmb->tpd_cons) & TPD_CONS_MASK) >>
-	TPD_CONS_SHIFT;
-    sc->age_rr_prod = (le32toh(cmb->rprod_cons) & RRD_PROD_MASK) >>
-	RRD_PROD_SHIFT;
+    /* ring indices are modulo the ring sizes, not the 16-bit field */
+    sc->age_tpd_cons = ((le32toh(cmb->tpd_cons) & TPD_CONS_MASK) >>
+	TPD_CONS_SHIFT) % AGE_TX_RING_CNT;
+    sc->age_rr_prod = ((le32toh(cmb->rprod_cons) & RRD_PROD_MASK) >>
+	RRD_PROD_SHIFT) % AGE_RR_RING_CNT;
@@ -2146,7 +2148,8 @@ age_rxintr(struct age_softc *sc, int rr_prod)
 	bus_dmamap_sync(sc->age_cdata.age_rr_ring_tag,
 	    sc->age_cdata.age_rr_ring_map, BUS_DMASYNC_POSTREAD);
 
-	for (prog = 0; rr_cons != rr_prod; prog++) {
+	/* bound the work done per interrupt (AGE_PROC_DEFAULT was dead) */
+	for (prog = 0; rr_cons != rr_prod && prog < AGE_PROC_DEFAULT; prog++) {
 		rxrd = &sc->age_rdata.age_rr_ring[rr_cons];
 		nsegs = AGE_RX_NSEGS(le32toh(rxrd->index));
 		if (nsegs == 0)