⬢ DragonFlyBSD Kernel Audit
DF-4112 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/netif/nge/if_nge.c
+++ b/sys/dev/netif/nge/if_nge.c
@@ -1369,7 +1391,19 @@
 	struct ifnet *ifp = &sc->arpcom.ac_if;
 	struct mii_data *mii;
 
-	lwkt_serialize_enter(ifp->if_serializer);
+	/*
+	 * NOTE: never block on the serializer here.  nge_stop() calls
+	 * callout_stop(&sc->nge_stat_timer) while holding if_serializer
+	 * (nge_stop is reached under the serializer from nge_ioctl,
+	 * nge_init, nge_watchdog, nge_detach and nge_intr); DragonFly's
+	 * callout_stop() synchronously waits for an in-progress callback,
+	 * so a callback parked in lwkt_serialize_enter() would deadlock
+	 * against the stopper (AB-BA).  Try-enter and retry in one tick.
+	 */
+	if (lwkt_serialize_try(ifp->if_serializer) == 0) {
+		callout_reset(&sc->nge_stat_timer, 1, nge_tick, sc);
+		return;
+	}
 
 	if (sc->nge_tbi) {
 		if (sc->nge_link == 0) {