DragonFlyBSD Kernel Audit
DF-2928 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/kern/kern_spinlock.c b/sys/kern/kern_spinlock.c
index 0000000..0000001 100644
--- a/sys/kern/kern_spinlock.c
+++ b/sys/kern/kern_spinlock.c
@@ -88,7 +88,9 @@
 
 #ifdef INVARIANTS
-static int spin_lock_test_mode;
+/*
+ * Read by indefinite_check() (sys/sys/indefinite2.h) to break spinlock
+ * test waits.  Must NOT be static.
+ */
+int spin_lock_test_mode;
 #endif
 
 #ifdef DEBUG_LOCKS_LATENCY
diff --git a/sys/sys/indefinite.h b/sys/sys/indefinite.h
index 0000000..0000002 100644
--- a/sys/sys/indefinite.h
+++ b/sys/sys/indefinite.h
@@ -41,6 +41,10 @@
 
 extern int lock_test_mode;
 extern int indefinite_uses_rdtsc;
+#if defined(INVARIANTS)
+extern int spin_lock_test_mode;
+#endif
 
 
 struct indefinite_info {
diff --git a/sys/sys/indefinite2.h b/sys/sys/indefinite2.h
index 0000000..0000003 100644
--- a/sys/sys/indefinite2.h
+++ b/sys/sys/indefinite2.h
@@ -168,6 +168,15 @@ indefinite_check(indefinite_info_t *info)
 		kprintf("%s: %s, indefinite wait (%d secs)!\n",
 			str, info->ident, info->secs);
 		if (panicstr)
 			return TRUE;
 #if defined(INVARIANTS)
+		/*
+		 * Spinlock indefinite-wait test hook (debug.spin_lock_test=1).
+		 * Restores the pre-indefinite2.h semantics: the sysctl's
+		 * recursive spin_lock breaks at the first 1-second report
+		 * instead of running into the 60-second panic below.
+		 */
+		if ((info->type == 'S' || info->type == 's') &&
+		    spin_lock_test_mode) {
+			print_backtrace(-1);
+			return TRUE;
+		}
 		if (lock_test_mode) {
 			print_backtrace(-1);
 			return TRUE;