INQUIRY/READ_CAPACITY/SERVICE_ACTION_IN write fixed-size replies past dxfer_len-sized kernel buffer
Summary
OsSendCommand at entry.c:2709 SetInquiryData writes 36 bytes to data_ptr. READ_CAPACITY (:2715) writes 8 bytes. SERVICE_ACTION_IN (:2740) writes 12 bytes. cam_periph_mapmem allocates kernel bounce buffer of exactly dxfer_len bytes. Small dxfer_len (e.g. 4) -> heap OOB write of 4-28 bytes past allocation. INQUIRY value partially attacker-influenced on RAID via array info. READ_CAPACITY cap value from disk size. Fix: validate dxfer_len >= expected reply size.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-1285 Β· 8 files| File | Type | Description | Size | |
|---|---|---|---|---|
| trigger_analysis.c | trigger-source | documentation marker | 1.1 KB | view raw |
| fix.diff | suggested-fix | validate dxfer_len against reply size in INQUIRY/READ_CAPACITY/SERVICE_ACTION_IN cases | 1.3 KB | view raw |
| build.sh | build-script | syntax-checks the marker | 432 B | view raw |
| run.sh | run-script | documents INCONCLUSIVE status | 647 B | view raw |
| combined_build.log | build-log | combined X86_64_GENERIC rebuild log; rc=0 | 5.6 MB | β download |
| env.txt | environment | uname, pciconf -l, kldstat -v | 1015 B | view raw |
| README.md | readme | human-readable summary (also corrects brief's hptrr -> hptmv) | 3.0 KB | β raw |
| VERDICT.md | verdict | detailed source-level analysis | 3.6 KB | β raw |
DF-1285 β hptmv OsSendCommand writes fixed-size replies past small dxfer_len buffer
Finding
OsSendCommand at sys/dev/raid/hptmv/entry.c:2678 handles three SCSI CDB
types by writing fixed-size replies directly into ccb->csio.data_ptr:
- INQUIRY (
entry.c:2709) βSetInquiryData()fillssizeof(INQUIRYDATA)(= 96 bytes, defined inosbsd.h:68-90) into the buffer. - READ_CAPACITY (
entry.c:2715) β writes 8 bytes viarbuf[0..7]. - SERVICE_ACTION_IN (0x9e) (
entry.c:2740) β writes 12 bytes viarbuf[0..11].
CAM's cam_periph_mapmem allocates the kernel bounce buffer at exactly
dxfer_len bytes (the user-specified transfer length). If the user issues
one of these CDBs with a smaller dxfer_len than the reply (e.g. dxfer_len=4
for INQUIRY), the writes overflow the allocation by 4..92 bytes.
The INQUIRY data is partially attacker-influenced on RAID arrays (array
membership strings from pVDev->VDeviceType flow into the
VendorId/ProductId/ProductRevisionLevel memcpy's at entry.c:2595-2620);
the READ_CAPACITY / SERVICE_ACTION_IN values are derived from
pVDev->VDeviceCapacity (disk size). The overflow bytes therefore are not
fully attacker-shaped, but the start of the overwrite is a fixed pattern
("RR18xx ", "3.00", etc.) and the size is controlled.
Fix
Validate csio->dxfer_len against the actual reply size before writing, and
return CAM_REQ_INVALID if the buffer is too small. Do this in each of the
three cases.
Note on the file vs the brief
The brief calls this "hptrr" β that is wrong. The vulnerable file is
sys/dev/raid/hptmv/entry.c (the hptmv driver β Highpoint RocketRAID
182x). The DB row's file column is correct.
Verification on this guest
- The hptmv driver is statically compiled in (
device hptmvinsys/config/X86_64_GENERIC:119) and shows up inkldstat -v(pci/hptmv). - The QEMU guest has no Marvell 88SX508x / Highpoint PCI device
(
pciconf -lshows only i440FX/PIIX/ACPI/virtio-net/virtio-blk/std-VGA).hptmv_probenever matches, sohptmv_attachand thexpt_bus_register->OsSendCommandpath never run. The bug is not runtime-triggerable on this guest. - Source-level confirmation:
osbsd.h:68-90βINQUIRYDATAis 96 bytes (5 + 1 + 1 + 8 + 16 + 4 + 20 + 40 + 1).entry.c:2710-2711βZeroMemory(data_ptr, dxfer_len)thenSetInquiryDatawrites the full struct.entry.c:2717-2734β READ_CAPACITY writes 8 bytes viarbuf[0..7].entry.c:2742-2756β SERVICE_ACTION_IN writes 12 bytes viarbuf[0..11].- Fix verified to compile (combined build with DF-1278/1279/1280/1287).
Realistic impact ceiling
Local-user-controllable heap OOB write of 4..92 bytes if an hptmv-managed
disk is exposed to a low-privileged user via the CAM pass(4) device or a
filesystem on top of an hptmv disk. The byte pattern at the overwrite start
is fixed ("RR18xx " or zero from ZeroMemory) β i.e. not fully
attacker-shaped, but the size is. Slab layout is unknown until triggered.
VERDICT β DF-1285
Status
INCONCLUSIVE (source-confirmed; not runtime-triggerable on this guest).
Mechanism (source-confirmed)
OsSendCommand at sys/dev/raid/hptmv/entry.c:2678 handles three SCSI CDB
types by writing fixed-size replies directly into ccb->csio.data_ptr:
| CDB | Lines | Bytes written | Source |
|---|---|---|---|
| INQUIRY (0x12) | entry.c:2709 | 96 | SetInquiryData fills INQUIRYDATA (osbsd.h:68-90) |
| READ_CAPACITY (0x25) | entry.c:2715 | 8 | rbuf[0..7] |
| SERVICE_ACTION_IN (0x9e) | entry.c:2740 | 12 | rbuf[0..11] |
CAM's cam_periph_mapmem allocates the kernel bounce buffer at exactly
dxfer_len bytes (the user-specified transfer length). If the user issues
one of these CDBs with a smaller dxfer_len than the reply (e.g.
dxfer_len=4 for INQUIRY), the writes overflow the allocation by 4..92
bytes.
The INQUIRY data is partially attacker-influenced on RAID arrays β array
membership strings from pVDev->VDeviceType flow into the
VendorId/ProductId/ProductRevisionLevel memcpy's at
entry.c:2595-2620 ("RR18xx ", "RAID 0 Array ", "3.00", etc.). The
READ_CAPACITY / SERVICE_ACTION_IN values are derived from
pVDev->VDeviceCapacity (disk size). The overflow bytes therefore are
not fully attacker-shaped, but the size and the start pattern are
controlled.
Note on the file vs the brief
The task brief calls this "hptrr" β that is wrong. The vulnerable file is
sys/dev/raid/hptmv/entry.c (the hptmv driver β Highpoint RocketRAID
182x, based on the Marvell 88SX508x chipset). The DB findings.file column
is correct.
Fix
Validate csio->dxfer_len against the actual reply size before writing,
and return CAM_REQ_INVALID if the buffer is too small. Do this in each
of the three cases. See fix.diff.
Verification on this guest
hptmvis statically compiled in (device hptmvinsys/config/X86_64_GENERIC:119) and shows up inkldstat -v(pci/hptmv).- No Marvell 88SX508x / Highpoint PCI device in
pciconf -l(only i440FX/PIIX/ACPI/virtio-net/virtio-blk/std-VGA), sohptmv_probenever matches andOsSendCommandis never called. Not runtime-triggerable. - Fix validation: combined
X86_64_GENERICrebuild with this fix applied exitedrc=0. Full log:combined_build.log.
Exploit chain
None on this guest (no HW). On a system with an hptmv-managed disk exposed
via CAM pass(4) or a filesystem on top of an hptmv disk, an
unprivileged user could trigger a heap OOB write of 4..92 bytes by issuing
an INQUIRY/READ_CAPACITY/SERVICE_ACTION_IN with a small dxfer_len. The
overwrite start pattern is partially fixed ("RR18xx " or zeros from
ZeroMemory); the size is fully controlled. No escalation was attempted
because the path is unreachable on this guest.
Realistic impact ceiling
Local-user heap OOB write of 4..92 bytes on systems presenting an hptmv
disk to unprivileged users. CVSS: AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:N
(local, requires the rare hptmv-deployed machine + permissive CAM access).
PoC changes
Folder was empty; added trigger_analysis.c, build.sh, run.sh,
README.md, this VERDICT.md, fix.diff, manifest.json,
combined_build.log.
Recommended fix
Matches the finding proposal: validate dxfer_len against the expected
reply size in each of the three cases. See fix.diff.
Fix status
not_testable β bug requires absent hardware. fix.diff applies cleanly
and compiles into X86_64_GENERIC (combined build rc=0).
Fix verification
not_testablecompile validated
nativekernel rc=0
Confirmed kernel references
β
Detail
Exploit chain
none
Evidence (decisive lines)
β
Verdict
Source-confirmed. hptmv INQUIRY/READ_CAPACITY/SERVICE_ACTION_IN fixed-size writes vs dxfer_len -> heap OOB. hptmv in GENERIC, no HW.
No comments yet.