⬢ DragonFlyBSD Kernel Audit
DF-4316 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/netif/lge/if_lge.c
+++ b/sys/dev/netif/lge/if_lge.c
@@ -981,9 +981,21 @@
 	struct lge_softc *sc = xsc;
 	struct ifnet *ifp = &sc->arpcom.ac_if;
 
-	lwkt_serialize_enter(ifp->if_serializer);
-	lge_tick_serialized(xsc);
-	lwkt_serialize_exit(ifp->if_serializer);
+	/*
+	 * Never block on the serializer here: every lge_stop() caller
+	 * (lge_detach, lge_init via ioctl/watchdog/rxeoc, lge_intr,
+	 * lge_ioctl) holds ifp->if_serializer while calling
+	 * callout_stop(&sc->lge_stat_timer), and callout_stop() sleeps
+	 * until an in-progress callback returns.  A callback parked in
+	 * lwkt_serialize_enter would deadlock both threads forever.
+	 */
+	if (lwkt_serialize_try(ifp->if_serializer)) {
+		lge_tick_serialized(xsc);
+		lwkt_serialize_exit(ifp->if_serializer);
+	} else {
+		/* Retry on the next tick. */
+		callout_reset(&sc->lge_stat_timer, 1, lge_tick, sc);
+	}
 }
 
 static void