⬢ DragonFlyBSD Kernel Audit
DF-5408 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-5408",
  "status": "reproduced",
  "verdict": "Reproduced as a validation bypass: sys_sigreturn strips PSL_VM_UNSUPP from the copy it validates (cpu_regs.c:366-369) but bcopy()s the raw mc_rflags into the trapframe (cpu_regs.c:441), so a guest user installs a VM-set rflags that EFL_SECURE exists to reject (proven: baseline accepts the poisoned frame and survives; fixed kernel prints sigreturn: rflags = 0x20206 and EINVALs the identical input). The bit provably survives both the vkernels and the hosts cpu_sanitize_frame into the host return-to-user path. On this rigs CPU (Skylake/KVM) VM at iretq/sysret is silently masked, so no fault manifests; per SDM other implementations #GP at the doreti iretq (DF-5335 special case), reachable from an unprivileged in-vkernel user. Impact recorded as none because no fault, leak, or escalation is realizable on the tested hardware.",
  "reproduced": true,
  "impact": "none",
  "confidence": "certain",
  "exploit_chain": "guest user -> signal handler poisons uc_mcontext.mc_rflags |= 0x20000 -> sigcode trampoline SYS_sigreturn -> EFL_SECURE sees stripped copy, raw mcontext installed into go_user trapframe -> host vmspace_ctl(RUN) -> host cpu_sanitize_frame whitelists 0x20000 (mask 0x274dd5) -> host return-to-user loads rflags with VM -> hardware masks it here (SDM: #GP(0) at iretq elsewhere). Ceiling on this rig: silent masking; on enforcing hardware: guest-triggered kernel-mode #GP on the doreti/espfix path.",
  "evidence": "run_suite.log (baseline: mode1 SURVIVED sigreturn = bypass), run_fixed.log (fixed: sigreturn: rflags = 0x20206 + process terminated, mode0 unchanged), disasm_vk_baseline.txt (and ~0x20000 check-strip + 0xc8 raw bcopy), disasm_host.txt (host mask 0x274dd5), disasm_vk_fixed.txt (mask 0x254dd5), iretvm.c (hardware probe with working control), vmflag.c modes 0/1/2/5/6",
  "kernel_refs": [
    "sys/platform/vkernel64/x86_64/cpu_regs.c:366",
    "sys/platform/vkernel64/x86_64/cpu_regs.c:369",
    "sys/platform/vkernel64/x86_64/cpu_regs.c:425",
    "sys/platform/vkernel64/x86_64/cpu_regs.c:441",
    "sys/platform/pc64/x86_64/machdep.c:916",
    "sys/platform/pc64/x86_64/machdep.c:1040"
  ],
  "poc_changes": "Seed was a source-analysis only; wrote vmflag.c (modes 0/1/2/5/6: control, sigreturn-poison, vmspace_ctl RUN frames, signal storms), iretvm.c CPL3 iretq hardware probe (two earlier revisions were defective: 4-slot frame and stack skew; final uses the correct 5-slot long-mode iretq frame), the vkernel build/image/run rig adapted from DF-5337, and fix.diff generated with diff -u against the pristine tree.",
  "attempts": 6,
  "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": 3900,
  "guest_dirty": 1,
  "build_cmd": "sh build_kernel.sh; sh build_image.sh (vmflag: cc -static -O2 -pthread)",
  "run_cmd": "sh run_suite.sh baseline  # then: cd /usr/src && patch -p1 < fix.diff && make -j6 nativekernel KERNCONF=VKERNEL64 && sh run_suite.sh fixed",
  "code_hash": "ca21e7001a7df69bdf6f37d3e91230e33bd5f3a4560886334b8d2ca3aee1fae0",
  "notes": "Same code shape exists in pc64 sys_sigreturn (host side) \u2014 verified by disassembly of the running guest kernel; the fix.diff covers both. Mode 5 (poisoned sigreturn + SIGUSR2 storm) survives on both baseline and fixed: DragonFlys sigreturn-exit does not re-check pending signals (mask restore without signotify) and the quickret SYSRETQ masks VM, so the doreti/iretq variant could not be forced deterministically here.",
  "recommended_fix": "Remove the PSL_VM_UNSUPP pre-strip in sys_sigreturn so EFL_SECURE validates the rflags actually installed; drop PSL_VM_UNSUPP from cpu_sanitize_frames mask (vkernel64 + pc64).",
  "fix_status": "fixed",
  "fix_baseline_reproduced": true,
  "fix_patched_reproduced": false,
  "fix_verdict": "fixed",
  "fix_evidence": "run_fixed.log: mode 1 rejected with kernel kprintf sigreturn: rflags = 0x20206 and process terminated (baseline accepted + survived); mode 0 control unchanged; disasm_vk_fixed.txt shows sanitize mask 0x254dd5 (VM removed) and disasm_vk_sigreturn_fixed.txt shows the check-strip gone."
}