DragonFlyBSD Kernel Audit
DF-0659 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/netgraph7/bluetooth/l2cap/ng_l2cap_misc.c b/sys/netgraph7/bluetooth/l2cap/ng_l2cap_misc.c
--- a/sys/netgraph7/bluetooth/l2cap/ng_l2cap_misc.c
+++ b/sys/netgraph7/bluetooth/l2cap/ng_l2cap_misc.c
@@ -222,14 +222,20 @@ int
 ng_l2cap_discon_untimeout(ng_l2cap_con_p con)
 {
 	if (!(con->flags & NG_L2CAP_CON_AUTO_DISCON_TIMO))
 		panic(
 "%s: %s - no disconnect timeout, state=%d, flags=%#x\n",
 			__func__,  NG_NODE_NAME(con->l2cap->node),
 			con->state, con->flags);
 	
-	if (ng_uncallout(&con->con_timo, con->l2cap->node) == 0)
+	/*
+	 * Always clear the flag BEFORE checking ng_uncallout's return value.
+	 * If ng_uncallout returns 0 the callout already fired and its
+	 * dispatch is queued; without this clear, a subsequent
+	 * con_ref/con_unref cycle within the same netgraph item would
+	 * call ng_l2cap_discon_timeout() which panics on the still-set
+	 * flag (DF-0659).
+	 */
+	con->flags &= ~NG_L2CAP_CON_AUTO_DISCON_TIMO;
+
+	if (ng_uncallout(&con->con_timo, con->l2cap->node) == 0)
 		return (ETIMEDOUT);
-
-	con->flags &= ~NG_L2CAP_CON_AUTO_DISCON_TIMO;
 
 	return (0);
 } /* ng_l2cap_discon_untimeout */