DF-5607 / verdict.json
{ "finding_id": "DF-5607", "status": "reproduced", "reproduced": true, "impact": "dos", "confidence": "certain", "verdict": "cothread.c runs every vkernel cothread with %gs=0 (tls_set_gs(0), cothread.c:149) while cpu_mask_all_signals() (cothread.c:109/:143 -> machintr.c:205-211) blocks only the 8 interrupt signals, leaving SIGSEGV/SIGBUS/SIGTRAP/SIGFPE deliverable to the process-wide SA_NODEFER exc_segfault handler (exception.c:227-233): any cothread fault recurses exc_segfault->kern_trap->mycpu-load->fault without bound. Proven on a real VKERNEL64 boot (DF-5587 proved the dynamic only in a standalone model): an LD_PRELOAD shim injects SIGSEGV in the vktimer cothread (verified %gs base NULL via get_tls_area) during cothread_sleep; 3/3 boots the whole vkernel dies SILENTLY (no panic, no dump, no console output), core shows signal 4 (SIGILL from signal-frame push failure) with the deepest frame in _get_mycpu (thread.h:77 movq %gs:globaldata) under kern_trap (trap.c:585) under exc_segfault (exception.c:269), cpu threads parked unaware. Fix validated on a rebuilt vkernel: __thread exc_nesting guard converts the death to a one-line diagnostic + honest SIGSEGV (2 handler entries vs ~308k). Latent trigger (needs a cothread-side fault: driver bug, corrupted ring, stack overflow), so severity Low like DF-5587; the delta is the file-owned mask discipline + real-boot reproduction + real-boot fix validation.", "exploit_chain": "", "evidence": "findings/poc/DF-5607/run.baseline.log (COTDFAULT markers then SILENT death), baseline_core.txt (signal 4, #0 _get_mycpu thread.h:77 / #1 kern_trap trap.c:585 / #2 exc_segfault exception.c:269), run.clean.log (healthy control boot), run.fixed.log + fixed_core.txt (recursive-fault diagnostic, signal 11 via raise), build.log, cotdfault.c, run.sh, build_image.sh", "kernel_refs": [ "sys/platform/vkernel64/platform/cothread.c:109", "sys/platform/vkernel64/platform/cothread.c:143", "sys/platform/vkernel64/platform/cothread.c:149", "sys/platform/vkernel64/platform/cothread.c:186", "sys/platform/vkernel64/platform/machintr.c:205", "sys/platform/vkernel64/x86_64/exception.c:227", "sys/platform/vkernel64/x86_64/trap.c:585", "sys/dev/virtual/vkernel/net/if_vke.c:672" ], "poc_changes": "Authored from scratch (no seed). First attempt keyed on sigblock()+%gs==NULL alone and missed (vkernel crit sections never sigblock; first %gs-NULL sigblock fires pre-boot), so the shim was reworked to nanosleep()+get_tls_area(473) cothread detection, which fires exactly in vktimer_threads cothread_sleep after tls_set_gs(0).", "attempts": 3, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64", "runtime_sec": 2100, "guest_dirty": 0, "build_cmd": "cd /usr/src && make -j6 nativekernel KERNCONF=VKERNEL64 ; cc -shared -O2 -fPIC -o /root/cotdfault.so cotdfault.c ; sh build_image.sh", "run_cmd": "sh /root/run5607.sh clean | fault (boots kernel.debug -m 512m -r /vkroot.img -n 2 -e init_path=/bin/vkinit, LD_PRELOAD=/root/cotdfault.so in fault mode)", "code_hash": "2e89a3e64f4be14b0a4101ad78d40a6767747ecf7caa55db123cfb4454fc2917", "notes": "Silent-death DoS class, vkernel-scope (host userland process). Masking fault signals in the cothread would trade silent death for silent livelock (blocked sync signal = insn retry loop) and is NOT the fix; the guard in exc_segfault is. Cross-ref: DF-5587 (exception.c side, standalone-model proof); this packs fix validation also validates DF-5587s fix on a real vkernel.", "recommended_fix": "Apply the exc_segfault __thread re-entrancy guard (fix.diff; shared locus with DF-5587) and document in cothread.c that fault signals are intentionally deliverable and must never fault in a cothread.", "fix_status": "fixed", "fix_baseline_reproduced": true, "fix_patched_reproduced": false, "fix_verdict": "Guest /usr/src patched with fix.diff, VKERNEL64 rebuilt (RC=0), identical injection re-run: console prints vkernel: recursive fault in exc_segfault and the process dies of a true SIGSEGV (core: signal 11 via raise->_thr_send_sig->lwp_kill) after 2 handler entries. Silent unbounded recursion eliminated.", "fix_evidence": "findings/poc/DF-5607/fix.diff; run.fixed.log (diagnostic line); run.fixed.driver.log; fixed_core.txt (signal 11); baseline vs fixed contrast in VERDICT.md" } |