vkernel's only host-SIGTERM shutdown path is a silent no-op whenever pid 1 does not catch SIGUSR2: 'Shutting down...' is printed and nothing stops
Summary
shutdown_intr unconditionally ksignal(initproc, SIGUSR2) but the delivery layer silently discards default-action signals to pid 1, and execsigs only resets caught signals - until init(8) has armed its SIGUSR2 handler the signal is posted and dropped. Live-proven: kill -TERM mid-boot or post-boot prints 'Shutting down...' and the vkernel stays alive indefinitely (commands still execute inside the 'shut-down' guest; in-guest kill -USR2 1 leaves pid 1 alive); a SIGTERM burst during boot yields hundreds of Shutting-down lines while boot continues. The documented stop mechanism silently fails against any booting vkernel or non-init init_path - the host then powers off underneath the still-running vkernel (dirty images, stale pidfiles). SIG_CATCH-gate + shutdown_nice fallback fix validated (same 3-hunk diff as DF-5660): clean halt through boot() to cpu halt.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-5661 Β· 11 files| File | Type | Description | Size | |
|---|---|---|---|---|
| run.sh | β | 127 B | view raw | |
| vkinit3.c | β | 164 B | view raw | |
| build_image.sh | β | 1.0 KB | view raw | |
| run.midboot.noop.log | β | 1.9 KB | view raw | |
| wedge_probe.log | β | 2.1 KB | view raw | |
| run.fixboot.log | β | 2.2 KB | view raw | |
| bootlog_excerpt.txt | β | 3.5 KB | view raw | |
| env.txt | β | 220 B | view raw | |
| fix.diff | β | 2.8 KB | view raw | |
| VERDICT.md | β | 3.8 KB | β raw | |
| verdict.json | β | 3.8 KB | view raw |
DF-5661 β VERDICT
Status: reproduced (impact: dos β the vkernel's shutdown mechanism silently fails; SIGTERM cannot stop a booting vkernel or any vkernel whose pid 1 is not real init(8); host shutdown leaves the vkernel running and it is killed uncleanly underneath, with dirty guest disk images).
Mechanism (certain)
- Host SIGTERM β vkernel
shutdownsig(shutdown.c:77) βsignalintr(2)(machintr.c:169) β INT2 ithread βshutdown_intr(shutdown.c:91):kprintf("Caught SIGTERM ... Shutting down...\n")thenksignal(initproc, SIGUSR2)(shutdown.c:95) β init(8)'s poweroff trigger (sbin/init/init.c:1343). - If pid 1 has not armed a SIGUSR2 handler yet β the entire boot window
(create_init at SI_SUB_CREATE_INIT runs long before start_init execs,
and handlers are only installed after exec) β or ever (non-init(8)
pid 1): kern_sig's issignal loop hits
case SIG_DFL:βif (p->p_pid <= 1) break; /* == ignore */(kern_sig.c:2134-2144). The signal is posted and silently discarded. execsigs()(kern_sig.c:426-445) resets only caught signals, so a SIGUSR2 posted while start_init is still building/exec'ing the first image cannot be rescued by exec either.
Live proof (rig: VKERNEL64 on the DragonFly guest, /vkroot.img,
init_path=/bin/vkinit β sh as pid 1)
run.midboot.noop.log+wedge_probe.log:kill -TERMmid-boot and post-boot β "Caught SIGTERM from host system. Shutting down..." β the vkernel stays alive indefinitely (S5, minutes observed); the operator's stop signal has no effect.- Guest liveness proven post-SIGTERM by console injection:
echo GUEST_ALIVE_OKexecuted;kill -USR2 1; echo STILL_HEREβ¦printedSTILL_HERE_AFTER_USR2β pid 1 ignores SIGUSR2 via the pidβ€1 guard; no panic, no death, no shutdown. - At-scale variant: a SIGTERM burst during boot yields a stream of "Shutting down..." lines while boot proceeds normally (bootlog_excerpt.txt; hundreds of hits, zero effect).
Impact ceiling
Not memory corruption; a reliability/availability defect with data-loss
adjacency: host shutdown scripts (killall TERM, rc.d vkernel stop,
lockf-based pidfile scripts β the machinery init.c:1375-1404 exists to
support) silently fail against a booting vkernel; the host then powers
off under the still-running vkernel β unclean guest disk state, stale
locked pidfile. Trigger needs only the ability to signal the vkernel
(same uid or root), i.e. exactly the documented operational path.
Fix validation (fixed)
fix.diff = gate the ksignal on ps_sigcatch (the kernel's own
delivery criterion) and route the fallback through the in-kernel
shutdown_nice(RB_POWEROFF|RB_HALT) path, plus the two kern_shutdown.c
hardening hunks (shutdown_nice's identical blind-SIGINT bug; the
curproc==NULL kern_closefrom assertion that fires when boot() runs
from ithread context β hit live during validation and fixed).
Patched kernel, handler-less pid 1 (vkinit3, standing in for pre-arm
init(8)), same kill -TERM: run.fixboot.log shows the complete clean
kernel-side halt (boot() called on cpu#0 β¦ The operating system has
halted. β¦ cpu halt, exiting vkernel, monitor exit, FIXB RESULT:
exited) β the no-op is gone, the vkernel stops cleanly, the guest host
is untouched.
Why not uid0
No memory-safety primitive: a dropped signal. The deliverable is the demonstrated silent-failure of the kernel's own shutdown path and its clean repair.
Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
Fix verification
fixedBaseline: kill -TERM (mid-boot and full-boot, handler-less pid 1) -> 'Caught SIGTERM ... Shutting down...' then the vkernel stays alive forever (live-guest probes). Patched: identical trigger -> complete clean halt (boot() on cpu#0, system threads stopped, 'The operating system has halted.', cpu halt, exit(EX_OK), monitor exits); FIXB RESULT: exited.
run.fixboot.log (full halt transcript); bootlog_excerpt.txt (serial console: FIXB RESULT: exited)
Confirmed kernel references
Detail
Exploit chain
same-uid signal (operator stop script / host shutdown sweep) during vkernel boot -> shutdown_intr prints 'Shutting down...' -> ksignal(initproc, SIGUSR2) dropped by the pid<=1 SIG_DFL guard -> vkernel never stops -> host powers off underneath the running vkernel -> unclean guest disk images, stale locked pidfile
Evidence (decisive lines)
run.midboot.noop.log + wedge_probe.log (message then live guest: GUEST_ALIVE_OK, STILL_HERE_AFTER_USR2); bootlog_excerpt.txt (no-op at scale); run.fixboot.log (clean kernel-side halt on the patched kernel); VERDICT.md
PoC changes
run.sh adapted from the DF-5607 rig driver; added vkinit3 (pid-1 with no handlers) to /vkroot.img for fix validation; probes injected through the fifo console to prove guest liveness post-SIGTERM.
Verified recommended fix
Only ksignal init when init actually catches SIGUSR2 (ps_sigcatch gate) and otherwise take the in-kernel shutdown path (shutdown_nice(RB_POWEROFF|RB_HALT) with the kern_shutdown.c hardening hunks); see fix.diff.
Verdict
The vkernel's only host-SIGTERM shutdown path, shutdown_intr's ksignal(initproc, SIGUSR2) (shutdown.c:95), is a silent no-op whenever pid 1 does not catch SIGUSR2: kern_sig's issignal loop drops default-action signals to pid<=1 (kern_sig.c:2134-2144) and execsigs() only resets caught signals, so the whole boot window (create_init .. init(8) arming handlers) -- and permanently for a vkernel whose init_path is not real init(8) -- swallows the documented stop signal after printing 'Shutting down...'. Rig-proven live: kill -TERM mid-boot and post-boot left the vkernel alive indefinitely (verified by executing console commands inside the 'shut-down' guest: GUEST_ALIVE_OK; and kill -USR2 1 from inside the guest: STILL_HERE_AFTER_USR2); a burst of SIGTERMs during boot produced a stream of 'Shutting down...' lines while boot continued normally. With fix.diff (shared with DF-5660) and a handler-less pid 1 standing in for pre-arm init(8), the same kill -TERM now takes the in-kernel path and halts cleanly: 'boot() called on cpu#0 ... The operating system has halted. ... cpu halt, exiting vkernel', monitor exits, guest host untouched.
No comments yet.