DF-5587 / verdict.json
{ "finding_id": "DF-5587", "status": "reproduced", "verdict": "exc_segfault is installed process-wide with SA_SIGINFO|SA_NODEFER and an empty sa_mask (exception.c:222-229); the vkernels cothreads run with %gs=0 (tls_set_gs(0), cothread.c:143-148) and only the 8 interrupt signals masked (cpu_mask_all_signals, machintr.c:205-211) \u2014 so any cothread fault enters exc_segfault whose kern_trap first statement (mycpu, trap.c:585) immediately re-faults, and SA_NODEFER+empty-mask re-delivers on the same stack without bound: measured 307,833 handler re-entries (3/3 deterministic) before the host killed the process (SIGILL/core on delivery failure) \u2014 the whole vkernel dies with no panic, no dump path, no diagnostic, versus the real kernels #DF->dblfault_handler->panic. Latent trigger (requires a cothread-side fault, e.g. a vkernel driver bug or bad DMA pointer in a disk/net/console cothread executing guest-issued I/O), so severity Info/hardening; the deterministic lwkt-thread recursion instance of the same install is DF-5338 (trap.c fall-through root). Fix semantics demonstrated: the exc_nesting guard from fix.diff converts the death to a one-line diagnostic + true SIGSEGV with core after exactly 2 handler entries; guard applied (combined with DF-5586s) into the guest /usr/src, VKERNEL64 rebuilt cleanly, in-vkernel fault storm still passes.", "reproduced": true, "impact": "dos", "confidence": "certain", "exploit_chain": "", "evidence": "findings/poc/DF-5587/build_and_run.log (3x: RECURSION_DEPTH=307833, SILENT_DEATH_CONFIRMED, termsig=4 core=128); fix_semantics.log (corefixed: vkernel: recursive fault in exc_segfault, termsig=11, handler_entries=2, FIX_SEMANTICS_OK); code: exception.c:222-229 + cothread.c:143-148 (tls_set_gs(0)) + machintr.c:205-211 (fault signals unmasked) + trap.c:585 (mycpu first)", "kernel_refs": [ "sys/platform/vkernel64/x86_64/exception.c:222", "sys/platform/vkernel64/platform/cothread.c:143", "sys/platform/vkernel64/platform/machintr.c:205", "sys/platform/vkernel64/x86_64/trap.c:585" ], "poc_changes": "Authored from scratch (no seed): exact init_exceptions install flags + NULL TLS base first dereference (the %gs==0 condition); shared MAP_ANON page for the cross-fork recursion counter; corefixed.c needed the shared-page counter too (COW hid the depth in the parent).", "attempts": 3, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 02:54:02 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64", "runtime_sec": 300, "guest_dirty": 0, "build_cmd": "sh build.sh (cc -static -O2 -o coresig coresig.c); cc -static -O2 -o corefixed corefixed.c", "run_cmd": "./coresig; ./corefixed", "code_hash": "d7029b99ccd53ad7007e65e7c5cc5db717902e7d3bb3175655cf8bb16c57c793", "notes": "Info/hardening severity: crash-equivalent outcome to a vkernel panic, the delta is silent death (no panic banner, no dump, no exit diagnostics) from any cothread fault. Guest reset with-src before return.", "recommended_fix": "exc_segfault re-entrancy guard: exc_nesting counter; on re-entry write(2) a diagnostic, reset the four fault dispositions to SIG_DFL and raise(signo) for an honest, core-dumping death", "fix_status": "fixed", "fix_baseline_reproduced": true, "fix_patched_reproduced": true, "fix_verdict": "fix.diff guard semantics proven by corefixed (2 entries + diagnostic + true SIGSEGV vs 307833 silent); applied (combined with DF-5586s guard) to guest /usr/src, VKERNEL64 rebuilt cleanly, in-vkernel fault storm passes unchanged (STORM_RC=0, ALIVE).", "fix_evidence": "findings/poc/DF-5587/fix_semantics.log; findings/poc/DF-5586/run_vk.log (patched-vkernel storm); fix.diff" } |