ciss_init_logical: unbounded CISS_LUN_TO_BUS/TARGET at attach yields kernel OOB write of pointers and objects
Summary
ciss_init_logical at ciss.c:1386-1406: CISS_LUN_TO_BUS (8-bit 0-255) and CISS_LUN_TO_TARGET (8-bit 0-255) from controller REPORT_LOGICAL_LUNS used to index ciss_logical[bus][target] with NO bounds check. ld->cl_controller=&sc->ciss_controllers[bus] writes OOB pointer. ciss_identify_logical kmallocs into OOB ld->cl_ldrive/cl_lstatus. Malicious/emulated CISS PCI device at attach. Fix: validate bus<max_logical_bus and target<CISS_MAX_LOGICAL.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-1190 Β· 11 files| File | Type | Description | Size | |
|---|---|---|---|---|
| harness.c | trigger-source | userspace replica of ciss_init_logical OOB-index loop with real CISS_LUN_TO_BUS/TARGET macros | 4.0 KB | view raw |
| VERDICT.md | verdict | full narrative: mechanism, path:line, harness proof, fix | 4.0 KB | β raw |
| build.sh | build-script | cc -O2 -Wall -o harness harness.c | 172 B | view raw |
| run.sh | run-script | ./harness | 66 B | view raw |
| run.log | run-log | decisive run: 2 OOB index accesses | 635 B | view raw |
| env.txt | environment | uname, cc version, module/threat-model notes | 418 B | view raw |
| fix.diff | suggested-fix | validate bus<max_logical_bus && target<CISS_MAX_LOGICAL before indexing | 556 B | view raw |
| fix_build.log | build-log | ciss.ko rebuilt with all 3 ciss fixes, -Werror, rc=0 | 29 B | view raw |
| README.md | readme | human reproduce doc | 1.4 KB | β 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-1190 β ciss_init_logical out-of-range bus/target index -> OOB write
File: sys/dev/raid/ciss/ciss.c:1391-1396
Class: memory corruption (hardware/firmware-attacker; malicious CISS PCI device
or malicious VBIOS at driver attach). No local-unprivileged syscall trigger on the
audit guest (no HP Smart Array / no AMD GPU present).
Reproduce
./build.sh && ./run.sh
What the harness does
harness.c is a faithful userspace replica of the kernel parsing routine cited
above, fed crafted controller/VBIOS data that the real malicious device would
supply. It demonstrates the out-of-bounds access / overflow / underflow using the
real kernel macros and struct sizes, with a canary or computed-index check to
make the OOB observable without needing the hardware.
Expected output
A [BUG REPRODUCED] (or UNDERFLOW for DF-1199) marker plus the computed
out-of-range index / overflow byte count / underflowed loop count. See run.log
for the captured decisive run.
Fix
See fix.diff (git-apply-able) and VERDICT.md. The fix was validated to
compile (module rebuilt with -Werror) β see fix_build.log. No live-kernel
trigger exists on the guest, so the fix is validated at the
applies + compiles + closes-the-code-path level.
Artifacts
VERDICT.md (full narrative), harness.c, build.sh, run.sh,
run.log, env.txt, fix.diff, fix_build.log, manifest.json.
DF-1190 β ciss_init_logical out-of-range bus/target index (OOB write)
Verdict
REPRODUCED (harness) β real bug confirmed by source trace + userspace replica.
Impact class: kernel heap OOB write / OOB pointer store. No local-unprivileged
trigger on the audit guest (no HP Smart Array controller); trigger requires a
malicious/emulated CISS PCI device at driver attach. uid=0 escalation chain
is N/A β this is a hardware/firmware-attacker primitive (driver-probe time),
not a syscall-driven local-privesc path.
Mechanism (confirmed path:line)
ciss_init_logical() (sys/dev/raid/ciss/ciss.c) walks the controller's
REPORT_LOGICAL_LUNS reply and decodes each LUN's 8-bit bus and target from
controller-supplied data:
sys/dev/raid/ciss/ciss.c:1391βbus = CISS_LUN_TO_BUS(cll->lun[i].logical.lun);sys/dev/raid/ciss/ciss.c:1392βtarget = CISS_LUN_TO_TARGET(cll->lun[i].logical.lun);sys/dev/raid/ciss/ciss.c:1393βld = &sc->ciss_logical[bus][target];
The index macros (sys/dev/raid/ciss/cissreg.h:509-510) yield 0..255 for
each of bus and target, but the arrays are far smaller:
- ciss_logical is ciss_max_logical_bus rows Γ CISS_MAX_LOGICAL(15) cols
(cissvar.h:49, allocated at ciss.c:1372-1383),
- ciss_controllers is ciss_max_logical_bus entries (ciss.c:1484-1486).
There is no bounds check between decoding bus/target and indexing. With
bus >= ciss_max_logical_bus or target >= 15:
1. sc->ciss_logical[bus] reads an out-of-bounds pointer (row pointer past
the array),
2. ld->cl_controller = &sc->ciss_controllers[bus] writes an OOB kernel
pointer into the corrupted ld (ciss.c:1396),
3. ciss_identify_logical(sc, ld) then kmallocs into ld->cl_ldrive /
ld->cl_lstatus (ciss.c:1397) β controlled heap writes through the
OOB-corrupted ld.
The earlier sanity check at ciss.c:1357 only bounds ndrives (the count) to
CISS_MAX_LOGICAL; it does not validate the per-LUN bus/target encodings.
Harness proof (run.log)
harness.c replicates the exact loop with the real CISS_LUN_TO_BUS /
CISS_LUN_TO_TARGET macros and a ciss_max_logical_bus=1 layout, feeding a
forged LUN with bus=200/target=250 and another with bus=0/target=40:
[!] OOB index drive=0 bus=200 (max 1) target=250 (max 15) -> writes ciss_logical[200][250] + ciss_controllers+200 [!] OOB index drive=1 bus=0 (max 1) target=40 (max 15) -> writes ciss_logical[0][40] + ciss_controllers+0 [BUG REPRODUCED] 2 out-of-range index accesses observed
Why not a live-kernel trigger / no uid0 chain
ciss is a module (/boot/kernel/ciss.ko, device ciss in
X86_64_GENERIC:115) that attaches only to HP Smart Array PCI devices
(ciss_pci_attach). The audit QEMU guest has no CISS controller, so the
module is never loaded/attached (kldstat shows neither). The malicious data
comes from the PCI device's REPORT_LOGICAL_LUNS DMA response at probe time β
it is not reachable from any unprivileged userspace syscall. Driving it live
would require either (a) a malicious physical/emulated CISS PCI device (a
hardware-attacker / VFIO-passthrough threat) or (b) kldload+crafted device
(root-only). Per the audit's realism bar this is a hardware/firmware-attacker
class finding: valid primitive (confirmed here at the harness level), but no
unprivileged local escalation path exists on a default guest.
Fix (fix.diff)
Validate bus < ciss_max_logical_bus and target < CISS_MAX_LOGICAL before
indexing, at ciss.c:1393. One logical change; compiles cleanly
(-Werror) in the rebuilt ciss.ko.
Fix validation
Built ciss.ko from patched source (with DF-1190/1191/1192 applied) β compiled
with -Werror and linked (/usr/obj/usr/src/sys/dev/raid/ciss/ciss.ko, 61664 B),
new "logical drive %d has out-of-range address" string present. No live kernel
trigger available on the guest (no CISS HW), so the fix is validated at the
applies + compiles + closes-the-code-path level (the honest bar for a
hardware-only driver bug), fix_status: not_testable.
Fix verification
not_testablecompile+harness validated
module build rc=0
Confirmed kernel references
β
Detail
Exploit chain
none
Evidence (decisive lines)
β
Verdict
REPRODUCED (harness). ciss_init_logical CISS_LUN_TO_BUS/TARGET no bounds -> OOB index. No HP controller.
No comments yet.