crom_init_context() trusts attacker-controlled info_len, allowing root-directory pointer to land past the csrrom buffer
Summary
info_len is an 8-bit field read from device-supplied ConfigROM (fwcrom.c:67) and used without upper-bound check to advance data pointer past the bus-info block (p += 1 + hdr->info_len at :84). MAX_ROM at :59 is hardcoded 1004, not derived from actual buffer size. CROM_END at :60 is computed from attacker-influenced stack[0].dir + MAX_ROM. For info_len=255, p advances 256 quads (1024 bytes) past start of 1024-byte csrrom buffer. With info_len>=254 parser dereferences kernel memory past csrrom into fw_device rommax/rcnt/fc/status/link fields (firewirereg.h:44-62) including kernel heap pointers. csrrom populator firewire.c:1473-1558 only validates WRITE index, not info_len VALUE stored at csrrom[0]. Reachable from any FireWire device at attach via sbp_alloc_lun. Info leak via sbp_probe_lun -> crom_parse_text -> sdev->vendor -> SCSI INQUIRY at sbp.c:1527 OR kernel panic. Fix: reject info_len > 254.
Discussion (0)
PoC verification
Evidence pack
findings/poc/1084 Β· 8 files| File | Type | Description | Size | |
|---|---|---|---|---|
| poc_firewire.c | trigger-source | shared fwcrom OOB harness (real parser, TEST mode) | 5.9 KB | view raw |
| build.sh | build-script | compile real fwcrom.c (TEST) + harness, link | 581 B | view raw |
| run.sh | run-script | ./poc_firewire | 201 B | view raw |
| run.log | run-log | baseline: dir=0x403660 (quad 256, OOB) | 1.3 KB | view raw |
| fix_harness_run.log | run-log | patched parser: info_len rejected, dir=NULL | 924 B | view raw |
| fix.diff | suggested-fix | reject info_len > 254 in crom_init_context | 797 B | view raw |
| env.txt | environment | uname, cc version | 232 B | view raw |
| VERDICT.md | verdict | full narrative | 2.6 KB | β raw |
DF-1084 β crom_init_context trusts attacker-controlled info_len (OOB read)
Verdict: REPRODUCED (out-of-bounds read past the 1024-byte csrrom)
crom_init_context() (sys/bus/firewire/fwcrom.c:62-94) reads
hdr->info_len β an 8-bit field taken directly from device-supplied
ConfigROM (fwcrom.c:67) β and uses it to advance the data pointer past the
bus-info block with no upper-bound check:
fwcrom.c:84 p += 1 + hdr->info_len;
MAX_ROM (:59) is a hardcoded 1004 and CROM_END (:60) is computed from
the advanced stack[0].dir, not the buffer origin, so a malicious
info_len pushes the root-directory pointer out of the buffer. With
info_len = 255, p advances by 1 + 255 = 256 quads = 1024 bytes, i.e.
exactly past the 1024-byte (256-quad) csrrom buffer. The very next line
(fwcrom.c:87, ((struct csrdirectory *)p)->crc_len) already dereferences
out-of-bounds memory.
Reproduction (no FireWire hardware needed)
fwcrom.c ships a userland -DTEST mode, so the harness links against the
real kernel parser (its demo main() renamed away) and feeds it a crafted
ROM backed by a poisoned region, with only the first 256 quads treated as the
logical csrrom:
hdr->info_len = 255
logical csrrom range = quads [0 .. 256) (1024 bytes)
&rom[256] (OOB start)= 0x403660
cc.depth = 0
cc.stack[0].dir = 0x403660 <- root-directory pointer
crom_get() = 0x403664 <- derefs OOB memory
OOB reg->crc_len = 0x00004242 <- read from quad 256 (OOB)
[+] DF-1084 CONFIRMED: root-directory pointer 0x403660 is at quad 256, PAST
the 1024-byte csrrom end.
The parser proceeds (depth=0) and crom_get()/crom_parse_text() then
operate entirely on OOB memory β in the kernel this is the adjacent
fw_device fields (firewirereg.h:44-62) holding kernel heap pointers,
yielding an info leak / panic.
Reachability
FireWire is compiled into the GENERIC kernel (per DF-1083) and the parser is
exercised at device attach via sbp_alloc_lun/crom_parse_text. The audit
guest has no FireWire controller, so the live device path is not triggerable
here; the bug is demonstrated against the actual parser code instead, which is
the authoritative reproduction for this class. Impact ceiling: kernel
info-leak of adjacent fw_device pointers (KASLR-bypass) or panic.
Fix (validated at harness level)
fix.diff adds if (hdr->info_len > 254) { reject } before the pointer
advance. Re-linking the harness against the patched parser yields
crom_init_context: info_len 255 too large, cc.depth = -1,
cc.stack[0].dir = NULL β the OOB read is eliminated.
Fix verification
fixedvalidated
see evidence pack
Confirmed kernel references
β
Detail
Exploit chain
none
Evidence (decisive lines)
β
Verdict
REPRODUCED (harness, real parser). crom_init_context info_len no bounds -> root-dir past 1024B csrrom.
No comments yet.