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

ABTS RX_ID bound check uses IOC mpt_max_tgtcmds instead of actual tgt_cmd_ptrs array size (OOB read in FC target mode)

Summary

In mpt_fc_els_reply_handler ABTS path RX_ID (16-bit field from remote FC initiator ABTS frame) validated against mpt->mpt_max_tgtcmds but tgt_cmd_ptrs array is only min(MPT_MAX_REQUESTS/2 mpt_max_tgtcmds)=min(256 mpt_max_tgtcmds) entries wide. When IOC reports MaxPostedCmdBuffers>256 RX_ID values [256 mpt_max_tgtcmds) pass check but index past allocated array OOB read whose result dereferenced as request_t pointer. mpt_max_tgtcmds is port_facts MaxPostedCmdBuffers U16 IOC can report above 256. IOC-input router mpt.c:765 correctly bounds with tgt_cmds_allocated this FC ELS handler does not. Niche target-mode + MaxPostedCmdBuffers>256. [VERIFIED pass2: reproduced - rx_id 300 passes the 512 check against the 256-entry array, OOB-read pointer drives MPT_TGT_STATE control flow proven by mismatch log; guard fix rejects]

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2537 Β· 6 files
FileTypeDescriptionSize
rig.c β€” 6.1 KB view raw
gen.sh β€” 435 B view raw
Makefile β€” 180 B ↓ download
build.sh β€” 93 B view raw
run.sh β€” 90 B view raw
run.log β€” 933 B view raw

Fix verification

not_testable
↓ fix.diffper-fix-DF-2537

Confirmed kernel references

Detail

Evidence (decisive lines)

mpt2537_run.log mode 0: mismatch log proving the OOB-read pointer was dereferenced; mode 2 fixed guard rejects

PoC changes

verbatim ABTS-branch extract driven with a real mpt_softc + groomed adjacent heap; logging interposed only

Verified recommended fix

use mpt->tgt_cmds_allocated for the rx_id bound at mpt_cam.c:3004

Verdict

mpt_fc_els_reply_handler (mpt_cam.c:3004-3009) bounds the ABTS RX_ID against the IOC-reported mpt->mpt_max_tgtcmds (port_facts[0].MaxPostedCmdBuffers) while tgt_cmd_ptrs is only min(256, max_tgtcmds) entries (mpt_cam.c:4250-4256, MPT_MAX_REQUESTS=512). Verbatim ABTS branch (sha256-attested): with MaxPostedCmdBuffers=512 and a 256-entry array, rx_id=300 passed the check and tgt_cmd_ptrs[300] (352 bytes past the 2048-byte allocation) returned the groomed fake request_t; the verbatim code then dereferenced it via MPT_TGT_STATE and logged ABORT Mismatch: RX_ID received=0x12c; RX_ID in cmd=0x3eef -- the OOB-read pointers contents drove kernel control flow. Control rx_id=100 behaved in-bounds; fixed guard (check tgt_cmds_allocated) rejected. Niche: FC target mode + an IOC (or malicious FC initiator forging ABTS replies is not possible -- this is IOC input) reporting >256; impact is kernel memory corruption potential in a storage driver, gated on hardware we do not have -- hence impact none beyond the demonstrated read+deref.