⬢ DragonFlyBSD Kernel Audit
DF-3502 / fix.diff
← back to finding ↓ download raw
--- a/sys/netgraph/fec/ng_fec.c
+++ b/sys/netgraph/fec/ng_fec.c
@@ -20,6 +20,7 @@
  */
 
 static int	*ng_fec_units = NULL;
 static int	ng_fec_units_len = 0;
 static int	ng_units_in_use = 0;
+static int	ng_fec_armed = 0;	/* fec nodes arming ng_ether_input_p */
@@ -455,6 +456,10 @@ ng_fec_delport(struct ng_fec_private *priv, char *iface)
 
 	/* Stop interface */
 	bifp->if_flags &= ~IFF_UP;
+	/* Stop claiming this member's RX path: clear our IFP2NG pointer,
+	 * otherwise it dangles after the node is freed and ng_fec_input
+	 * dereferences freed memory on the next armed RX frame. */
+	ac = (struct arpcom *)bifp;
+	if (ac->ac_netgraph == (void *)priv->node)
+		ac->ac_netgraph = NULL;
 	bifp->if_ioctl(bifp, SIOCSIFFLAGS, NULL, NULL);
 
 	/* Restore MAC address. */
@@ -1131,7 +1136,8 @@ ng_fec_constructor(node_p *nodep)
 
 	/* Grab hold of the ether_input pipe. */
 	if (ng_ether_input_p == NULL)
 		ng_ether_input_p = ng_fec_input;
+	ng_fec_armed++;
 
 	/* Attach the interface */
 	ether_ifattach(ifp, priv->arpcom.ac_enaddr, NULL);
@@ -1231,8 +1237,9 @@ ng_fec_rmnode(node_p node)
 	ng_cutlinks(node);
 	ng_unname(node);
-	if (ng_ether_input_p != NULL)
-		ng_ether_input_p = NULL;
+	if (--ng_fec_armed <= 0 && ng_ether_input_p == ng_fec_input)
+		ng_ether_input_p = NULL;
 	ether_ifdetach(&priv->arpcom.ac_if);