⬢ DragonFlyBSD Kernel Audit
DF-4271 / fix.diff
← back to finding ↓ download raw
fix.diff - DF-4271: drain the self-re-arming tick callout across detach.

wb_stop() only issues callout_stop(), which by contract (kern_timeout.c)
does not interlock against an in-progress callback; wb_tick self-serializes
and re-arms itself, so a wb_tick blocked on the serializer during detach
proceeds after teardown, runs mii_tick against the deleted miibus child and
re-arms a callout inside the freed softc (repeating UAF every hz).

Drain AFTER releasing the serializer (draining while holding it would
deadlock against wb_tick's own serialize_enter).

Applies on top of sys/dev/netif/wb/if_wb.c (read-only audit tree; never applied).

--- a/sys/dev/netif/wb/if_wb.c
+++ b/sys/dev/netif/wb/if_wb.c
@@ -840,10 +840,13 @@ wb_detach(device_t dev)
 	if (device_is_attached(dev)) {
 		lwkt_serialize_enter(ifp->if_serializer);
 		wb_stop(sc);
 		bus_teardown_intr(dev, sc->wb_irq, sc->wb_intrhand);
 		lwkt_serialize_exit(ifp->if_serializer);
 
+		/* wb_tick re-arms itself under the serializer: drain it after
+		 * the release so a blocked tick cannot outlive the softc. */
+		callout_drain(&sc->wb_stat_timer);
+
 		ether_ifdetach(ifp);
 	}