⬢ DragonFlyBSD Kernel Audit
DF-4506 / amplifier.diff
← back to finding ↓ download raw
DF-4506 GUEST-ONLY RACE AMPLIFIER (instrumentation; never for sys/)
=====================================================================

Widens the load-to-dereference window of idr_find() with a sysctl-gated
tsleep() inserted between the (hoisted) node-pointer load and the array
dereference.  The C source of idr_find() has no atomics or barriers; the
compiler is free to emit these loads in this order, so the interleaving
enabled here is one the uninstrumented kernel already permits.  The
amplifier only makes the ~2-5ns window observable.  Default (sysctl=0) is
a no-op.

Apply inside the guest's /usr/src (NOT to the repo's sys/ tree):

  cd /usr/src && patch -p1 < amplifier.diff
  make -j6 buildkernel KERNCONF=X86_64_GENERIC
  make installkernel && reboot

--- a/sys/libkern/linux_idr.c	2026-09-20 22:40:38.494056050 +0000
+++ b/sys/libkern/linux_idr.c	2026-09-20 22:41:04.661717126 +0000
@@ -120,6 +120,7 @@
 #include <sys/idr.h>
 #include <sys/kernel.h>
 #include <sys/libkern.h>
+#include <sys/sysctl.h>
 #include <sys/malloc.h>
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -133,6 +134,10 @@
 
 MALLOC_DEFINE(M_IDR, "idr", "Integer ID management");
 
+int idr_dbg_find_pause = 0;
+SYSCTL_INT(_debug, OID_AUTO, idr_find_pause, CTLFLAG_RW,
+    &idr_dbg_find_pause, 0, "DF-4506 amplifier: ticks to park in idr_find");
+
 static void	idr_grow(struct idr *idp, int want);
 static void	idr_reserve(struct idr *idp, int id, int incr);
 static int	idr_find_free(struct idr *idp, int want, int lim);
@@ -516,13 +521,19 @@
 idr_find(struct idr *idp, int id)
 {
 	void *ret;
+	int dbg_count = idp->idr_count;
+	struct idr_node *dbg_nodes = idp->idr_nodes;
 
-	if (id < 0 || id >= idp->idr_count) {
+	/* DF-4506 RACE AMPLIFIER (guest-only debug instrumentation) */
+	if (idr_dbg_find_pause > 0)
+		tsleep(&idr_dbg_find_pause, 0, "idrfp", idr_dbg_find_pause);
+
+	if (id < 0 || id >= dbg_count) {
 		ret = NULL;
-	} else if (idp->idr_nodes[id].allocated == 0) {
+	} else if (dbg_nodes[id].allocated == 0) {
 		ret = NULL;
 	} else {
-		ret = idp->idr_nodes[id].data;
+		ret = dbg_nodes[id].data;
 	}
 	return ret;
 }