⬢ DragonFlyBSD Kernel Audit
DF-2421 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-2421",
  "status": "reproduced",
  "verdict": "REPRODUCED on live AHCI hardware: an operator-privileged XPT_SCSI_IO submitted via /dev/pass0 with CAM_DIR_NONE carries a raw user-supplied csio->data_ptr into ahci_xpt_scsi_disk_io (passsendccb skips cam_periph_mapmem for DIR_NONE, scsi_pass.c:565-568; cam_periph.c:677 returns untouched), where the synthetic handlers write it unconditionally. Surgical non-fatal proof: single INQUIRY CCBs zeroed+overwrote kernel bss hostname[] and .data version[] at byte-exact chosen offsets, each read back via sysctl (kern.hostname truncated from 64 to exactly 8/16/40 chars; kern.version cut at +64), CCBs returning CAM_REQ_CMP silently; READ_CAPACITY (:1159) and EVPD page_inquiry (:1693) paths proven the same way. Panic proofs: data_ptr=NULL -> Fatal trap 12 fault VA 0x0 supervisor WRITE Stopped at memset+0x2b (= bzero(rdata,rdata_len)); data_ptr=0xfffff800deadf000 -> trap 0xc at the same write instruction, kernel panics faulting the caller-chosen address. uid=0 escalation not completed: primitive is write-only with constrained content (zeros + inquiry header + IDENTIFY-derived strings), no kernel-read oracle from the same interface to locate dynamic targets; the arbitrary-address write itself (where+length fully controlled) is demonstrated against live kernel .data/.bss.",
  "reproduced": true,
  "impact": "panic",
  "confidence": "certain",
  "exploit_chain": "operator/root opens /dev/passN (0600 root:operator) -> CAMIOCOMMAND XPT_SCSI_IO, CAM_DIR_NONE, data_ptr=<kernel VA>, dxfer_len=<len>, INQUIRY/READ_CAPACITY/EVPD -> passsendccb skips mapmem -> ahci_xpt_scsi_disk_io bzero/bcopy at the raw pointer -> silent arbitrary kernel-address write (demonstrated on hostname[]/version[]) or panic (NULL / unmapped VA)",
  "evidence": "run.log (verbatim: hostname 64->8/16/40 chars, version truncated at +64, all CAM_REQ_CMP), panic-null.txt (fault 0x0, memset+0x2b), panic-addr.txt (chosen VA fault), fix-validation.log (patched kernel: all 5 attack modes -> CAM_REQ_INVALID 0x6, zero corruption, normal I/O unaffected)",
  "kernel_refs": [
    "sys/dev/disk/ahci/ahci_cam.c:1083",
    "sys/dev/disk/ahci/ahci_cam.c:1109",
    "sys/dev/disk/ahci/ahci_cam.c:1159",
    "sys/dev/disk/ahci/ahci_cam.c:1693",
    "sys/bus/cam/scsi/scsi_pass.c:565",
    "sys/bus/cam/cam_periph.c:677",
    "sys/bus/cam/cam_xpt.c:3888"
  ],
  "poc_changes": "no runnable PoC existed; wrote ahcipoc.c (modes inquiry-null / inquiry-addr / readcap-addr / evpd-addr / surgical / read10 / atapi), built against the guests /usr/src CAM headers (/usr/include/cam is not installed); required live AHCI hardware attached at QEMU launch (up_ahci.sh)",
  "attempts": 7,
  "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": 900,
  "guest_dirty": 0,
  "build_cmd": "guest: cc -O -I/usr/src/sys -I/usr/src/sys/bus -o ahcipoc ahcipoc.c",
  "run_cmd": "./ahcipoc surgical <kernva-hex> 36   (and inquiry-null / inquiry-addr fffff800deadf000)",
  "code_hash": "56eeebd163c12d51818b8c5018719e4e47e5ea7e6182095769c23210ec80b9bb",
  "notes": "content control: zeros + fixed INQUIRY/READ_CAPACITY header fields + IDENTIFY-derived vendor/product/serial strings (serial/model operator-chosen on emulated media). Symbol addresses from /boot/kernel/kernel symtab (no KASLR). Fix kernel #1 Thu Oct 15 02:34:42 UTC 2026.",
  "recommended_fix": "reject CAM_DIR_NONE CCBs with dxfer_len > 0 in ahci_xpt_scsi_disk_io() and ahci_xpt_scsi_atapi_io() before any data_ptr dereference (fix.diff, validated: CAM_REQ_INVALID)",
  "fix_status": "fixed",
  "fix_baseline_reproduced": true,
  "fix_patched_reproduced": false,
  "fix_verdict": "fixed",
  "fix_evidence": "fix-validation.log: patched kernel, all five attack modes return cam_status 0x6 (CAM_REQ_INVALID), hostname/version unchanged, read10/dd normal (260-720 MB/s)"
}