DF-0659 / fix.diff
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 */ |