mpt_abort_target_ccb indexes trt[target_lun] without the MPT_MAX_LUNS guard every sibling target-mode XPT case has
Summary
XPT_ABORT (reachable via pass(4)) lands in mpt_abort_target_ccb, which picks trt[ccb->ccb_h.target_lun] with no bounds check, unlike the identical pattern guarded elsewhere in the file. trt[] has 256 entries; a LUN in [256, CAM_LUN_WILDCARD) would OOB-read a tgt_resource_t and STAILQ_REMOVE from it. Currently unreachable with OOB values (pass paths enumerated up to max_lun=256) - SIM-boundary defense-in-depth matching the sym(4) DF-3574 Info precedent. Latent: any future producer of high-LUN paths turns this into an OOB list removal.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3676 Β· 6 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 399 B | β raw | |
| VERDICT.md | β | 2.7 KB | β raw | |
| fix.diff | β | 587 B | view raw | |
| env.txt | β | 281 B | view raw | |
| verdict.json | β | 1.6 KB | view raw | |
| manifest.json | β | 471 B | view raw |
DF-3676 β mpt_abort_target_ccb indexes trt[lun] without the bounds guard every sibling XPT case has
Severity: Info (defense-in-depth; no currently-reachable producer of LUN >= 256). mpt_cam.c:4631-4635 vs the guard at 3683-3693. trt[] has 256 entries (mpt.h:367,709). Pattern precedent: sym(4) DF-3574 (Info). Fix in fix.diff. No runtime PoC (hardware-gated; guest has no MPT HBA β env.txt).
DF-3676 β VERDICT
status: inconclusive (hardening gap; currently unreachable with OOB values; no MPT hardware on guest)
Root cause
Every mpt XPT case that indexes mpt->trt[lun] validates the LUN first β
except the abort path:
/* sys/dev/disk/mpt/mpt_cam.c:3683-3693 (XPT_{NOTIFY_ACK,IMMED_NOTIFY,ACCEPT_TARGET_IO}) */
if (lun == CAM_LUN_WILDCARD) {
...
} else if (lun >= MPT_MAX_LUNS) {
mpt_set_ccb_status(ccb, CAM_REQ_INVALID); /* <-- guard */
break;
} else {
trtp = &mpt->trt[lun];
}
/* sys/dev/disk/mpt/mpt_cam.c:4631-4635 (XPT_ABORT -> mpt_abort_target_ccb) */
if (ccb->ccb_h.target_lun == CAM_LUN_WILDCARD) {
trtp = &mpt->trt_wildcard;
} else {
trtp = &mpt->trt[ccb->ccb_h.target_lun]; /* <-- no MPT_MAX_LUNS check */
}
trt[] has MPT_MAX_LUNS = 256 entries (mpt.h:367, mpt.h:709). A LUN in
[256, CAM_LUN_WILDCARD) reads tgt_resource_t (two STAILQ heads + int)
out of bounds and STAILQ_REMOVEs from it (mpt_cam.c:4645-4651) β list
corruption.
Reachability today (why Info, not Medium)
XPT_ABORT reaches mpt_action from userland via pass(4) (XPT_ABORT lacks
XPT_FC_XPT_ONLY β cam_ccb.h:143), but the abort CCB's path LUN is the
pass device's enumerated LUN, and CAM scans LUNs only up to
cpi->max_lun = MPT_MAX_LUNS (mpt reports 256 at mpt_cam.c:3598-3599;
SPI: 7). So no currently-reachable producer hands mpt a path LUN β₯ 256.
The check is nevertheless required at the SIM boundary because (a) CAM
does not enforce it centrally, (b) any future caller (xpt ioctl extension,
in-kernel periph) can construct arbitrary-LUN paths, and (c) the file's own
convention β every sibling case guards. This mirrors the sym(4) DF-3574
pattern filed as Info.
Fix
--- a/sys/dev/disk/mpt/mpt_cam.c
+++ b/sys/dev/disk/mpt/mpt_cam.c
@@ -4628,8 +4628,12 @@ mpt_abort_target_ccb(struct mpt_softc *mpt, union ccb *ccb)
mpt_lprt(mpt, MPT_PRT_DEBUG, "aborting ccb %p\n", accb);
- if (ccb->ccb_h.target_lun == CAM_LUN_WILDCARD) {
+ if (ccb->ccb_h.target_lun == CAM_LUN_WILDCARD) {
trtp = &mpt->trt_wildcard;
- } else {
+ } else if (ccb->ccb_h.target_lun < MPT_MAX_LUNS) {
trtp = &mpt->trt[ccb->ccb_h.target_lun];
+ } else {
+ return (CAM_LUN_INVALID);
+ }
Guest verdict
inconclusive (hardware-gated even for the benign reachability demo); source-level gap certain.
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
not_testableGuard diff authored (fix.diff); not exercisable without hardware.
fix.diff; env.txt
Confirmed kernel references
Detail
Evidence (decisive lines)
VERDICT.md (guard asymmetry with path:line); fix.diff; env.txt
PoC changes
n/a
Verified recommended fix
Add 'else if (lun < MPT_MAX_LUNS)' with CAM_LUN_INVALID return in mpt_abort_target_ccb
Verdict
Hardening gap (Info): mpt_abort_target_ccb indexes mpt->trt[ccb->ccb_h.target_lun] with no MPT_MAX_LUNS check (mpt_cam.c:4631-4635) while every sibling target-mode XPT case guards lun >= MPT_MAX_LUNS (mpt_cam.c:3683-3693, 4298, 4324). trt[] is 256 entries. Today no reachable producer hands mpt a path LUN >= 256 (pass paths are enumerated up to cpi->max_lun=256), so this is defense-in-depth at the SIM boundary, matching the sym DF-3574 precedent. Not executable on this guest (no MPT hardware).
No comments yet.