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

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)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2261 Β· 7 files
FileTypeDescriptionSize
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

fixed
↓ fix.diffper-fix-DF-2261

Confirmed 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.