DragonFlyBSD Kernel Audit
DF-0622 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/netgraph7/ng_car.c b/sys/netgraph7/ng_car.c
--- a/sys/netgraph7/ng_car.c
+++ b/sys/netgraph7/ng_car.c
@@ -558,6 +558,16 @@
 	const priv_p priv = NG_NODE_PRIVATE(node);
 
 	if (hinfo) {
+		/*
+		 * Cancel any pending queue-processing callout before
+		 * tearing down the queue state it depends on.  Otherwise
+		 * a pending callout (which holds its own ref on node+hook)
+		 * survives the disconnect and fires ng_car_q_event on a
+		 * purged queue, NULL-dereferencing the mbuf slots.
+		 * Mirrors the cleanup already done in ng_car_shutdown().
+		 */
+		ng_uncallout(&hinfo->q_callout, node);
+
 		/* Purge queue if not empty. */
 		while (hinfo->q_first != hinfo->q_last) {
 			NG_FREE_M(hinfo->q[hinfo->q_first]);
@@ -672,6 +682,14 @@
 	/* Refill tokens for time we have slept. */
 	ng_car_refillhook(hinfo);
 
+	/*
+	 * The queue may have been drained/purged out-of-band (e.g. hook
+	 * disconnect) since this callout was scheduled; bail before touching
+	 * mbufs to avoid a NULL deref on the purged slots.
+	 */
+	if (hinfo->q_first == hinfo->q_last)
+		return;
+
 	/* If we have some tokens */
 	while (hinfo->tc >= 0) {