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

CAMGETPASSTHRU leaks stale kernel pointers and prior I/O data via whole-CCB bcopy

Summary

cam_periph_ioctl CAMGETPASSTHRU case pulls CCB from periph->ccb_list (reused pool) runs xpt_setup_ccb+xpt_action(XPT_GDEVLIST) which only init ccb_hdr routing fields and cgdl fields then bcopy(ccb addr sizeof(union ccb)) copies entire huge union ccb to userspace. Every ccb_hdr field not touched by xpt_setup_ccb - cbfcnp (kernel text pointer) periph_priv.entries[*].ptr sim_priv.entries[*].ptr path (kernel heap pointer) saved_ccb_ptr (=ppriv_ptr0 kernel heap pointer into periph softc) retry_count timeout - plus entire non-header union body (csio.cdb_io csio.data_ptr csio.sense_data from prior SCSI I/O) leaked verbatim. Yields KASLR bypass (cbfcnp function pointer into compiled driver code) plus kernel heap addresses and stale SCSI CDB/sense bytes. All CAM periph d_open gates SYSCAP_RESTRICTEDROOT so attacker already root-equivalent. Useful in capability-confined-root (jail with RESTRICTEDROOT) and as KASLR primer for subsequent kernel-exploit chain. [VERIFIED pass2: reproduced - returned union ccb carries path timeout_ch sim_priv pointers matching SIM-softc ground truth exactly across 3 runs; first bzero fix caught still-leaking by A/B, scrubbed-shadow fix-validated zeroed]

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2266 Β· 3 files
FileTypeDescriptionSize
run_baseline_leak.log run-log path/timeout_ch/sim_priv leak x3 runs 1.6 KB view raw
dfcam_harness.c support fake SIM whose sim_priv ground truth is 0x51510000 19.7 KB view raw
fix.diff suggested-fix scrubbed shadow copy-out (never touches pooled CCB) 2.2 KB view raw

Fix verification

fixed
↓ fix.diffper-fix-DF-2266

Confirmed kernel references

Detail

Exploit chain

root ioctl(CAMGETPASSTHRU) on pass/ses/ch/cd/sa/pt -> pooled CCB stale header + union body -> whole-union bcopy to user -> cam_path/callout/SIM-softc* disclosure

Evidence (decisive lines)

run_baseline_leak.log: ATTR path/timeout_ch/sim_priv values x3 runs; ground truth 0x51510000 in stage_05/ab_ab02 ground sysctl output

PoC changes

Authored leak66 driver + ground-truth marker in fake SIM; iterated the FIX twice after A/B caught the preserve-bzero variant still leaking path/timeout_ch

Verified recommended fix

copy out through a zeroed shadow union ccb (scrubbed ccb_hdr + cgdl only), never the pooled CCB

Verdict

CAMGETPASSTHRU on a real compiled cam_periph.c bcopies the whole 720-byte pooled union ccb to userspace: the returned CCB contained ccb_h.path=0xfffff8008d6c10c0, ccb_h.timeout_ch=0xfffff8008d6a0c38, and ccb_h.sim_priv.entries[0].ptr=0x51510000 matching the rig SIM softc ground truth exactly, identical across 3 runs (deterministic per boot, KASLR primer). First fix attempt (bzero pooled CCB) still leaked the two preserved pointers and was replaced by a scrubbed-shadow copy-out; A/B after the final fix shows zero kernel pointers with CAMGETPASSTHRU still functional. Root-equivalent gate (0600 root:operator + SYSCAP_RESTRICTEDROOT): Low severity confirmed. A/B: Fixed kernel: CAMGETPASSTHRU returns zeroed path/timeout_ch/sim_priv/link fields (no kernel pointers) while still returning the correct pass device.