# DF-2928 — dead `spin_lock_test_mode`: `debug.spin_lock_test=1` panics INVARIANTS kernels after 60s

## What it is

`sys/kern/kern_spinlock.c` — the INVARIANTS-only sysctl `debug.spin_lock_test`
(value 1, "Test the indefinite wait code") is broken because the variable it
sets is dead code:

- `sys/kern/kern_spinlock.c:91` declares `static int spin_lock_test_mode;`
- the handler sets it around the deliberate recursive `spin_lock`
  (`kern_spinlock.c:419-424`) intending to make the contested wait break
- **nothing reads it**: `indefinite_check()` (sys/sys/indefinite2.h) honors a
  *different* global, `lock_test_mode` (sys/kern/kern_lock.c:71), so the
  wait never breaks
- after 60 seconds `indefinite_check()` panics unconditionally for spinlock
  types (`indefinite2.h:183-186`):
  `panic("spin_lock_ex: %s, indefinite wait!")`

The 2017 rewrite of the indefinite-wait machinery (indefinite2.h) moved the
test-mode check to `lock_test_mode` and dropped the spinlock-specific
variable; upstream master (2026-09) still has the dead static, so this is
unfixed upstream.

## Impact

- The calling CPU spins ~60 s inside a critical section (preemption and
  interrupts masked on that CPU), then the kernel **panics**.
- Requires **root-equivalent privilege** (`caps_priv_check_self(SYSCAP_RESTRICTEDROOT)`,
  `kern_spinlock.c:409`) and an **INVARIANTS kernel** — severity Low.
- Verified: an unprivileged user gets "Operation not permitted".

## Build / Run

No compile needed — sysctl-only PoC.

    # on the guest, as root:
    sysctl -w debug.spin_lock_test=1      # blocks 60s, then panic

Or via the harness: `./run.sh` (uses dfbsd-qemu/vm.sh; see VERDICT.md for the
recorded session).

## Expected output

Live msgbuf while it spins (one line per second, never breaks):

    spin_lock_ex: sysctl_spin_lock_test, indefinite wait (1 secs)!
    ...
    spin_lock_ex: sysctl_spin_lock_test, indefinite wait (11 secs)!
    sysctl_spin_lock_test() at sysctl_spin_lock_test+0x233   <- INVARIANTS backtrace
    ...
    spin_lock_ex: sysctl_spin_lock_test, indefinite wait (57 secs)!
    [at 60 secs] panic: spin_lock_ex: sysctl_spin_lock_test, indefinite wait!

Guest then stops answering ssh (`vm.sh status` -> down; vm.sh reports
"guest not answering (likely DDB on panic)").

## Fix

`fix.diff` restores the pre-2017 semantics: make `indefinite_check()` honor
`spin_lock_test_mode` for spinlock wait types ('S'/'s') so the test sysctl
breaks the wait after the first 1-second report instead of running into the
60-second panic.  (Alternative: delete the value==1 test branch entirely.)
