⬢ DragonFlyBSD Kernel Audit
DF-2396 / fix.diff
← back to finding ↓ download raw
--- a/sys/kern/kern_sysctl.c
+++ b/sys/kern/kern_sysctl.c
@@ -1473,12 +1473,20 @@
 #endif
 	}
 
+	/*
+	 * Mark the handler as running so sysctl_remove_oid_locked()'s
+	 * drain loop actually drains: without this, an oid freed under a
+	 * racing reader leaves a dangling oid / freed arg1 (DF-2396).
+	 */
+	atomic_add_int(&oid->oid_running, 1);
 	if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE)
 		error = oid->oid_handler(oid, (int *)arg1 + indx, arg2 - indx,
 					 req);
 	else
 		error = oid->oid_handler(oid, oid->oid_arg1, oid->oid_arg2,
 					 req);
+	if (atomic_fetchadd_int(&oid->oid_running, -1) == 1)
+		wakeup(&oid->oid_running);
 
 	if ((oid->oid_kind & CTLFLAG_NOLOCK) == 0)
 		lockmgr(&oid->oid_lock, LK_RELEASE);