DF-3557 / fix.diff
--- a/sys/netgraph7/UI/ng_UI.c +++ b/sys/netgraph7/UI/ng_UI.c @@ -134,25 +134,39 @@ /* * Receive a control message */ +/* + * Bound nested synchronous FLOW relaying. A closed hook cycle (e.g. two + * UI nodes wired into a downstream/upstream ring) otherwise relays the + * item synchronously forever (ng_snd_item() applies forwarded items + * inline), overflowing the LWKT token array. Pure cycles stay nested + * for the whole relay, so a nesting counter trips deterministically. + */ +#define NG_UI_FLOW_HOPS_MAX 8 + +static volatile u_int ng_UI_flow_hops; + static int ng_UI_rcvmsg(node_p node, item_p item, hook_p lasthook) { int error; const priv_p priv = NG_NODE_PRIVATE(node); struct ng_mesg *msg; + hook_p dest; msg = NGI_MSG(item); /* only peeking */ if ((msg->header.typecookie == NGM_FLOW_COOKIE) && lasthook) { - if (lasthook == priv->downlink) { - if (priv->uplink) { - NG_FWD_ITEM_HOOK(error, item, priv->uplink); - return (error); - } - } else { - if (priv->downlink) { - NG_FWD_ITEM_HOOK(error, item, priv->downlink); - return (error); + dest = (lasthook == priv->downlink) ? priv->uplink : + priv->downlink; + if (dest != NULL) { + if (atomic_fetchadd_int(&ng_UI_flow_hops, 1) >= + NG_UI_FLOW_HOPS_MAX) { + atomic_subtract_int(&ng_UI_flow_hops, 1); + NG_FREE_ITEM(item); + return (ELOOP); } + NG_FWD_ITEM_HOOK(error, item, dest); + atomic_subtract_int(&ng_UI_flow_hops, 1); + return (error); } } |