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); }