siba_pci_sprom dispatches rev-4/5/8 parsers without validating buffer size -> heap OOB read past 64-word buffer
Summary
siba_pci_sprom at siba_core.c:1372-1437: first allocs 64-word buf (SIBA_SPROMSIZE_R123), only reallocs to 220 words if CRC fails. Dispatches r45/r8 based on rev byte without checking buffer size. siba_sprom_r45 indexes word 151 (SIBA_SPROM4_PWR_INFO_CORE3), r8 indexes word 201. If 64-word path taken -> OOB read up to 276 bytes past 128-byte allocation. Crafted SPROM: R123 CRC-8 valid + rev byte=4/5/8. Fix: validate siba_spromsize>=SIBA_SPROMSIZE_R4 when rev>=4.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-1287 Β· 8 files| File | Type | Description | Size | |
|---|---|---|---|---|
| trigger_analysis.c | trigger-source | documentation marker | 900 B | view raw |
| fix.diff | suggested-fix | validate siba_spromsize >= SIBA_SPROMSIZE_R4 before dispatching to r45/r8 parsers | 1.9 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 | 3.3 KB | β raw |
| VERDICT.md | verdict | detailed source-level analysis | 4.2 KB | β raw |
DF-1287 β siba_pci_sprom dispatches rev-4/5/8 parsers without buffer-size check
Finding
siba_pci_sprom (sys/dev/netif/bwn/siba/siba_core.c:1372) initially
allocates a 64-word SPROM buffer (SIBA_SPROMSIZE_R123 = 64,
sibareg.h:303) at line 1378, reads it via siba_sprom_read at line 1382
(which also sets siba->siba_spromsize = 64), and runs a CRC check at line
1383.
Only if the CRC fails does it free and realloc a 220-word
(SIBA_SPROMSIZE_R4 = 220, sibareg.h:304) buffer at lines 1385-1390.
Then at line 1398 it extracts the SPROM revision byte from the last word
of whatever buffer it ended up with, and dispatches to a per-revision
parser (lines 1403-1428):
- rev 1/2/3 β siba_sprom_r123 (stays within 64 words)
- rev 4/5 β siba_sprom_r45
- rev 8 β siba_sprom_r8
siba_sprom_r45 indexes SIBA_SPROM4_PWR_INFO_CORE0 = 0x1080
(sibareg.h:402) through SIBA_SPROM4_PWR_INFO_CORE3 = 0x110A
(sibareg.h:405). With SIBA_OFFSET(o) = (o - SIBA_SPROM_BASE) / 2 and
SIBA_SPROM_BASE = 0x1000 (sibareg.h:305), this is word index 64..133 plus
the per-core pa offsets, well beyond the 64-word R123 buffer. Similarly
siba_sprom_r8 indexes up to word ~158 (SIBA_SPROM8_CDDPO = 0x1192,
SIBA_SPROM8_PWR_INFO_CORE3 = 0x1120, etc.).
The trigger is straightforward: a crafted SPROM image whose 64-word R123
CRC-8 is valid (so the realloc path is skipped), and whose last byte
encodes rev 4, 5, or 8. The next siba_sprom_r45 / r8 call then reads
up to ~276 bytes past the 128-byte allocation.
Fix
Validate siba->siba_spromsize >= SIBA_SPROMSIZE_R4 before dispatching to
siba_sprom_r45 or siba_sprom_r8 in any of the three dispatch sites
(chipid 0x4321 path, rev 4/5 case, rev 8 case). If the buffer is too small,
log a warning and fall back to the R123 parser (which is the only one
guaranteed to fit).
Verification on this guest
- The siba_bwn / bwn drivers are statically compiled in
(
device siba_bwnanddevice bwninsys/config/X86_64_GENERIC:267-268) and present inkldstat -v(siba_bwn/bwn). - The QEMU guest has no Broadcom BCM43xx PCI NIC (
pciconf -lshows only i440FX/PIIX/ACPI/virtio-net/virtio-blk/std-VGA), sosiba_pci_probenever matches andsiba_pci_spromis never called. Bug is not runtime-triggerable on this guest. - Source-level confirmation:
siba_core.c:1378β initial alloc isSIBA_SPROMSIZE_R123 * 2 = 128bytes.siba_core.c:1382-1383βsiba_sprom_readthen CRC; realloc only on CRC fail.siba_core.c:1398βsprom->rev = buf[siba_spromsize - 1] & 0xff.siba_core.c:1408, 1418, 1421β dispatch tor45/r8with no buffer size check.siba_core.c:1632-1710βsiba_sprom_r45accesses offsetsSIBA_OFFSET(0x1080..0x110A + extra)= words 64..133+, far past 64.siba_core.c:1727-1860βsiba_sprom_r8accesses up to word ~158.sibareg.h:303-305, 402-405β confirming the constants.- Fix verified to compile (combined build with DF-1278/1279/1280/1285).
Realistic impact ceiling
Hardware-attacker (PCIe WiFi card or USB-attached Broadcom chip with crafted
SPROM) heap OOB read past a 128-byte M_DEVBUF allocation at attach time.
The read feeds struct siba_sprom fields β information leak of adjacent
slab data is the realistic ceiling; no write primitive through this path.
VERDICT β DF-1287
Status
INCONCLUSIVE (source-confirmed; not runtime-triggerable on this guest).
Mechanism (source-confirmed)
siba_pci_sprom (sys/dev/netif/bwn/siba/siba_core.c:1372):
- Line 1378 β allocates a 64-word buffer (
SIBA_SPROMSIZE_R123 = 64,sibareg.h:303) β i.e. 128 bytes. - Line 1382 β
siba_sprom_read(siba, buf, SIBA_SPROMSIZE_R123)reads 64 words and setssiba->siba_spromsize = 64. - Line 1383 β runs
sprom_check_crc(buf, siba->siba_spromsize)on the 64-word image. - Lines 1384-1394 β only if CRC fails, free + realloc a 220-word
buffer (
SIBA_SPROMSIZE_R4 = 220,sibareg.h:304). - Line 1398 β
sprom->rev = buf[siba_spromsize - 1] & 0xff. - Lines 1403-1428 β dispatch on
siba->siba_chipidthen onsprom->rev: - rev 1/2/3 βsiba_sprom_r123(stays within 64 words). - rev 4/5 βsiba_sprom_r45- rev 8 βsiba_sprom_r8
siba_sprom_r45 (siba_core.c:1632) walks SIBA_SPROM4_PWR_INFO_CORE0..3
(sibareg.h:402-405: 0x1080..0x110A) plus per-core offsets, i.e.
SIBA_OFFSET = (0x1080..0x110A - SIBA_SPROM_BASE) / 2 = 64..133, far past
the 64-word buffer. siba_sprom_r8 (siba_core.c:1727) walks
SIBA_SPROM8_* constants up to SIBA_SPROM8_CDDPO = 0x1192
(sibareg.h:523), i.e. SIBA_OFFSET = 0xc8 = 200, plus the
SIBA_SHIFTOUT_4 macro adds another +2 β word 202.
The trigger is a crafted SPROM image with a valid 64-word R123 CRC and a
last byte claiming rev 4/5/8. siba_sprom_r45 / r8 then read up to
~276 bytes past the 128-byte allocation. The read values are written into
struct siba_sprom fields.
Fix
Validate siba->siba_spromsize >= SIBA_SPROMSIZE_R4 before dispatching to
siba_sprom_r45 / siba_sprom_r8 in any of the three dispatch sites
(chipid 0x4321 path, rev 4/5 case, rev 8 case). If too small, log a
warning and fall back to siba_sprom_r123 (the only parser guaranteed to
fit). See fix.diff.
Verification on this guest
siba_bwnandbwnare statically compiled in (device siba_bwn,device bwnatsys/config/X86_64_GENERIC:267-268).- No Broadcom BCM43xx PCI NIC in
pciconf -l(only i440FX/PIIX/ACPI/ virtio-net/virtio-blk/std-VGA), sosiba_pci_probenever matches andsiba_pci_spromis never called. Not runtime-triggerable. - Source-level proof:
siba_core.c:1378β initial allocSIBA_SPROMSIZE_R123 * 2 = 128bytes.siba_core.c:1382-1383β read + CRC.siba_core.c:1384-1394β realloc only on CRC fail.siba_core.c:1398βsprom->rev = buf[siba_spromsize - 1] & 0xff.siba_core.c:1408, 1418, 1421β dispatch to r45 / r8 with no size check.siba_core.c:1632-1710βsiba_sprom_r45reads words 64..133+.siba_core.c:1727-1860βsiba_sprom_r8reads up to word ~202.sibareg.h:303-305, 402-405, 523, 532, 557β confirming the constants.- Fix validation: combined
X86_64_GENERICrebuild with this fix applied exitedrc=0. Full log:combined_build.log.
Exploit chain
None. The primitive is a kernel-heap OOB read past a 128-byte M_DEVBUF
allocation. The read values feed struct siba_sprom fields (wireless
calibration data). The realistic ceiling is information leak of adjacent
slab data; there is no write primitive through this path.
Realistic impact ceiling
Hardware-attacker (PCIe WiFi card or USB-attached Broadcom chip with crafted
SPROM) heap OOB read at attach time. CVSS:
AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:N/A:H β AV:L because physical access is
the realistic vector (an external WiFi NIC); the read is large enough (up
to ~276 bytes) to leak substantial kernel heap.
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 siba_spromsize >= SIBA_SPROMSIZE_R4
before dispatching to r45/r8. See fix.diff. The implementation falls back
to siba_sprom_r123 rather than skipping the parser entirely, so that
already-present R123 fields (MAC, board info) are still populated.
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. siba_pci_sprom r45/r8 parsers on undersized 64-word buffer -> ~276B heap OOB read. siba_bwn in GENERIC, no Broadcom WiFi.
No comments yet.