DF-2928 / trigger.sh
#!/bin/sh # DF-2928 — sys/kern/kern_spinlock.c: dead spin_lock_test_mode makes # debug.spin_lock_test=1 spin 60s in a critical section and panic # INVARIANTS kernels instead of breaking the wait as documented. # # Run as root on the target DragonFlyBSD (INVARIANTS kernel). # Usage: ./trigger.sh (blocks ~65s; the kernel panics at 60s) # ./trigger.sh poll (read the live msgbuf mid-spin) # # Unprivileged users are refused (verified): # $ sysctl -w debug.spin_lock_test=1 # sysctl: debug.spin_lock_test=1: Operation not permitted set -eu if [ "$(id -u)" -ne 0 ]; then echo "must be root (caps_priv_check_self(SYSCAP_RESTRICTEDROOT))" >&2 exit 1 fi if ! sysctl -n debug.spin_lock_test >/dev/null 2>&1; then echo "kernel lacks INVARIANTS; sysctl_spin_lock_test not compiled" >&2 exit 1 fi case "${1:-fire}" in poll) # While the (backgrounded) fire run spins, the msgbuf accumulates # one "indefinite wait (N secs)!" report per second and never breaks. date dmesg | grep -E "indefinite|spin_lock" | tail -20 ;; fire) date # The sysctl handler (kern_spinlock.c:417-425) sets the DEAD static # spin_lock_test_mode before the recursive spin_lock, then blocks # in _spin_lock_contested -> indefinite_check(), which only honors # kern_lock.c's lock_test_mode. After 60 seconds: # panic("spin_lock_ex: %s, indefinite wait!") [indefinite2.h:185] sysctl -w debug.spin_lock_test=1 ;; detach) # fire, but in the background so the caller can poll (sysctl -w debug.spin_lock_test=1 >/tmp/df2928.log 2>&1 &) date; echo launched ;; esac |