{
  "finding_id": "DF-5403",
  "status": "reproduced",
  "reproduced": true,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "sg(4) never rejects SG_IO with dxferp==NULL and dxfer_len>0: sgsendccb() (scsi_sg.c:868-869) only runs cam_periph_mapmem() when data_ptr != NULL, so the CCB reaches the SIM with data_ptr==NULL and dxfer_len>0, and the transports dereference it. On the stock QEMU PIIX3 ATAPI rig the nata transports INQUIRY special case does bzero(csio->data_ptr=NULL, dxfer_len) (atapi-cam.c:561->582) - deterministic Fatal trap 12, supervisor write to address 0x0, Stopped at memset+0xd5 (inlined bzero), reproducible at will. On ahci SATA disks the same synthesized-INQUIRY bzero exists (ahci_cam.c:1083->1097), and commands that instead reach ahci_ata_cmd/ahci_load_prdt make bus_dmamap_load(NULL, len) build a PRDT segment at PHYSICAL address 0 (pmap_extract fails, _bus_dma_extract returns 0), i.e. device-controlled DMA into physical page 0 (DIR_IN) or disclosure of physical page 0 to the device (DIR_OUT). On a stock kernel the bug is latent ONLY because the sibling ABI bug DF-5402 blocks the SG_IO entry with EFAULT; it was reproduced on an ABI-fix-only kernel and the panic disappears with the NULL-data validation and only that change (EINVAL returned, sanity SG_IO unaffected). Device is root/operator-gated, so this is a root-triggerable kernel panic (same gate as DF-2281) rather than an unpriv escalation.",
  "exploit_chain": "open(/dev/sg0) as root -> SG_IO{dxfer_direction=FROM_DEV, cmdp=INQUIRY(12 00 00 00 ff 00), dxferp=NULL, dxfer_len=512} -> sgioctl accepts, cam_fill_csio(data_ptr=NULL, dxfer_len=512) -> sgsendccb skips mapmem (data_ptr==NULL) -> xpt_scsi_io (no validation) -> atapi_action XPT_SCSI_IO -> INQUIRY case (alloc len 0xff > 36) -> bzero(NULL, 512) -> Fatal trap 12 write va 0x0 -> panic. Non-INQUIRY variant on ahci: bus_dmamap_load(NULL, len) -> phys-0 PRDT -> DMA at physical address 0.",
  "evidence": "panic.abifixed.txt (serial console: Fatal trap 12, fault virtual address 0x0, supervisor write data, Stopped at memset+0xd5, process = poc5402); run.null-trigger-hang.log (ioctl never returns); run.abifixed-sanity.log (same kernel: real-buffer SG_IO works, so the CCB path is healthy except for the NULL pair); run.patched.log (full-fix kernel #2: rc=-1 errno=22 EINVAL, guest stays up, sanity unchanged); kernel #1 experiment in VERDICT.md (dead-check placement still panicked, confirming the sink).",
  "kernel_refs": [
    "sys/bus/cam/scsi/scsi_sg.c:868",
    "sys/bus/cam/scsi/scsi_sg.c:543",
    "sys/bus/cam/cam_xpt.c:2977",
    "sys/dev/disk/nata/atapi-cam.c:561",
    "sys/dev/disk/nata/atapi-cam.c:582",
    "sys/dev/disk/nata/atapi-cam.c:756",
    "sys/dev/disk/ahci/ahci_cam.c:1083",
    "sys/dev/disk/ahci/ahci_cam.c:1097",
    "sys/dev/disk/ahci/ahci.c:2025",
    "sys/platform/pc64/x86_64/busdma_machdep.c:568"
  ],
  "poc_changes": "poc5402.c written from scratch (no seed); null mode is the trigger, sanity mode proves the same kernel runs well-formed SG_IO fine. Initial trigger attempt on the stock kernel returned EFAULT, which led to discovering the DF-5402 ABI blocker; verification then used an ABI-fix-only kernel to un-mask this bug.",
  "attempts": 3,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly v6.5.0.1712.g89e6a-DEVELOPMENT #0..#2 x86_64 (stock Jun 29 2026; ABI-fixed Oct 4; full-fix Oct 4; QEMU Virtual CPU 2.5+, 6 vCPU)",
  "runtime_sec": 3873,
  "guest_dirty": 1,
  "build_cmd": "cc -O -o poc5402 poc5402.c   (in-guest, gcc 8.3)",
  "run_cmd": "./poc5402 sanity && ./poc5402 null   (root, /dev/sg0; on a kernel where SG_IO is callable, i.e. with the DF-5402 ABI fix)",
  "code_hash": "1618e8e10dad5df503a028973b0fca9cb031d1ec5cae423066b9de22ddb1b1c6",
  "notes": "Latency caveat for triage: on an UNPATCHED stock kernel this exact trigger is blocked by DF-5402 (EFAULT before the CCB is built) - the two defects are independent, and fixing DF-5402 alone turns this into a live, deterministic panic; the fixes must land together (fix.diff contains both). pass(4) builds the same shape of CCB from user data and should be audited for the same NULL-pair acceptance. Write target is fixed (address 0), not attacker-steerable, so no uid=0 chain was pursued; impact is panic/phys-0 DMA.",
  "recommended_fix": "In sgioctls SG_IO case, after the direction switch, reject dir != CAM_DIR_NONE && req.dxferp == NULL && req.dxfer_len != 0 with EINVAL (fix.diff part 2); land together with the DF-5402 ABI indirection fix.",
  "fix_status": "fixed",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 1,
  "fix_verdict": "Baseline (ABI-fix-only kernel #0): Fatal trap 12 write va 0x0 in memset/bzero <- atapi INQUIRY case, 2/2 trigger runs (once via the 3-mode run, once standalone; identical IP ffffffff80bca655). Patched (kernel #2 = ABI fix + NULL-data validation, make -j6 nativekernel rc=0 under -Werror, installkernel, reboot): same PoC returns rc=-1 errno=22 (EINVAL), no trap, guest stays up, sanity SG_IO still returns drive INQUIRY (no false positives).",
  "fix_evidence": "run.patched.log (EINVAL, poc-exit=0, guest up); panic.abifixed.txt vs absence of any trap in run.patched.log; fix.diff (part 2 = the validation); VERDICT.md behavior table."
}