DragonFlyBSD Kernel Audit
DF-2832 / witness.diff
← back to finding ↓ download raw
--- /tmp/opencode/df2832/orig.c	2026-09-02 00:22:49.535948645 +0000
+++ /tmp/opencode/df2832/witness.c	2026-09-02 00:22:49.543948543 +0000
@@ -100,6 +100,12 @@
 SYSCTL_INT(_debug, OID_AUTO, rush_requests, CTLFLAG_RW,
 		&stat_rush_requests, 0, "");
 
+/* DF2832 witness counters (IN-GUEST ONLY) */
+static int df2832_hits;
+static int df2832_starts;
+SYSCTL_INT(_debug, OID_AUTO, df2832_hits, CTLFLAG_RD, &df2832_hits, 0, "");
+SYSCTL_INT(_debug, OID_AUTO, df2832_starts, CTLFLAG_RD, &df2832_starts, 0, "");
+
 LIST_HEAD(synclist, vnode);
 
 #define	SC_FLAG_EXIT		(0x1)		/* request syncer exit */
@@ -353,6 +359,7 @@
 	mp->mnt_syncer_ctx = NULL;
 	lwkt_reltoken(&ctx->sc_token);
 
+	kprintf("DF2832: thr_stop FREE ctx=%p mp=%p\n", ctx, mp);
 	hashdestroy(ctx->syncer_workitem_pending, M_DEVBUF, ctx->syncer_mask);
 	kfree(ctx, M_TEMP);
 }
@@ -572,6 +579,27 @@
 }
 
 /*
+ * DF2832 witness: park up to ~500ms emulating preemption between the
+ * mp->mnt_syncer_ctx load and the atomic RMW below. If the mount is torn
+ * down while parked, mnt_syncer_ctx != local ctx, i.e. on the stock
+ * kernel the RMW would operate on memory freed by vn_syncer_thr_stop().
+ * On HIT we print and REFRAIN from the RMW (pure evidence, no corruption).
+ */
+#define DF2832_PARK(ctx, fn)	do {				\
+	int _n;						\
+	for (_n = 0; _n < 500; ++_n) {				\
+		if (mp->mnt_syncer_ctx != (ctx)) {		\
+			atomic_add_int(&df2832_hits, 1);		\
+			kprintf("DF2832: HIT stale ctx=%p in "	\
+				fn " after %d ms park (mp=%p)\n",	\
+				(ctx), _n, mp);			\
+			return;					\
+		}						\
+		tsleep(&df2832_hits, 0, "df2832w", 1);		\
+	}							\
+} while (0)
+
+/*
  * Force continuous full syncs until stopped.  This may be used by
  * filesystems waiting on dirty data to be flushed to avoid syncer/tsleep
  * races.
@@ -582,6 +610,8 @@
 	struct syncer_ctx *ctx;
 
 	if (mp && (ctx = mp->mnt_syncer_ctx) != NULL) {
+		atomic_add_int(&df2832_starts, 1);
+		DF2832_PARK(ctx, "trigger_syncer_start");
 		if (atomic_fetchadd_int(&ctx->syncer_trigger, 2) <= 1)
 			wakeup(ctx);
 	}
@@ -607,6 +637,8 @@
 
 	if (mp && (ctx = mp->mnt_syncer_ctx) != NULL) {
 		if ((ctx->syncer_trigger & 1) == 0) {
+			atomic_add_int(&df2832_starts, 1);
+			DF2832_PARK(ctx, "trigger_syncer");
 			atomic_set_int(&ctx->syncer_trigger, 1);
 			wakeup(ctx);
 		}