⬢ DragonFlyBSD Kernel Audit
DF-4064 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/netif/fxp/if_fxp.c b/sys/dev/netif/fxp/if_fxp.c
--- a/sys/dev/netif/fxp/if_fxp.c
+++ b/sys/dev/netif/fxp/if_fxp.c
@@ -1446,7 +1446,17 @@ fxp_tick(void *xsc)
 	struct fxp_cb_tx *txp;
 	struct mbuf *m;
 
-	lwkt_serialize_enter(sc->arpcom.ac_if.if_serializer);
+	/*
+	 * Never block on the ifnet serializer from this (non-MPSAFE)
+	 * callout: the callback runs on a softclock thread under the MP
+	 * lock (kern_timeout.c), and every fxp_stop() caller invokes
+	 * callout_stop(&sc->fxp_stat_timer) while already holding the
+	 * serializer.  DragonFly's callout_stop() synchronously waits for
+	 * an in-progress callback ('costp', kern_timeout.c:920), so a
+	 * callback parked in lwkt_serialize_enter ('slize',
+	 * lwkt_serialize.c:234) deadlocks against the stopper (AB-BA),
+	 * wedging both threads, the CPU's softclock and the MP lock.
+	 * Retry on the next tick instead (emx_txgc_timer pattern).
+	 */
+	if (lwkt_serialize_try(sc->arpcom.ac_if.if_serializer) == 0) {
+		callout_reset(&sc->fxp_stat_timer, 1, fxp_tick, sc);
+		return;
+	}
 
 	IFNET_STAT_INC(ifp, opackets, sp->tx_good);