⬢ DragonFlyBSD Kernel Audit
DF-4203 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-4203",
  "status": "reproduced",
  "verdict": "Race consequence REPRODUCED twice on live AHCI hardware (trigger state injected; natural arming remains PM-hardware-gated). With at->at_probe forced to ATA_PROBE_NEED_IDENT (its only production producer is the PM hard-reset completion ahci_pm.c:876; QEMU has no SATA PM device model) while dd readers, a camcontrol reset loop and a pass XPT_SCSI_IO storm run, the unlocked re-probe at ahci_cam.c:989-990 panics the kernel within 25-45 seconds in exactly the predicted double-completion mode: run 2 panic ccb->ccb_xa.state != ATA_S_PUT failed in ahci_put_ccb at ahci.c:3321 with backtrace ahci_cam_probe -> ahci_poll -> ahci_port_intr -> ahci_ata_complete_disk_rw -> ahci_put_ccb x2 (the unlocked probe polls a command already completed elsewhere and free-lists the ccb twice); run 1 panic xa->state != ATA_S_ONCHIP && xa->state != ATA_S_PUT in ahci_ata_cmd_done at ahci.c:3776 from the port thread, with the panic kprintf character-interleaved on the serial console with a concurrent probes Found-DISK kprintf from another CPU. CONTROL: the identical load WITHOUT arming runs 70s clean (14650 pass CCBs, single boot probe, no panic) - the NEED_IDENT branch is the differentiator. Fix (ap_lock bracket around the re-probe, mirroring the dispatch 60 lines below) validated: the identical armed race on the patched kernel completed with 1518 serialized re-probes, zero panics/assertions. Caveat kept honest: had the trigger not been injected, the branch cannot be entered on this guest (no PM), so natural-world reproduction still requires physical port-multiplier hardware.",
  "reproduced": true,
  "impact": "panic",
  "confidence": "likely",
  "exploit_chain": "",
  "evidence": "panic-race2.txt (double-put backtrace through ahci_cam_probe), panic-race.txt (port-thread double completion + interleaved concurrent probe kprintf), run.log (race + clean control transcript), race.sh, fix-validation.log (patched kernel: armed race clean, 1518 probes, 0 panics)",
  "kernel_refs": [
    "sys/dev/disk/ahci/ahci_cam.c:989",
    "sys/dev/disk/ahci/ahci.c:940",
    "sys/dev/disk/ahci/ahci.c:3321",
    "sys/dev/disk/ahci/ahci.c:3776",
    "sys/dev/disk/ahci/ahci_pm.c:876"
  ],
  "poc_changes": "first round (this pack) concluded untested: no AHCI controller and a firmware-level boot hang. This round: (1) got live AHCI hardware by attaching -device ahci + ide-hd/ide-cd at QEMU launch with explicit bootindex pinning (the old hang was an invocation artifact), (2) reused the DF-2420 rigs arm command to force NEED_IDENT on the real port (no driver logic copied), (3) built race.sh combining dd readers + camcontrol reset loop + pass CCB storm + arming, plus a no-arming control",
  "attempts": 4,
  "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": 1200,
  "guest_dirty": 0,
  "build_cmd": "rig: see ../DF-2420/build.sh (df2420rig.ko provides the arm command); race.sh needs no build",
  "run_cmd": "sh race.sh   (dd storm + camcontrol reset loop + pass read10s + sysctl dev.df2420rig=\"arm 0 45\")",
  "code_hash": "b609b725e433957f2e88203338120bb13012fc92e6f9e8b92f14a4d74396f5db",
  "notes": "trigger state injected via rig because the only production producer of NEED_IDENT is PM hard-reset completion (ahci_pm.c:876) and QEMU has no PM device model; everything downstream of the arming is production code on live hardware; two distinct panic signatures across two runs + clean control. Fix kernel #1 Thu Oct 15 02:34:42 UTC 2026.",
  "recommended_fix": "bracket the re-entrant ahci_cam_probe() in the XPT_SCSI_IO path with ahci_os_lock_port()/ahci_os_unlock_port() (fix.diff, validated: armed race runs clean with the probe serialized)",
  "fix_status": "fixed",
  "fix_baseline_reproduced": true,
  "fix_patched_reproduced": false,
  "fix_verdict": "fixed",
  "fix_evidence": "fix-validation.log: patched kernel, identical armed race (25s arm) -> no panic, no assertions, 1518 Found-DISK re-probes (branch exercised, now serialized), guest healthy"
}