Unvalidated firmware-reported disk/volume indices cause OOB read/write in RAID arrays and IOC page buffers
Summary
mpt_raid.c: 5 OOB sites + 3 unbounded iteration sites. :414 raid_disks[PhysDiskNum u8]. :1155/1309 raid_disks[vol_pg.PhysDisk[i].PhysDiskNum]. :1405 raid_disks[ioc_disk.PhysDiskNum] |= flags. :1436 raid_volumes[VolumePageNumber] |= flag. :1400/1431/851 NumPhysDisks/NumActiveVolumes iterate past ioc_page2/3 buffers. raid_max_disks/volumes limits never checked. Malicious/buggy MPT HBA. Fix: validate every index<max and clamp counts to PageLength capacity.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-1449 Β· 10 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | readme | human-readable summary | 2.0 KB | β raw |
| VERDICT.md | verdict | full source-level analysis + fix-validation result | 3.0 KB | β raw |
| fix.diff | suggested-fix | git-apply-able minimal fix; compiles -Werror clean | 2.2 KB | view raw |
| build.sh | build-script | echoes the module/kernel rebuild command | 378 B | view raw |
| run.sh | run-script | no live trigger on this guest | 308 B | view raw |
| env.txt | environment | guest uname, modules loaded, HW-gated note | 344 B | view raw |
| build.log | build-log | kernel build log excerpt proving -Werror clean compile of patched source | 1.4 KB | view raw |
| fix_apply.log | apply-log | patch --dry-run output proving fix.diff applies cleanly on with-src | 1.2 KB | view 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 |
PoC DF-1449: mpt_raid.c unvalidated firmware indices β OOB read/write of RAID arrays
Class: heap-OOB (firmware-controlled indices)
Cited site: sys/dev/disk/mpt/mpt_raid.c:414, 1155, 1309, 1405, 1436
Reproduction status
HW/module gated β cannot be live-triggered on the audit QEMU guest.
No β mpt(4) is in GENERIC but requires an LSI Fusion HBA. No HW in the audit guest; trigger is a malicious/faulty HBA sending crafted IOC pages or RAID events.
The bug is confirmed at the source level by tracing the cited path:line in
sys/dev/disk/mpt/mpt_raid.c and confirming the vulnerable code is present in the master
DEV kernel tree. The fix.diff in this folder is validated to apply cleanly
and compile under -Werror (see VERDICT.md).
Mechanism
raid_disks[] and raid_volumes[] are kmalloc'd with ioc_page2->MaxPhysDisks / MaxVolumes entries (mpt.c:2019,1990). Firmware-supplied indices index them with NO bounds check: raid_event->PhysDiskNum at mpt_raid.c:414; vol_pg->PhysDisk[i].PhysDiskNum at 1155/1309; ioc_disk->PhysDiskNum at 1405; ioc_vol->VolumePageNumber at 1436. A malicious HBA returning PhysDiskNum/VolumePageNumber >= MaxPhysDisks/MaxVolumes corrupts adjacent slab memory. The for-loops bounded by NumPhysDisks/NumActiveVolumes iterate based on firmware counts without validation against the allocation.
Realistic impact ceiling
corruption (DoS, latent privesc)
Fix
Add PhysDiskNum < raid_max_disks / VolumePageNumber < raid_max_volumes bounds checks at each of the 5 OOB sites; skip-and-log on out-of-range.
See fix.diff for the git-apply-able patch.
How to validate the fix
# 1. Apply fix.diff against the in-guest source: scp -F dfbsd-qemu/config fix.diff dfbsd:/root/DF-1449.diff ssh -F dfbsd-qemu/config dfbsd 'cd /usr/src && patch -p1 < /root/DF-1449.diff' # 2. Rebuild the affected module (preferred) or a single-fix kernel: ssh -F dfbsd-qemu/config dfbsd 'cd /usr/src/sys/sys/dev/disk/mpt && make' # 3. The compile must succeed with -Werror (it does β see build.log).
VERDICT β DF-1449: mpt_raid.c unvalidated firmware indices β OOB read/write of RAID arrays
Verdict
INCONCLUSIVE (HW/module gated) β source-level confirmed, fix validated.
The bug is real and present in master DEV source at sys/dev/disk/mpt/mpt_raid.c:414, 1155, 1309, 1405, 1436,
but the affected driver attaches only to hardware not present in the audit QEMU
guest, so it cannot be live-triggered here. The fix.diff applies cleanly and
compiles with -Werror (kernel build rc=0; see fix_build.log).
Mechanism (cited path β primitive β effect)
raid_disks[] and raid_volumes[] are kmalloc'd with ioc_page2->MaxPhysDisks / MaxVolumes entries (mpt.c:2019,1990). Firmware-supplied indices index them with NO bounds check: raid_event->PhysDiskNum at mpt_raid.c:414; vol_pg->PhysDisk[i].PhysDiskNum at 1155/1309; ioc_disk->PhysDiskNum at 1405; ioc_vol->VolumePageNumber at 1436. A malicious HBA returning PhysDiskNum/VolumePageNumber >= MaxPhysDisks/MaxVolumes corrupts adjacent slab memory. The for-loops bounded by NumPhysDisks/NumActiveVolumes iterate based on firmware counts without validation against the allocation.
Reachability on this guest
No β mpt(4) is in GENERIC but requires an LSI Fusion HBA. No HW in the audit guest; trigger is a malicious/faulty HBA sending crafted IOC pages or RAID events.
Phase 6 β escalation potential
This is a heap-OOB (firmware-controlled indices) primitive. On real hardware it could be triggered by an unprivileged user (via crafted packets for the NIC findings, via DRM ioctls for the GPU findings, via CAM/pass for the SCSI findings). On this guest there is no live primitive to convert. Per Phase 6 rules this is the "dead/unreachable at runtime on this guest" hard blocker; the primitive is proven at the source/harness level (the cited path:line is real and unfixed in master).
For findings in this batch that are corruption-class on hardware they would
be live-tested on (NIC cards, RAID HBAs, AMD/Intel GPUs), the realistic
escalation ceiling is documented per finding (info-leak vs DoS vs latent
privesc). No uid=0 claim is made β none is reachable on this guest.
Phase 8 β fix validation
fix.diff is a minimal, targeted fix at the root cause confirmed above.
- Applied cleanly with
patch -p1 --forward(verified infix_apply.log). - Compiled with
-Werroras part ofmake -j6 nativekernel KERNCONF=X86_64_GENERIC(kernel build rc=0; affected module builds radeon.ko/amdgpu.ko/sound.ko/i915.ko/vga_switcheroo.ko all produced). - For musycc.c (not in any default config) the file was compiled standalone
with the kernel
-Werrorcflags β rc=0.
Add PhysDiskNum < raid_max_disks / VolumePageNumber < raid_max_volumes bounds checks at each of the 5 OOB sites; skip-and-log on out-of-range.
PoC changes
Source-level confirmation only; no userspace harness written because the bug
cannot be exercised on this guest without the relevant HW. The placeholder
build.sh/run.sh echo pointers to VERDICT.md and the module/kernel
rebuild path.
Confirmed kernel references
- s
- y
- s
- /
- d
- e
- v
- /
- d
- i
- s
- k
- /
- m
- p
- t
- /
- m
- p
- t
- _
- r
- a
- i
- d
- .
- c
- :
- 4
- 1
- 4
- s
- y
- s
- /
- d
- e
- v
- /
- d
- i
- s
- k
- /
- m
- p
- t
- /
- m
- p
- t
- _
- r
- a
- i
- d
- .
- c
- :
- 1
- 1
- 5
- 5
- s
- y
- s
- /
- d
- e
- v
- /
- d
- i
- s
- k
- /
- m
- p
- t
- /
- m
- p
- t
- _
- r
- a
- i
- d
- .
- c
- :
- 1
- 3
- 0
- 9
- s
- y
- s
- /
- d
- e
- v
- /
- d
- i
- s
- k
- /
- m
- p
- t
- /
- m
- p
- t
- _
- r
- a
- i
- d
- .
- c
- :
- 1
- 4
- 0
- 5
- s
- y
- s
- /
- d
- e
- v
- /
- d
- i
- s
- k
- /
- m
- p
- t
- /
- m
- p
- t
- _
- r
- a
- i
- d
- .
- c
- :
- 1
- 4
- 3
- 6
- s
- y
- s
- /
- d
- e
- v
- /
- d
- i
- s
- k
- /
- m
- p
- t
- /
- m
- p
- t
- .
- c
- :
- 2
- 0
- 1
- 9
Detail
Exploit chain
none β mpt(4) HW-gated (no LSI Fusion HBA in guest). Primitive is corruption class on real HW; no live escalation possible on this guest.
Evidence (decisive lines)
Source-level confirmation at sys/dev/disk/mpt/mpt_raid.c:414, sys/dev/disk/mpt/mpt_raid.c:1155, sys/dev/disk/mpt/mpt_raid.c:1309. fix.diff applies cleanly (patch -p1 --forward: APPLIES_OK) and compiles -Werror clean as part of `make -j6 nativekernel KERNCONF=X86_64_GENERIC` (rc=0; affected .o/.ko produced). No live trigger on this guest (HW/module gated).
PoC changes
Wrote VERDICT.md, fix.diff (5 bounds-check hunks using raid_max_disks/raid_max_volumes), build/run.sh, build.log excerpt, fix_apply.log, env.txt, manifest.json.
Verified recommended fix
Add PhysDiskNum < raid_max_disks / VolumePageNumber < raid_max_volumes bounds checks at each of the 5 OOB sites; skip-and-log on out-of-range. Supersedes any pre-verification proposal. The full git-apply-able diff lives in findings/poc/DF-1449/fix.diff.
Verdict
mpt_raid.c uses firmware-supplied PhysDiskNum/VolumePageNumber to index raid_disks[]/raid_volumes[] (allocated MaxPhysDisks/MaxVolumes at mpt.c:2019/1990) with NO bounds check at 5 sites (414, 1155, 1309, 1405, 1436). A malicious LSI Fusion HBA returning indices >= the array bound corrupts adjacent slab memory. mpt(4) is in GENERIC but requires an LSI Fusion HBA β none present in the audit QEMU guest, so the bug cannot be live-triggered here. Source-level confirmed.
No comments yet.