⬢ DragonFlyBSD Kernel Audit
DF-4303 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/netif/bfe/if_bfe.c
+++ b/sys/dev/netif/bfe/if_bfe.c
@@ -1491,21 +1491,30 @@
 
 	mii = device_get_softc(sc->bfe_miibus);
 
-	lwkt_serialize_enter(ifp->if_serializer);
+	/*
+	 * Never block on the serializer here.  bfe_stop() tears this
+	 * callout down with callout_stop() while holding the same
+	 * serializer, and callout_stop() synchronously waits for an
+	 * in-progress callback (kern_timeout.c "costp" wait).  A
+	 * callback blocked in lwkt_serialize_enter() therefore
+	 * deadlocks the softclock thread against the serializer
+	 * holder (AB-BA).  Use try-enter and retry on the next tick.
+	 */
+	if (lwkt_serialize_try(ifp->if_serializer)) {
+		bfe_stats_update(sc);
 
-	bfe_stats_update(sc);
-	callout_reset(&sc->bfe_stat_timer, hz, bfe_tick, sc);
-
-	if (sc->bfe_link == 0) {
-		mii_tick(mii);
-		if (!sc->bfe_link && mii->mii_media_status & IFM_ACTIVE &&
-		    IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE)  {
-			sc->bfe_link++;
+		if (sc->bfe_link == 0) {
+			mii_tick(mii);
+			if (!sc->bfe_link && mii->mii_media_status & IFM_ACTIVE &&
+			    IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE)  {
+				sc->bfe_link++;
+			}
+			if (!sc->bfe_link)
+				sc->bfe_link++;
 		}
-		if (!sc->bfe_link)
-			sc->bfe_link++;
+		lwkt_serialize_exit(ifp->if_serializer);
 	}
-	lwkt_serialize_exit(ifp->if_serializer);
+	callout_reset(&sc->bfe_stat_timer, hz, bfe_tick, sc);
 }
 
 /*