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

isp_handle_platform_atio copies firmware CDB length into 16-byte cdb_bytes without bound (target-mode heap overflow)

Summary

In parallel-SCSI target-mode ATIO handler aep->at_cdblen (firmware-reported uint8_t may be up to ATIO_CDBLEN=26) used directly as memcpy length into atiop->cdb_io.cdb_bytes which is only IOCDBLEN=CAM_MAX_CDBLEN=16 bytes. CDB of 17..26 bytes from malicious SCSI initiator overflows cdb_bytes by 1..10 bytes into cdb_len/tag_action/sense_len/tag_id/init_id fields. FC paths correctly use fixed 16-byte lengths only legacy parallel-SCSI path unbounded. Requires kernel compiled with ISP_TARGET_MODE (off by default) and parallel-SCSI QLogic ISP adapter in target mode. Overwritten tag_id can confuse ATIO/CTIO bookkeeping potential command misrouting. [VERIFIED pass2: reproduced - target-mode ATIO copies firmware at_cdblen 26 into 16-byte cdb_bytes with marker bytes landing in cdb_len tag_action sense_len init_id; clamp fix A/B clean; config-gated]

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2473 Β· 8 files
FileTypeDescriptionSize
README.md β€” 967 B ↓ raw
VERDICT.md β€” 2.2 KB ↓ raw
build.sh β€” 99 B view raw
run.log β€” 564 B view raw
env.txt β€” 963 B view raw
fix.diff β€” 770 B view raw
manifest.json β€” 787 B view raw
verdict.json β€” 2.4 KB view raw

DF-2473 -- isp_handle_platform_atio copies firmware CDB length unbounded (target mode)

Verification used the shared rig tree at /root/rigs on the audit guest (see manifest). The rig for this finding: dfv_ispt (rig.c = harness, gen.sh = verbatim extractor, dfv_*_extract.h = generated production text). The decisive outputs below were captured live on the guest during the 2026-10-24 verification session; full session logs are summarized per run.

Build

sh build.sh            # extracts verbatim driver text + builds the KLD

Run (guest, root)

kldload ./dfv_rig.ko

kldload dfv_ispt.ko; sysctl kern.dfv_ispt_run=1; sysctl -n kern.dfv_ispt_status

Expected

run.log: marker bytes 0xF0-0xF9 in cdb_len/tag_action/sense_len/init_id after the verbatim handler; control clean; fixed clean.

Fix validation

fix.diff clamps cdblen to sizeof cdb_bytes (and logs); A/B clean.

Verdict: reproduced / impact=limited_write (see verdict.json, VERDICT.md)

VERDICT.md
↓ download raw

DF-2473 verdict -- isp_handle_platform_atio copies firmware CDB length unbounded (target mode)

status: reproduced reproduced: 1 impact: limited_write confidence: certain attempts: 1 runtime_sec: 600

Compiled with ISP_TARGET_MODE (the only configuration in which this code exists - no in-tree build defines it), the verbatim isp_handle_platform_atio runs ISP_MEMCPY(atiop->cdb_io.cdb_bytes, aep->at_cdb, aep->at_cdblen) with at_cdblen a firmware uint8_t (ATIO_CDBLEN = 26) against the 16-byte cdb_t (IOCDBLEN/CAM_MAX_CDBLEN). With at_cdblen=26 and marker CDB bytes 0xE0..0xF9 the verbatim handler left cdb_len=0xf0, tag_action=0xf1, sense_len=0xf2 and init_id=0x0000f9f8 - ten marker bytes written past cdb_io into the following ccb_accept_tio fields exactly as filed. Control (cdblen=16) shows only the legitimate handler-written values. Requires a parallel-SCSI ISP in target mode fed by a hostile initiator (firmware-controlled field). Fix (clamp to sizeof cdb_bytes) A/B: cdb_len=0x10, no marker bytes.

Evidence (decisive lines)

DF2473[cdblen=26]: IOCDBLEN=16 sizeof(cdb_t)=16 offsets cdb_io=208 cdb_len=224 tag_action=225 sense_len=226 tag_id=228 init_id=232 DF2473: after verbatim handler: cdb_len=0xf0 tag_action=0xf1 sense_len=0xf2 tag_id=0xffffffff init_id=0x0000f9f8 DF2473: marker CDB bytes were 0xE0..0xF9 --- control (cdblen=16) --- DF2473: after verbatim handler: cdb_len=0x10 tag_action=0x22 sense_len=0x00 tag_id=0xffffffff init_id=0x00000005 --- fixed source A/B --- DF2473: after verbatim handler: cdb_len=0x10 tag_action=0x22 sense_len=0x00 tag_id=0xffffffff init_id=0x00000005

Exploit chain / privesc assessment

no unpriv path; target-mode + hostile-initiator configuration; 1..10-byte overflow into adjacent CCB fields (tag_id/init_id bookkeeping confusion per the filing).

Fix + A/B

fix.diff clamps cdblen to sizeof cdb_bytes (and logs); A/B clean.

Fix status (batch validation)

Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.

Fix verification

fixed
↓ fix.diffper-fix-DF-2473

Confirmed kernel references

Detail

Exploit chain

no unpriv path; target-mode + hostile-initiator configuration; 1..10-byte overflow into adjacent CCB fields (tag_id/init_id bookkeeping confusion per the filing).

Evidence (decisive lines)

run.log: marker bytes 0xF0-0xF9 in cdb_len/tag_action/sense_len/init_id after the verbatim handler; control clean; fixed clean.

PoC changes

rig compiled with -DISP_TARGET_MODE; platform functions interposed.

Verified recommended fix

clamp aep->at_cdblen to sizeof cdb_bytes before ISP_MEMCPY

Verdict

Compiled with ISP_TARGET_MODE (the only configuration in which this code exists - no in-tree build defines it), the verbatim isp_handle_platform_atio runs ISP_MEMCPY(atiop->cdb_io.cdb_bytes, aep->at_cdb, aep->at_cdblen) with at_cdblen a firmware uint8_t (ATIO_CDBLEN = 26) against the 16-byte cdb_t (IOCDBLEN/CAM_MAX_CDBLEN). With at_cdblen=26 and marker CDB bytes 0xE0..0xF9 the verbatim handler left cdb_len=0xf0, tag_action=0xf1, sense_len=0xf2 and init_id=0x0000f9f8 - ten marker bytes written past cdb_io into the following ccb_accept_tio fields exactly as filed. Control (cdblen=16) shows only the legitimate handler-written values. Requires a parallel-SCSI ISP in target mode fed by a hostile initiator (firmware-controlled field). Fix (clamp to sizeof cdb_bytes) A/B: cdb_len=0x10, no marker bytes.