DragonFlyBSD Kernel Audit
DF-0296 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/netgraph/netgraph/ng_base.c b/sys/netgraph/netgraph/ng_base.c
--- a/sys/netgraph/netgraph/ng_base.c
+++ b/sys/netgraph/netgraph/ng_base.c
@@ -694,6 +694,19 @@
 }
 
 /*
+ * DF-0296: Take a reference on a hook so it (and its peer) cannot be
+ * freed while the caller dereferences hook->peer->node.  Callers MUST
+ * call ng_unref_hook() when done.
+ */
+void
+ng_ref_hook(hook_p hook)
+{
+	crit_enter();
+	hook->refs++;
+	crit_exit();
+}
+
+/*
  * Add an unconnected hook to a node. Only used internally.
  */
 static int
@@ -1138,15 +1151,24 @@
 		hook = ng_findhook(node, segment);
 
 		/* Can't get there from here... */
-		if (hook == NULL
-		    || hook->peer == NULL
+		if (hook == NULL) {
+			TRAP_ERROR;
+			return (ENOENT);
+		}
+		/* DF-0296: Take a reference so the peer hook/node cannot be
+		 * freed by ng_destroy_hook() while we dereference peer->node.
+		 */
+		ng_ref_hook(hook);
+		if (hook->peer == NULL
 		    || (hook->flags & HK_INVALID) != 0) {
+			ng_unref_hook(hook);
 			TRAP_ERROR;
 			return (ENOENT);
 		}
 
 		/* Hop on over to the next node */
 		node = hook->peer->node;
+		ng_unref_hook(hook);
 	}
 
 	/* If node somehow missing, fail here (probably this is not needed) */