PROBE_SERIAL_NUM_1 OOB-read of VPD 0x80 response and XPT_GDEV_TYPE overflow of cgd->serial_num[252]
Summary
Two coupled bugs driven by malicious SCSI device VPD page 0x80 response. (1) PROBE_SERIAL_NUM_1 reads serial_buf->length (u_int8_t device-controlled max 255) does bcopy(serial_buf->serial_num dev->serial_num serial_buf->length) but serial_buf->serial_num is u_int8_t[251] inside 255-byte struct any length>251 reads 1-4 bytes past kmalloc buffer into adjacent kernel heap. (2) XPT_GDEV_TYPE copies dev->serial_num_len bytes (now up to 255) into cgd->serial_num[252] via bcopy 3-byte overwrite of cgd->reserved cgd->serial_num_len one byte past struct ccb_getdev within union ccb. Leaked heap bytes propagated to user via bcopy(ccb inccb sizeof(union ccb)) in xptioctl. Requires malicious SCSI target device (USB mass storage FireWire Thunderbolt Fibre Channel iSCSI) returning VPD 0x80 with length>=252. Impact: 4-byte heap OOB read per probe leaking adjacent kmalloc data into dev->serial_num propagated via XPT_GDEV_TYPE/XPT_DEV_MATCH root-only query. 3-byte CCB field corruption internal. [VERIFIED pass2: reproduced - VPD 0x80 length 255 drives 255-byte bcopy into 251-slot serial_num with mnopq alignment plus first OOB heap byte captured, XPT_GDEV_TYPE then overflows ccb_getdev by 3 bytes clobbering serial_num_len; malicious-target reach, root query; clamp fix-validated; side observation of runtime-scan lockmgr self-lock noted]
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-2261 Β· 7 files| File | Type | Description | Size | |
|---|---|---|---|---|
| rig/dfcam_harness.c | trigger-source | fake-SIM harness (scripted VPD 0x80, scan, spray, capture) | 19.9 KB | view raw |
| rig/df_rig.c | trigger-source | userland driver (find/leak66/phys78/ses80) | 8.6 KB | view raw |
| stage_01_attach_control.log | run-log | control bus, length=20, clean | 934 B | view raw |
| stage_02_2261_oob.log | run-log | malicious bus: mnopq alignment + clobbered fields | 1.4 KB | view raw |
| stage_03_2261_oob_run2.log | run-log | repeat run 2 | 1.6 KB | view raw |
| stage_04_2261_oob_run3.log | run-log | repeat run 3 | 2.1 KB | view raw |
| fix.diff | suggested-fix | clamp serial length in probedone + GDEV_TYPE | 1.9 KB | view raw |
Fix verification
fixedConfirmed kernel references
Detail
Exploit chain
malicious SCSI target VPD 0x80 length=255 -> probedone OOB read of 4 heap bytes -> dev->serial_num_len=255 -> XPT_GDEV_TYPE 3-byte overflow of ccb_getdev -> user-visible heap byte + field clobber
Evidence (decisive lines)
stage_02/03/04 logs: serial_num[246..251] = 6d 6e 6f 70 71 00 with final serial_num_len=0x00 (kernel wrote 255 first); stage_01 control clean
PoC changes
Authored dfcam fake-SIM harness + df_rig userland driver; had to move scanning kernel-side (xptioctl scans hold the SIM lock and hit a separate lockmgr recursion) and clamp the fake INQUIRY response to dxfer_len (rig-side fix)
Verified recommended fix
clamp the VPD serial length to SVPD_SERIAL_NUM_SIZE in probedone and bound the XPT_GDEV_TYPE copy by sizeof(cgd->serial_num)
Verdict
A fake CAM target returning VPD page 0x80 with length=255 drove the REAL probe machinery to bcopy 255 bytes out of the 255-byte serial_buf allocation (serial_num holds 251): byte alignment (serial_num[246..250]="mnopq", [251]=0x00 instead of pattern "r") proves the out-of-bounds source bytes, and XPT_GDEV_TYPE then overflowed ccb_getdev by 3 bytes (reserved and serial_num_len clobbered to 0x00 although the kernel had just written 255), identical across 3 runs. Control target (length=20) clean. Requires a malicious SCSI target; query path root-only. Fix (clamp to 251 + GDEV_TYPE bound) validated by A/B. A/B: Fixed kernel: malicious length 255 clamps to 251; no overflow of ccb_getdev (reserved/serial_num_len intact, kernel-set); control unchanged at 20.
No comments yet.