⬢ DragonFlyBSD Kernel Audit
DF-3738 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/netif/emx/if_emx.c
+++ b/sys/dev/netif/emx/if_emx.c
@@ -1911,7 +1911,27 @@
 	struct emx_softc *sc = xsc;
 	struct ifnet *ifp = &sc->arpcom.ac_if;
 
-	lwkt_serialize_enter(&sc->main_serialize);
+	if ((ifp->if_flags & (IFF_RUNNING | IFF_UP)) !=
+	    (IFF_RUNNING | IFF_UP))
+		return;
+
+	/*
+	 * Never block on the serializer here: emx_stop() (and the LSC
+	 * interrupt path) call callout_stop(&sc->timer) while HOLDING the
+	 * serializer, and DragonFly's callout_stop() synchronously waits
+	 * for an in-progress callback -- a blocking enter would deadlock
+	 * the callout subsystem against the serializer (AB-BA).  Use the
+	 * same try-and-retry pattern as emx_txgc_timer().
+	 */
+	if (!lwkt_serialize_try(&sc->main_serialize)) {
+		callout_reset(&sc->timer, 1, emx_timer, sc);
+		return;
+	}
+	if ((ifp->if_flags & (IFF_RUNNING | IFF_UP)) !=
+	    (IFF_RUNNING | IFF_UP)) {
+		lwkt_serialize_exit(&sc->main_serialize);
+		return;
+	}
 
 	emx_update_link_status(sc);
 	emx_update_stats(sc);