⬢ DragonFlyBSD Kernel Audit
DF-3607 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-3607",
  "status": "inconclusive",
  "reproduced": 0,
  "impact": "none",
  "confidence": "likely",
  "verdict": "ncr_timeout() (ncr.c:5148-5182) completes nccbs that are still armed in the chips DSA when a connected command exceeds its CCB timeout; DragonFly CAM never arms ccb_h.timeout_ch and ncrs XPT_ABORT/XPT_RESET_DEV are unimplemented, so this daemon is the only recovery path. A later phase mismatch reaches ncr_int_ma() with the dead (or reused) nccb found by DSA match (ncr.c:5692-5707, mismatch-return commented out): the chip is either wedged (ncr.c:5775-5782, all HBA I/O hangs) or restarted from stale/mismatched scatter descriptors (ncr.c:5798-5828) -> DMA into released buffers (kernel memory corruption). Runtime: driver made fully live on the audit guest (ncr0 attached to QEMU-emulated LSI 53C895A after a one-line guest-side sym probe change; snooptest passed; CAM probes flowed through ncr_action; the daemons completion path observed firing 90+ times). The race window itself needs a SCSI target that stalls mid-phase past tlimit and then resumes; stock QEMU scsi devices cannot stall on demand, so the trigger binary (builds clean, /tmp/ncr_timeout_race) could not be aimed at a pass device (no INQUIRY completes through the chip on the emulator). Source-certain; runtime choreography not enterable on this guest.",
  "exploit_chain": "",
  "evidence": "VERDICT.md (line-accurate trace); run.log (daemon path live on guest, attach + COMMAND FAILED + timeout nccb lines); env.txt (guest uname + binaries); fix.diff; ncr_timeout_race.c",
  "kernel_refs": [
    "sys/dev/disk/ncr/ncr.c:5148",
    "sys/dev/disk/ncr/ncr.c:5160",
    "sys/dev/disk/ncr/ncr.c:5168",
    "sys/dev/disk/ncr/ncr.c:5181",
    "sys/dev/disk/ncr/ncr.c:4116",
    "sys/dev/disk/ncr/ncr.c:4137",
    "sys/dev/disk/ncr/ncr.c:4170",
    "sys/dev/disk/ncr/ncr.c:4452",
    "sys/dev/disk/ncr/ncr.c:5692",
    "sys/dev/disk/ncr/ncr.c:5701",
    "sys/dev/disk/ncr/ncr.c:5775",
    "sys/dev/disk/ncr/ncr.c:5798",
    "sys/dev/disk/ncr/ncr.c:5824",
    "sys/bus/cam/cam_xpt.c:3906"
  ],
  "poc_changes": "replaced cam_errstr with cam_errbuf (DFly camlib); dropped scsi_read_write()/CCB_CLEAR_ALL_EXCEPT_HDR (not in DFly userland headers) for a manually built 10-byte READ CDB; kept timeout=1ms per the sketch",
  "attempts": 3,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #2: Tue Sep 15 08:44:40 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64",
  "runtime_sec": 2820,
  "guest_dirty": 0,
  "build_cmd": "cc -O2 -o ncr_timeout_race ncr_timeout_race.c -lcam",
  "run_cmd": "./ncr_timeout_race passN 200   (blocked on this guest: no pass node; chip queue handshake stalls on QEMU lsi emulation)",
  "code_hash": "edc731e7bdff45481d6b6cffd2870a4692f986560697e614750cceef34cb75db",
  "notes": "Guest kernel rebuilt (sym probe neutered + SYM_SETUP_LP_PROBE_MAP=0x04) so ncr claims QEMU lsi53c895a; stock GENERIC boots sym instead because newbus keeps the numerically larger probe result (subr_bus.c:1456), making ncrs -1000 probe lose to syms -20. Guest reset to clean snapshot after the run.",
  "recommended_fix": "In ncr_timeout, do not soft-complete an nccb whose CCB_PHYS still equals the chip DSA - force ncr_init recovery; in ncr_int_ma, refuse to fix up (hard reset) when the matched nccb has magic != CCB_MAGIC or ccb == NULL",
  "fix_status": "not_testable",
  "fix_baseline_reproduced": 0,
  "fix_patched_reproduced": 0,
  "fix_verdict": "fix.diff authored (two guards: connected-ccb timeout -> bus reset; dead-nccb phase fixup -> bus reset). Baseline condition (stalling target mid-phase) is not reproducible on the QEMU lsi emulator, so the patched-kernel A/B could not be run; not_testable.",
  "fix_evidence": "findings/poc/DF-3607/fix.diff"
}