{
  "finding_id": "DF-2423",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "Reproduced on the QEMU guest with a verbatim-TU kernel-compiled harness: the real ahci_pm_read (ahci_pm.c:976-978) and ahci_pm_write (:1013-1015) deref xa->fis (first struct member, offset 0) immediately after ahci_ata_get_xfer with no NULL check, panicking with Fatal trap 12 at fault VA 0x0 (dfx_pm_read+0x2b and dfx_pm_write+0x2c, IPs cross-checked against disassembly) whenever the per-port CCB free list is exhausted (ahci_get_ccb NULL, ahci.c:3675-3678). Control run with a free CCB completes normally through the real code path; fix.diff (NULL check returning EBUSY) was A/B validated - panic gone, control path bit-identical. Reachable in production from the PM async-notify/hotplug state machine (ahci.c:841, :891) which runs before exclusive access while CAM NCQ I/O holds all AHCI_REG_CAP_NCS (up to 32) per-port slots shared across PM targets; requires AHCI hardware with a port multiplier. Hardware-gated kernel DoS/panic, not privesc: fixed-offset supervisor LOAD of a guaranteed-not-present page in kernel-thread contexts; no unprivileged user-context path exists (CAM xpt entries are 0600 root:operator), though DragonFly does permit user mmap of page 0, which is why the guard is worth having.",
  "exploit_chain": "",
  "evidence": "panic.txt (phase2: Fatal trap 12, fault virtual address 0x0, dfx_pm_read+0x2b 0xffffffff80a800cb, backtrace dfx_pm_read <- dfx2423_sysctl); panic.write.txt (phase3: dfx_pm_write+0x2c 0xffffffff80a8018c); disas.baseline-vs-fixed.txt (baseline has no check between callq get_xfer and mov (%rax),%rdx; fixed kernel inserts test %rax,%rax; je); run.control.log (free CCB: rv=0 data=ddccbbaa, FIS encodings exact, counters 2/2/2/2); run.fixed.log (phases 1-3 on fixed kernel: EBUSY 16, no crash, guest up); build.sh sha256 gate pins the TU to the pristine tree hash db2f5784...ac66",
  "kernel_refs": [
    "sys/dev/disk/ahci/ahci_pm.c:976",
    "sys/dev/disk/ahci/ahci_pm.c:978",
    "sys/dev/disk/ahci/ahci_pm.c:1013",
    "sys/dev/disk/ahci/ahci_pm.c:1015",
    "sys/dev/disk/ahci/ahci.c:3669",
    "sys/dev/disk/ahci/ahci.c:3675",
    "sys/dev/disk/ahci/ahci.c:3297",
    "sys/dev/disk/ahci/ahci.c:841",
    "sys/dev/disk/ahci/ahci.c:891",
    "sys/dev/disk/ahci/atascsi.h:356",
    "sys/dev/disk/ahci/ahci_attach.c:349"
  ],
  "poc_changes": "No seed PoC existed; authored the verbatim-interposition kernel harness from scratch: pristine ahci_pm.c TU included with preprocessor symbol renames (dfx_pm_*) because the stock kernel already contains the ahci driver, three interposed pool functions (get_xfer/ata_cmd/put_xfer) modeling ahci.c:3669-3699, sysctl trigger instead of a device node, and a conf/files + conf/options + DFX2423 config wiring for the kernel build (runtime kldload GPFs on this guest).",
  "attempts": 5,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #2: Mon Oct 19 11:32:07 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/DFX2423 x86_64",
  "runtime_sec": 3600,
  "guest_dirty": 0,
  "build_cmd": "sh /tmp/build.sh (sha256-gated; make -j6 nativekernel KERNCONF=DFX2423 in the guest /usr/src)",
  "run_cmd": "sysctl hw.dfx2423_phase=1|2|3 on the DFX2423 harness kernel",
  "code_hash": "8c3f8d929393b117274cfbb5762fd1511ae38968ac7e3ab72ddd0724f4aad38e",
  "notes": "Privesc closed explicitly: fixed-offset NULL LOAD in kernel-thread contexts on the real attack surface (port thread / CAM xpt thread) - no control of loaded value or store targets, deterministic panic only. DF allows user mmap of page 0 (verified on guest), so the guard matters if a user-context caller ever appears; today the only user-context entries (XPT_PATH_INQ/XPT_ENG_EXEC via /dev/xpt0, 0600 root:operator) are already privileged. Same unchecked get_xfer idiom exists at ahci_cam.c:300,387,539,562,589,693,1082,1524 and ahci.c:4057,4090 (attach/exclusive contexts today) - recommend the same guard there. Panic classification per table: ssh hang RUN_RC=124 + vm.sh status down right after the sysctl.",
  "recommended_fix": "NULL-check the ahci_ata_get_xfer return in ahci_pm_read and ahci_pm_write and return EBUSY (see fix.diff, A/B validated)."
}
