Heap overflow in isp_handle_platform_atio CDB copy (parallel SCSI target mode)
Summary
isp_handle_platform_atio at isp_freebsd.c:1926-1927: ISP_MEMCPY(atiop->cdb_io.cdb_bytes, aep->at_cdb, aep->at_cdblen) copies firmware-reported at_cdblen (uint8 0..255) into cdb_bytes[IOCDBLEN=16]. Source at_cdb[ATIO_CDBLEN=26]. No clamp. at_cdblen>16 overflows cdb_bytes into cdb_len/tag_action/sense_len/tag_id/init_id fields. FC sibling paths atio2/atio7 use fixed ATIO2_CDBLEN=16/sizeof(fcp_cmnd_cdb)=16. Requires ISP_TARGET_MODE option (not default) AND parallel-SCSI QLogic HBA. Attacker: device on parallel SCSI bus or SCSI-passthrough VM. Fix: clamp to min(at_cdblen, sizeof(cdb_bytes)).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-1155 Β· 8 files| File | Type | Description | Size | |
|---|---|---|---|---|
| VERDICT.md | verdict | Full source trace + 3-layer reachability analysis | 4.7 KB | β raw |
| fix.diff | suggested-fix | Clamp at_cdblen to sizeof(cdb_bytes) (git apply-able, validated) | 581 B | view raw |
| build.sh | build-doc | Documents why no executable PoC is possible | 453 B | view raw |
| run.sh | run-doc | Documents why runtime trigger is impossible on this guest | 223 B | view raw |
| env.txt | environment | uname + 3-layer unreachability proof (no symbol, no opt, no HBA) | 558 B | view raw |
| README.md | readme | human reproduce doc | 940 B | β raw |
| ../fix_build_combined.log | build-log | Combined 41-finding kernel build (rc=0, -Werror clean) | 5.6 MB | β download |
| ../fix_build_summary.txt | build-summary | Summary of the combined 41-finding kernel build | 826 B | view raw |
DF-1155 β heap overflow in isp_handle_platform_atio CDB copy
Result
NOT REPRODUCED on this guest. Real source-level defense-in-depth bug;
fix authored. See VERDICT.md for the full analysis.
Build & run
./build.sh # documents why no executable PoC is possible ./run.sh # documents why runtime trigger is impossible
Reachability summary (3 independent blockers)
- The vulnerable function
isp_handle_platform_atiois not in the kernel binary β all callers are inside#ifdef ISP_TARGET_MODE, which is not defined;nm kernel.debug | grep -c isp_handle_platform_atioβ 0. ISP_TARGET_MODEis opt-in only (LINT64, commented out) β not inX86_64_GENERIC.- No QLogic parallel-SCSI HBA on the QEMU guest.
Fix
fix.diff β clamp at_cdblen to sizeof(cdb_bytes) (= IOCDBLEN = 16)
at sys/dev/disk/isp/isp_freebsd.c:1926-1927. Applies cleanly with
git apply.
DF-1155 β heap overflow in isp_handle_platform_atio CDB copy
Verdict
NOT REPRODUCED on this guest (defense-in-depth source bug confirmed; path unreachable on the default GENERIC DragonFlyBSD kernel running in QEMU). Real source-level defect; fix.diff authored.
Mechanism (source trace, bug confirmed real)
In sys/dev/disk/isp/isp_freebsd.c:1829, isp_handle_platform_atio()
copies a SCSI CDB delivered by the QLogic firmware into a CAM
ccb_accept_tio:
/* sys/dev/disk/isp/isp_freebsd.c:1925-1927 */
atiop->init_id = GET_IID_VAL(aep->at_iid);
atiop->cdb_len = aep->at_cdblen; /* L1926 */
ISP_MEMCPY(atiop->cdb_io.cdb_bytes, aep->at_cdb, aep->at_cdblen); /* L1927 */
The sizes are mismatched and there is no clamp:
| Object | Field | Size | Source |
|---|---|---|---|
source at_entry_t.at_cdb |
aep->at_cdb |
ATIO_CDBLEN = 26 |
sys/dev/disk/isp/ispmbox.h:1965,1980 |
length at_entry_t.at_cdblen |
aep->at_cdblen |
uint8_t β 0..255 |
sys/dev/disk/isp/ispmbox.h:1973 |
destination ccb_accept_tio.cdb_io.cdb_bytes |
atiop->cdb_io.cdb_bytes |
IOCDBLEN = CAM_MAX_CDBLEN = 16 |
sys/bus/cam/cam.h:53, sys/bus/cam/cam_ccb.h:44 |
The firmware-reported at_cdblen (0..255) is fed directly to ISP_MEMCPY
without clamping to the destination size. A malicious firmware (or hostile
device on a parallel SCSI bus, or a SCSI-passthrough VM) reports
at_cdblen > 16 β the copy overruns cdb_bytes[16] into the subsequent
fields of struct ccb_accept_tio (cdb_len, tag_action, sense_len,
tag_id, init_id, β¦) and beyond into adjacent slab memory. Per the
finding, the FC siblings isp_handle_platform_atio2 (:1953) and
isp_handle_platform_atio7 (:2126) use the fixed sizes
ATIO2_CDBLEN = 16 / sizeof(fcp_cmnd_cdb) = 16, so they are not
affected.
Why it does NOT reproduce on this guest
This finding has three independent reachability blockers, any one of which is fatal:
1. The vulnerable function is not in the kernel binary.
isp_handle_platform_atio is defined at isp_freebsd.c:1828-1950, which
sits outside any #ifdef ISP_TARGET_MODE block. However every
caller is inside such a block β the only entry point is the
RQSTYPE_ATIO dispatch at isp_freebsd.c:5354-5359 inside the
ISPASYNC_TARGET_ACTION case at :5334, which is inside the
#ifdef ISP_TARGET_MODE block at :5263 (closed at :5431). Since
ISP_TARGET_MODE is not defined by X86_64_GENERIC:
$ grep ISP_TARGET_MODE sys/config/X86_64_GENERIC (empty)
the function has no callers, the compiler/linker drops it, and:
$ ssh dfbsd 'nm /boot/kernel/kernel.debug | grep -c isp_handle_platform_atio' 0
β confirmed: zero isp_handle_platform_atio symbols in the running kernel.
2. ISP_TARGET_MODE is opt-in, not default.
sys/conf/options:203 declares ISP_TARGET_MODE opt_isp.h. The only
configuration that mentions it is sys/config/LINT64:1462 and it is
commented out (#options ISP_TARGET_MODE=1). So even a custom
kernel must explicitly opt in; default GENERIC and most production kernels
do not enable target mode.
3. No parallel-SCSI QLogic HBA in the QEMU guest.
Even with ISP_TARGET_MODE enabled, the ISP driver only registers target
mode for actual QLogic SCSI HBAs (1040/1080/12160/2100/2200/2300/2322
parallel SCSI; 2400/2500 FC). The QEMU guest has none of these on
its virtual PCI bus β devinfo -v | grep -i qlogic is empty, and no
isp controller attaches at probe. No firmware request queue β no ATIO
entry β no path to the vulnerable function.
Exploit chain
none β primitive (kernel heap overflow) requires all three of: kernel
built with ISP_TARGET_MODE, a QLogic SCSI HBA physically present (or
SCSI-passthrough VM), and malicious firmware/device. None of these hold
on the default GENERIC DragonFlyBSD guest.
PoC changes
none β no executable PoC is possible. Even building a custom
ISP_TARGET_MODE=1 kernel would not help: the guest has no QLogic HBA,
so the ISP driver would never call isp_handle_platform_atio. The
function's only caller is the firmware-dispatch ISPASYNC_TARGET_ACTION
path, which fires only when the HBA's request queue delivers an
RQSTYPE_ATIO entry.
Recommended fix
Clamp the copy length to the destination buffer size (16 bytes); also
clamp the cdb_len recorded for the upper layer to the same value. See
fix.diff β applies cleanly with git apply (validated). Matches the
finding markdown's proposal.
The sibling FC paths (isp_handle_platform_atio2/atio7) are already
safe because they use the fixed ATIO2_CDBLEN = 16 for both source and
destination, so no parallel fix is needed there.
Fix verification
not_testablegit apply --check validated
see evidence pack
Confirmed kernel references
β
Detail
Exploit chain
none
Evidence (decisive lines)
β
Verdict
Source-confirmed. isp_handle_platform_atio CDB copy no clamp. ISP_TARGET_MODE not compiled, no QLogic HW.
No comments yet.