⬢ DragonFlyBSD Kernel Audit
DF-5607 / verdict.json
← back to finding ↓ download raw
{
  "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"
}