⬢ DragonFlyBSD Kernel Audit
DF-3776 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/netif/jme/if_jme.c
+++ b/sys/dev/netif/jme/if_jme.c
@@ -2568,7 +2568,23 @@
 	struct jme_softc *sc = xsc;
 	struct mii_data *mii = device_get_softc(sc->jme_miibus);
 
-	lwkt_serialize_enter(&sc->jme_serialize);
+	/*
+	 * jme_stop() stops jme_tick_ch with callout_stop() while holding
+	 * ALL driver serializers (ASSERT_IFNET_SERIALIZED_ALL, if_jme.c,
+	 * entered via ifnet_serialize_all).  callout_stop() on this
+	 * kernel synchronously waits (ssleep "costp",
+	 * sys/kern/kern_timeout.c:920) for an in-progress callback, so a
+	 * blocking serializer acquire here can deadlock (AB-BA) against
+	 * jme_stop()'s caller (ifconfig down/MTU/media, jme_init reinit,
+	 * watchdog, jme_detach, jme_suspend).  Try-enter instead and
+	 * retry on the next tick; the STOP issued by callout_stop()
+	 * unloads the racing re-arm.
+	 */
+	if (!lwkt_serialize_try(&sc->jme_serialize)) {
+		callout_reset_bycpu(&sc->jme_tick_ch, 1, jme_tick, sc,
+		    JME_TICK_CPUID);
+		return;
+	}
 
 	KKASSERT(mycpuid == JME_TICK_CPUID);