⬢ DragonFlyBSD Kernel Audit
DF-3715 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/netif/em/if_em.c	2026-09-15 21:39:34.188447660 +0000
+++ b/sys/dev/netif/em/if_em.c	2026-09-15 21:40:02.404089946 +0000
@@ -2030,9 +2030,17 @@
 	struct adapter *adapter = xsc;
 	struct ifnet *ifp = &adapter->arpcom.ac_if;
 
-	lwkt_serialize_enter(ifp->if_serializer);
-	em_82547_move_tail_serialized(adapter);
-	lwkt_serialize_exit(ifp->if_serializer);
+	/*
+	 * Non-blocking, see em_timer(): em_stop() calls
+	 * callout_stop(&adapter->tx_fifo_timer) under the serializer.
+	 */
+	if (lwkt_serialize_try(ifp->if_serializer)) {
+		em_82547_move_tail_serialized(adapter);
+		lwkt_serialize_exit(ifp->if_serializer);
+	} else {
+		callout_reset(&adapter->tx_fifo_timer, 1,
+			em_82547_move_tail, adapter);
+	}
 }
 
 static int
@@ -2219,23 +2227,33 @@
 	struct adapter *adapter = xsc;
 	struct ifnet *ifp = &adapter->arpcom.ac_if;
 
-	lwkt_serialize_enter(ifp->if_serializer);
-
-	em_update_link_status(adapter);
-	em_update_stats(adapter);
+	/*
+	 * Never block on the serializer here.  em_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,
+	 * like em_txgc_timer().
+	 */
+	if (lwkt_serialize_try(ifp->if_serializer)) {
+		em_update_link_status(adapter);
+		em_update_stats(adapter);
+
+		/* Reset LAA into RAR[0] on 82571 */
+		if (e1000_get_laa_state_82571(&adapter->hw) == TRUE)
+			e1000_rar_set(&adapter->hw, adapter->hw.mac.addr, 0);
 
-	/* Reset LAA into RAR[0] on 82571 */
-	if (e1000_get_laa_state_82571(&adapter->hw) == TRUE)
-		e1000_rar_set(&adapter->hw, adapter->hw.mac.addr, 0);
+		if (em_display_debug_stats && (ifp->if_flags & IFF_RUNNING))
+			em_print_hw_stats(adapter);
 
-	if (em_display_debug_stats && (ifp->if_flags & IFF_RUNNING))
-		em_print_hw_stats(adapter);
-
-	em_smartspeed(adapter);
+		em_smartspeed(adapter);
 
+		lwkt_serialize_exit(ifp->if_serializer);
+	}
 	callout_reset(&adapter->timer, hz, em_timer, adapter);
 
-	lwkt_serialize_exit(ifp->if_serializer);
 }
 
 static void