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)
PoC verification
Evidence pack
findings/poc/DF-2266 Β· 3 files| File | Type | Description | Size | |
|---|---|---|---|---|
| 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
fixedConfirmed 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.
No comments yet.