⬢ DragonFlyBSD Kernel Audit
DF-3935 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/netif/age/if_age.c
+++ b/sys/dev/netif/age/if_age.c
@@ -2188,11 +2188,24 @@ age_rxintr(struct age_softc *sc, int rr_prod)
 static void
 age_tick(void *xsc)
 {
 	struct age_softc *sc = xsc;
 	struct ifnet *ifp = &sc->arpcom.ac_if;
 	struct mii_data *mii = device_get_softc(sc->age_miibus);
 
-	lwkt_serialize_enter(ifp->if_serializer);
+	/*
+	 * DF-3715 family: age_stop() tears this callout down with
+	 * callout_stop() while holding ifp->if_serializer; a callback
+	 * dequeued and blocked in lwkt_serialize_enter() then deadlocks
+	 * the synchronous stopper (AB-BA, wchan 'costp').  Use a
+	 * try-enter and bail (the next tick retries) so the callback
+	 * can always complete and callout_stop() can always return.
+	 */
+	if (!lwkt_serialize_try(ifp->if_serializer)) {
+		callout_reset(&sc->age_tick_ch, 1, age_tick, sc);
+		return;
+	}
 
 	mii_tick(mii);
 	callout_reset(&sc->age_tick_ch, hz, age_tick, sc);
 
 	lwkt_serialize_exit(ifp->if_serializer);
 }