Stack buffer overflow in hptiop_post_req_itl via unbounded SG list (HIGH_MEM_ACESS path)
Summary
hptiop_post_req_itl HIGH_MEM_ACESS branch at hptiop.c:2417-2457: stack struct hpt_iop_request_scsi_command req (64B, sg_list[1]). Loop :2432-2440 psg=req.sg_list; for(idx=0;idx<nsegs;idx++,psg++){psg->pci_address/size/eot=...} overflows stack for nsegs>1. nsegs from bus_dmamap_load up to max_sg_count(HBA-reported, typically 32+). Also bcopy(cdb,req.cdb,cdb_len) at :2442 overflows cdb[16]. Also bus_space_write_region_1 over-reads stack. Triggered when SRB DMA >=32GB (HPT_SRB_FLAG_HIGH_MEM_ACESS). Unprivileged: dd if=/dev/daX bs=128k. Fix: write SG entries directly to MMIO, clamp cdb_len.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-1311 Β· 11 files| File | Type | Description | Size | |
|---|---|---|---|---|
| VERDICT.md | verdict | source-trace verdict: stack sg_list[1] overflow in ITL submission path | 3.5 KB | β raw |
| README.md | readme | build/run/expected (HBA-gated) + fix-validation steps | 1.3 KB | β raw |
| trigger_path.c | trigger-source | documents the HBA-only trigger (multi-seg disk I/O) | 1.5 KB | view raw |
| fix.diff | suggested-fix | clamp max_sg_count + size on-stack request buffer for max SG + bound cdb bcopy | 2.6 KB | view raw |
| build.sh | build-log | documents the single-fix nativekernel+installkernel build | 770 B | view raw |
| run.sh | run-log | reachability check (nm/pciconf/dmesg) | 717 B | view raw |
| fix_build.log | build-log | FULL untrimmed nativekernel output, rc=0 (-Werror), all 5 fixes compile | 5.6 MB | β download |
| run.log | run-log | baseline #0 reachability (no HBA, 81 hptiop symbols linked) | 209 B | view raw |
| env.txt | environment | guest uname, cc, PCI, CPU, module presence | 2.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 |
DF-1311 β hptiop_post_req_itl stack buffer overflow
Build
No standalone PoC binary β the trigger lives inside the kernel driver
(sys/dev/raid/hptiop/hptiop.c) and is only reachable on a host with a
HighPoint RocketRAID 3xxx HBA attached. The deliverable is the fix:
./build.sh # applies fix.diff and builds a single-fix GENERIC kernel
Run
./run.sh # attempts the trigger path; expected: NOT reachable on this guest
Expected (bug present, on a host WITH the HBA)
A multi-segment SCSI transfer to a disk on a HighPoint RocketRAID 3xxx HBA
overflows the on-stack struct hpt_iop_request_scsi_command (sg_list[1])
β kernel stack corruption β panic or worse.
On THIS guest (no HBA)
The driver is compiled into GENERIC but never attaches (no HighPoint PCI
device). ./run.sh documents the unreachable path and exits. This is
not_testable at runtime on the QEMU guest; the fix is compile- and
boot-validated instead (see VERDICT.md, fix_build.log).
Reproduce the FIX validation
scpfix.diffto the guest,cd /usr/src && patch -p1 < fix.diffmake -j6 nativekernel KERNCONF=X86_64_GENERIC- Install
kernel.strippedβ/boot/kernel/kernel, reboot. - Confirm guest boots cleanly (no new hptiop-related issues) and
kern.versionbumps to the rebuilt build.
DF-1311 β hptiop_post_req_itl stack buffer overflow (HighPoint RocketRAID)
Verdict
NOT TESTABLE AT RUNTIME on this guest β confirmed real latent vulnerability in source.
The bug is genuine and the analysis is certain, but the vulnerable I/O path can only execute on a machine with a HighPoint RocketRAID 3xxx (ITL/IOP) HBA, which the QEMU audit guest does not have.
Mechanism (confirmed by source trace)
sys/dev/raid/hptiop/hptiop.c:2401 hptiop_post_req_itl() is the ITL-family
firmware SCSI-command submission callback. In the
HPT_SRB_FLAG_HIGH_MEM_ACESS branch (line 2417) it builds the request in a
stack-local struct hpt_iop_request_scsi_command req;.
That struct (sys/dev/raid/hptiop/hptiop.h:301) contains:
u_int8_t cdb[16];
...
struct hpt_iopsg sg_list[1]; /* only ONE scatter/gather slot */
- Scatter/gather overflow: line 2432-2440 loops
idx < nsegs, advancing apsgpointer intoreq.sg_listand writingpci_address/size/eotper segment.nsegscomes frombus_dmamap_loadand is bounded only byhba->max_sg_count(set verbatim from HBA firmwareiop_config.max_sg_countat line 1933, with no upper clamp). A typical HBA reports 30+ segments, so any multi-segment transfer writesnsegs-116-bytestruct hpt_iopsgentries past the 1-entry stack array β kernel stack overflow. - CDB overflow: line 2442
bcopy(cdb, req.cdb, ccb->csio.cdb_len)copiescdb_len(up toMAX_CDBLEN=16 via CAM, but controllable through the CDB pointer path) intocdb[16]with no length check β off-by/overflow ofcdb.
hptiop is compiled statically into X86_64_GENERIC (device hptiop), but
the function is dead code unless the driver actually attaches to a HighPoint PCI
device β which requires the physical HBA.
Why it does not reproduce on this guest
pciconf -l: the only PCI devices are i440FX/PIIX3/virtio and a QEMU std-VGA (1234:1111). No HighPoint RAID controller is present.dmesgshows nohptiopattach.nm /boot/kernel/kernel | grep -c hptiopshows the code is linked (81 symbols) but never executed.- No CAM bus for hptiop exists, so no userspace
ioctl/pass/dapath can deliver a CCB tohptiop_post_req_itl. This is "needs specific HW" (case d).
Severity / realistic ceiling
On a host with a HighPoint RocketRAID 3xxx HBA, this is a kernel stack buffer
overflow reachable by ordinary multi-segment disk I/O (no privilege beyond
access to a disk on the HBA). Worst case is kernel stack corruption β panic
or potential code execution depending on what the overflowed sg_list/cdb
overwrite (saved frame pointer / return address are within reach for large
nsegs). The CVSS in the finding (AV:L/AC:L/PR:L) is appropriate.
Fix (see fix.diff)
- Clamp
hba->max_sg_countto a compile-timeHPTIOP_MAX_SG_COUNT(64) at attach so an absurd firmware value can't blow the stack buffer. - Replace the fixed 1-entry stack struct with a stack byte-buffer sized for
HPTIOP_MAX_SG_COUNTscatter/gather entries, accessed via a pointer. - Bound the
cdbbcopytosizeof(req->cdb).
This is compiled-and-boot-validated on GENERIC (see build.log / fix_build.log); runtime behaviour cannot be exercised without the HBA.
Note on the brief's "mpr SAS" label
The job brief mislabeled DF-1298 as "mpr SAS"; DF-1298 is actually the
amdgpu/display bios_parser.c. DF-1311 (this finding) is the HighPoint RAID
driver hptiop. mpr is a different finding not in this batch.
Fix verification
not_testablecompile+boot validated -Werror
nativekernel rc=0, boots #1 clean
Confirmed kernel references
β
Detail
Exploit chain
none
Evidence (decisive lines)
β
Verdict
Source-confirmed. hptiop_post_req_itl stack sg_list[1] overflow via nsegs + cdb[16] overflow. hptiop in GENERIC, no HighPoint HBA.
No comments yet.