⬢ DragonFlyBSD Kernel Audit
DF-3681 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/netif/igb/if_igb.c
+++ b/sys/dev/netif/igb/if_igb.c
@@ -743,6 +743,7 @@
 igb_detach(device_t dev)
 {
 	struct igb_softc *sc = device_get_softc(dev);
+	int i;
 
 	if (device_is_attached(dev)) {
 		struct ifnet *ifp = &sc->arpcom.ac_if;
@@ -762,6 +763,19 @@
 
 		ifnet_deserialize_all(ifp);
 
+		/*
+		 * igb_timer() and igb_txgc_timer() self-rearm, and
+		 * callout_stop() (see igb_stop()) does not interlock
+		 * against a callback that is already in progress; a
+		 * blocked igb_timer() resumes once the serializers are
+		 * released above and would rearm into freed memory.
+		 * Terminate both callout classes before the rings and
+		 * softc go away.
+		 */
+		callout_terminate(&sc->timer);
+		for (i = 0; i < sc->tx_ring_cnt; ++i)
+			callout_terminate(&sc->tx_rings[i].tx_gc_timer);
+
 		ether_ifdetach(ifp);
 	} else if (sc->mem_res != NULL) {
 		igb_rel_hw_control(sc);