DragonFlyBSD Kernel Audit
DF-0017 / panic.txt
← back to finding ↓ download raw
============================================================
 DF-0017 — kernel panic signature (from dfbsd-qemu/boot.log)
 Trigger: ./trigger 300  (300-deep DMSG circuit chain + root DELETE)
 Guest:   DragonFly v6.5.0.1712.g89e6a-DEVELOPMENT (X86_64_GENERIC)
============================================================

(Reproduced twice — identical signature, only the exhausted-stack
 address differs between runs.  rsp is page-aligned in both cases,
 indicating total 16 KB LWKT thread-stack exhaustion.)

Run #1 (depth=300):
login: DOUBLE FAULT

Fatal double fault
rip = 0xffffffff806564d4
rsp = 0xfffff800abae1000
rbp = 0xfffff800abae1000
cpuid = 1; lapic id = 1
panic: double fault
cpuid = 1
Trace beginning at frame 0xfffff8004602eec8
dblfault_handler() at dblfault_handler+0x10c 0xffffffff80bd5f3c 
dblfault_handler() at dblfault_handler+0x10c 0xffffffff80bd5f3c 
Debugger("panic")

CPU1 stopping CPUs: 0x00000001
 stopped
Stopped at      Debugger+0x7c:  movb    $0,0xbd77f9(%rip)
db> 

------------------------------------------------------------

Run #2 (depth=300, after control run depth=5 which did NOT panic):
login: DOUBLE FAULT

Fatal double fault
rip = 0xffffffff806564d4
rsp = 0xfffff800ab38f000
rbp = 0xfffff800ab38f000
cpuid = 1; lapic id = 1
panic: double fault
cpuid = 1
Trace beginning at frame 0xfffff8004602eec8
dblfault_handler() at dblfault_handler+0x10c 0xffffffff80bd5f3c 
dblfault_handler() at dblfault_handler+0x10c 0xffffffff80bd5f3c 
Debugger("panic")

CPU1 stopping CPUs: 0x00000001
 stopped
Stopped at      Debugger+0x7c:  movb    $0,0xbd77f9(%rip)
db> 

------------------------------------------------------------
INTERPRETATION
------------------------------------------------------------
A "Fatal double fault" with a page-aligned rsp (== rbp) is the
canonical signature of a kernel thread stack overflow on x86: the
unbounded recursion exhausts the 16 KB LWKT kernel thread stack
(LWKT_THREAD_STACK = UPAGES*PAGE_SIZE = 4*4096, sys/sys/thread.h:472),
the stack pointer runs off the allocation, and the next push/fault
finds no usable stack to dispatch even a normal page-fault handler ->
double fault -> panic.

The double-fault trace naturally shows only dblfault_handler() because
the original (kdmsg) call frames have been destroyed by the stack
exhaustion -- there is no recoverable frame to walk.  (Confirmed: the
LWKT stack has NO guard page; kmem_alloc_stack() in sys/vm/vm_extern.h
is just kmem_alloc1(..|KM_STACK) with no guard mapping, so the overflow
corrupts adjacent kernel memory before double-faulting -- i.e. it is a
memory-corruption primitive that reliably manifests as a DoS.)

The chain is built by the DMSG CREATE/circuit-nesting path and torn
down by kdmsg_simulate_failure() / kdmsg_state_dying(), both unbounded
recursive walks (sys/kern/kern_dmsg.c:1346 and :1428).  See VERDICT.md.