β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-2278

CAM_DATA_PHYS / CAM_SG_LIST_PHYS accepted by pass allowing user-supplied raw physical DMA addresses to reach the SIM

Summary

passsendccb() treats CAM_DATA_PHYS only as hint to skip cam_periph_mapmem() - never rejects it. User issuing XPT_SCSI_IO with CAM_DATA_PHYS bypasses bounce-buffer copyin path entirely; user-supplied csio.data_ptr forwarded unmodified to SIM which interprets it as kernel/DMA address. XPT device explicitly rejects CAM_DATA_PHYS for XPT_DEV_MATCH (cam_xpt.c:1133). This asymmetry is defense-in-depth gap: if device node ever exposed to less-privileged subject (common FreeBSD operator-group relaxation) pass becomes arbitrary physical memory read/write primitive via storage controller. ahci SIM forwards value as-is to DMA engine without re-checking source. On systems without restricting IOMMU this is arbitrary kernel-memory read/write. [VERIFIED pass2: reproduced on stock - CAM_DATA_PHYS INQUIRY panics at atapi insl directly to the forwarded raw user address, raw kernel address variant yields device-controlled kernel write characterized; root-only on stock; reject-flags fix-validated EINVAL no panic]

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2278 Β· 3 files
FileTypeDescriptionSize
panic_stock_ata_pio.txt panic stock kernel: insl into forwarded user address 2.1 KB view raw
run_rig_capture.log run-log SIM received raw PHYS data_ptr=0x414100000000 verbatim 883 B view raw
fix.diff suggested-fix reject CAM_DATA_PHYS/CAM_SG_LIST_PHYS in passsendccb 948 B view raw

Fix verification

fixed
↓ fix.diffper-fix-DF-2278

Confirmed kernel references

Detail

Exploit chain

privileged CAMIOCOMMAND XPT_SCSI_IO + CAM_DATA_PHYS + arbitrary data_ptr -> mapmem skipped -> raw address forwarded to SIM -> transport DMA/PIO uses it as kernel address -> panic (demonstrated) or device-data write to arbitrary kernel memory (characterized)

Evidence (decisive lines)

panic_stock_ata_pio.txt (Fatal trap 12, ata_pio_read+0x10d, fault 0x7fffffdfd340); run_rig_capture.log (SIM received raw PHYS data_ptr=0x414100000000); ab_ab03 EINVAL + phys_seen=0

PoC changes

Authored phys/physpanic PoCs; the accidental first run (before output staging) produced the stock panic transcript, later reproduced deliberately

Verified recommended fix

reject CAM_DATA_PHYS and CAM_SG_LIST_PHYS in passsendccb for XPT_SCSI_IO (EINVAL)

Verdict

passsendccb forwards the raw user-supplied csio.data_ptr when CAM_DATA_PHYS is set: on the stock kernel the atapi transport consumed it as a kernel PIO destination and panicked (ata_pio_read insl to user address 0x7fffffdfd340, transcript captured); on the rig kernel the fake SIM received the arbitrary marker 0x414100000000 verbatim (flags 0x200040) while XPT_DEV_MATCH rejects the same flag with EINVAL. A raw kernel address instead of a user address yields device-controlled data written to kernel memory (privileged arbitrary write). Fix (reject the flags) validated: EINVAL, SIM phys_seen=0, control path intact. Root-only on stock (0600 root:operator + SYSCAP_RESTRICTEDROOT): Low/privesc-bucket defense-in-depth correct. A/B: Fixed kernel: CAM_DATA_PHYS ioctl returns EINVAL with no panic (baseline stock kernel faulted in ata_pio_read); control INQUIRY unaffected; SIM-side capture shows phys_seen=0.