iir_pci_attach drives the i960 MPR register layout at fixed offsets 0x2c-0x3fc0 with no BAR0 size validation β short BAR0 => MMIO reads/writes past the resource mapping (panic or up to ~12KB wild zero-write) before the magic read-back can reject the card
Summary
BAR0 mapped then immediately driven at fixed offsets (magic at +0x1000, a 0x2FC0-byte zero-fill of 0x1000-0x3FC0, queue regs, doorbells) with no rman_get_size check against GDT_PCINEW_SZ (0x4000) - a short BAR makes every access past the mapping: page fault, or wild kernel-memory zero-write if the neighbor page is mapped (the magic write lands BEFORE the read-back check, so the zero-fill runs before the card is rejected). Crafted/broken PCIe device trigger band (same as DF-4172). Size-check fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4889 Β· 5 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 1.1 KB | β raw | |
| VERDICT.md | β | 2.9 KB | β raw | |
| fix.diff | β | 687 B | view raw | |
| verdict.json | β | 2.4 KB | view raw | |
| env.txt | β | 636 B | view raw |
DF-4889
iir_pci_attach maps BAR0 and immediately drives the i960 MPR register layout at fixed offsets
0x002c..0x3FC0 (magic write/read at 0x1000 at iir_pci.c:223-231, 0x2FC0-byte region clear at
iir_pci.c:232-233) without ever checking rman_get_size(io) >= GDT_PCINEW_SZ (0x4000). A card
with the probed IDs (0x8086:0x0600 / ICP 0x1119 range) but a short BAR0 β MMIO reads/writes past
the resource mapping: panic, or a bulk zero-write of up to ~12KB into kernel memory following the
mapping β before the magic read-back check can reject the card.
Hardware-gated finding β PoC not runnable on the audit guest (no such controller; pciconf -lv
shows no 0x8086:0x0600 / 0x1119 device β see env.txt). Driver is compiled into the guest kernel
(kldstat -v β 100 pci/iir), so the code path is live wherever the card exists.
Status: untested per the DF-4175 hardware-gated convention; the missing check is certain by
inspection. Source citations in the pass-2 result block; full narrative in VERDICT.md; fix in
fix.diff (size check right after bus_alloc_resource_any).
DF-4889 β iir_pci_attach uses fixed DPMEM offsets up to 0x3FC0 with no BAR0 size validation
Status: untested (hardware-gated β no matching controller on the audit guest; code gap certain by inspection). Severity: Low. Class: improper input validation β out-of-bounds MMIO access (CWE-125/CWE-787, device-memory variant).
Root cause (sys/dev/raid/iir/iir_pci.c)
iir_pci_attach maps BAR0 with bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE)
(iir_pci.c:186-192) and immediately drives the i960 "MPR" register layout at fixed offsets,
never comparing the mapped extent (rman_get_size(io)) against the layout size GDT_PCINEW_SZ
(0x4000, iir.h:101):
- first access:
bus_space_write_4(..., GDT_MPR_IC, GDT_MPR_MAGIC)at offset 0x1000 (iir_pci.c:223-224) followed by a read-back (iir_pci.c:225-226); - interface-area clear:
bus_space_set_region_4(..., GDT_I960_SZ, 0, GDT_MPR_SZ >> 2)β 0xBF0 words covering 0x1000..0x3FC0 (iir_pci.c:232-233); - status/command doorbells at 0x2c/0x34, queue regs up to
GDT_MPR_IC + GDT_S_INFO + 12β 0x1013 (iir_pci.c:236-301).
A card that enumerates with the probed IDs (Intel 0x8086:0x0600, or ICP vortex 0x1119:0x0100-0x02ff / 0x0300 β iir_pci.c:160-171) but declares BAR0 smaller than 0x4000 (a broken card, or a deliberately crafted PCIe device) causes every access past the mapped extent to land on the virtual page(s) after the resource mapping: unmapped β kernel page-fault panic; or mapped for another purpose β wild kernel-memory reads/writes at fixed offsets past the mapping (the 0x1000..0x3FC0 region clear at iir_pci.c:232-233 is a bulk write of zeros over up to 12KB past a short BAR).
The magic read-back at iir_pci.c:225-231 catches most broken cards if the first write/read at 0x1000 happens to fault or read back garbage β but with a short BAR whose following virtual page is writable kernel memory, the write at :223 already corrupted that page before the check, and the read-back may return exactly the magic just written, passing the check and proceeding to the 0x2FC0-byte zero-clear.
Threat model
Attacker must control PCIe-enumerated hardware (evil device, DMA-attached card, or a misbehaving/counterfeit RAID card) β a physical/supply-chain trigger, hence Low. No path from an unprivileged user. Same trigger band as sibling hardware-gated raid findings (DF-4172 etc.).
Fix
See fix.diff: require rman_get_size(io) >= GDT_PCINEW_SZ right after mapping (and, with
DF-4888's fix, the BAR is properly released when the check fails).
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_testablefix.diff authored post-verification against the read-only sys/ tree; not build-validated (no controller hardware)
findings/poc/DF-4889/fix.diff
Confirmed kernel references
Detail
Evidence (decisive lines)
findings/poc/DF-4889/VERDICT.md (offset math incl. 0x1000..0x3FC0 region clear); findings/poc/DF-4889/fix.diff; guest hardware-absence proof in findings/poc/DF-4889/env.txt
PoC changes
no runnable PoC (hardware absent); evidence pack documents the offset math and fix
Verified recommended fix
Reject attach when rman_get_size(io) < GDT_PCINEW_SZ immediately after mapping BAR0 (see fix.diff)
Verdict
Source-verified, hardware-gated: iir_pci_attach never validates rman_get_size(io) against the MPR layout size GDT_PCINEW_SZ (0x4000) yet touches fixed offsets 0x2c..0x3fc0 - the very first access (GDT_MPR_MAGIC write/read at offset 0x1000, iir_pci.c:223-231) and the GDT_MPR_SZ region clear at iir_pci.c:232-233 run past a short BAR. The write at :223 precedes the read-back check, so a writable page following a short mapping is corrupted before the card is rejected. Not runnable on the audit guest: no matching controller in pciconf (env.txt); driver compiled into the kernel (kldstat -v: '100 pci/iir').
No comments yet.