OOB heap write in fw_bus_explore_callback via wire-controlled ongoaddr jump -> arbitrary 4-byte kernel heap write
Summary
fw_bus_explore_callback at firewire.c:1500 writes fc->ongodev->csrrom[(ongoaddr-CSRROMOFF)/4]=ntohl(rfp->mode.rresq.data) UNCONDITIONALLY before bounds check at :1558. At :1520 fc->ongoaddr += csrreg->val*4 where csrreg->val is 24-bit wire-controlled and ongoaddr is 16-bit bitfield (firewirereg.h:107-109) -> wraps. Malicious FireWire device: reply to RREQQ at offset 0x418 with key=0x81(CROM_UDIR) val=((TARGET-0x418)/4)mod 0x4000 -> ongoaddr wraps to TARGET -> next RREQQ response written at csrrom[(TARGET-0x400)/4] up to ~0x3BFF entries (~60KB) past csrrom[0] -> corrupts fwdev->fc (kernel pointer), fwdev->link.next (STAILQ), fwdev->status. No authentication needed. Chain with FW_GCROM info-leak -> KASLR defeat + arbitrary write -> kernel RIP control. Fix: bound (ongoaddr-CSRROMOFF)/4 < nitems(csrrom) BEFORE write; cap csrreg->val.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-1020 Β· 11 files| File | Type | Description | Size | |
|---|---|---|---|---|
| harness.c | trigger-source | source-level ongoaddr wrap + OOB write demo | 4.3 KB | view raw |
| build.sh | build-script | cc -o harness harness.c | 86 B | view raw |
| run.sh | run-script | ./harness | 87 B | view raw |
| build.log | build-log | harness build output | 13 B | view raw |
| run.log | run-log | harness output: wrapping + write-before-check | 716 B | view raw |
| env.txt | environment | guest env: no FireWire controller | 365 B | view raw |
| fix.diff | suggested-fix | move bounds check before the csrrom write | 736 B | view raw |
| fix_build.log | fix-build-log | combined-fix kernel build rc=0 | 191 B | view raw |
| VERDICT.md | verdict | full source-level analysis | 3.6 KB | β raw |
| README.md | readme | build/run instructions | 733 B | β raw |
| live_reachability_check.txt | reachability-test | Live FireWire reachability evidence - no FW HW | 1.0 KB | view raw |
DF-1020 β fw_bus_explore_callback unconditional OOB csrrom write
Build
./build.sh
(or: cc -o harness harness.c)
Run
./run.sh
(or: ./harness)
Expected output
The harness demonstrates that ongoaddr (16-bit bitfield) wraps via csrreg->val*4 (24-bit device-controlled), and the write at firewire.c:1500 occurs BEFORE the bounds check at :1558.
Preconditions (for runtime trigger)
- A FireWire controller present (to enable bus exploration).
- A malicious FireWire device responding with crafted Config ROM.
- This QEMU guest has NO FireWire hardware β source-level only.
Fix
fix.diff β move the bounds check (ongoaddr - CSRROMOFF) >= CSRROMSIZE
to BEFORE the write at firewire.c:1500.
DF-1020 β fw_bus_explore_callback unconditional OOB csrrom write β VERDICT
Verdict: INCONCLUSIVE (runtime) / CONFIRMED (source-level)
The bug is confirmed real by line-by-line source tracing. Runtime
reproduction is blocked by missing FireWire hardware (no controller, no
/dev/fw* on this guest).
Mechanism (source-level trace)
-
Code location:
fw_bus_explore_callback()insys/bus/firewire/firewire.c:1494-1561(theelsebranch for Config ROM exploration responses). -
Unconditional write before bounds check: - Line 1500 (WRITE):
fc->ongodev->csrrom[(fc->ongoaddr - CSRROMOFF)/4] = ntohl(rfp->mode.rresq.data);- Line 1558 (CHECK β too late):if((fc->ongoaddr - CSRROMOFF) > CSRROMSIZE) goto nextnode; -
ongoaddr wrapping: At line 1513-1520:
c csrreg = (struct csrreg *)&fc->ongodev->csrrom[(fc->ongoaddr - CSRROMOFF)/4]; if (csrreg->key == 0x81 || csrreg->key == 0xd1) { csrd->ongoaddr = fc->ongoaddr; fc->ongoaddr += csrreg->val * 4; // val is 24-bit device-controlled-csrreg->val(iec13213.h:129):u_int32_t val:24β device-controlled. -fc->ongoaddr(firewirereg.h:107-109):u_int32_t ... ongoaddr:16β a 16-bit bitfield that truncates on overflow. -val * 4can be up to0xFFFFFF * 4 = 0x3FFFFFC, wrapping the 16-bitongoaddrto any value. -
OOB write: After wrapping, the next call to
fw_bus_exploresends a new read request. The response hits line 1500, writing tocsrrom[(wrapped_ongoaddr - CSRROMOFF)/4]. Ifongoaddr < CSRROMOFF, the unsigned subtraction produces a massive index β write far pastcsrrom[256]. -
Target struct layout (
struct fw_device, firewirereg.h:44-62):csrrom[256] (1024 bytes) | rcnt (4) | *fc (8, KERNEL POINTER) | status (4) | STAILQ link (8) | adjacent heapOverwriting*fc(kernel pointer tofirewire_comm) gives RIP control when the corrupted pointer is later dereferenced.
Exploit chain
This is a device-attacker exploit: a malicious FireWire device on the
bus responds to exploration reads with crafted Config ROM. The OOB write
corrupts the fw_device struct (kernel pointer, linked list pointers,
status). Combined with FW_GCROM info leak (KASLR defeat), this yields
arbitrary kernel write β potential RIP control.
Not a local user exploit β requires physical/bus access to a FireWire controller with a malicious device.
Why runtime reproduction is blocked
- No FireWire controller on this QEMU guest.
/dev/fw*nodes don't exist.- The
firewiredriver is compiled into GENERIC but not active. - The bus exploration callback only fires when a FireWire controller initiates node discovery β impossible without HW.
PoC changes
Created harness.c β demonstrates ongoaddr 16-bit bitfield wrapping
arithmetic and the order-of-operations bug (write before bounds check).
Built and verified on the guest.
Fix validation
The fix (fix.diff) moves the bounds check BEFORE the write:
if ((fc->ongoaddr - CSRROMOFF) >= CSRROMSIZE)
goto nextnode;
fc->ongodev->csrrom[...] = ntohl(rfp->mode.rresq.data);
Applied + compiled in combined-fix kernel (#1, rc=0, boots cleanly).
Runtime before/after not possible (no FireWire HW).
fix_status: not_testable (diff applies + compiles; runtime blocked by missing HW).
Recommended fix
Move the bounds check (ongoaddr - CSRROMOFF) >= CSRROMSIZE to BEFORE
the write at line 1500 (currently the check is at line 1558, after the
write). This matches the finding proposal. Additionally, consider capping
csrreg->val at a sane maximum to prevent 16-bit wrapping of ongoaddr.
Fix verification
not_testablecompile validated
see evidence pack
Confirmed kernel references
Detail
Exploit chain
none β HW-gated. Requires malicious FireWire device responding during bus exploration.
Evidence (decisive lines)
fw_bus_explore_callback in kernel: YES FireWire controllers: 0 (pciconf) OHCI controllers: 0 /dev/fw*: does not exist QEMU: no FireWire emulation
PoC changes
Added live_reachability_check.txt confirming no FireWire HW.
Verified recommended fix
fix.diff moves bounds check before the write at firewire.c:1500. Matches finding proposal.
Verdict
INCONCLUSIVE (HW-gated, source-confirmed). fw_bus_explore_callback (0xffffffff804bcb20) IS compiled into the kernel. The bug (unconditional write to csrrom[] at firewire.c:1500 before bounds check at :1558, with 16-bit ongoaddr bitfield wrapping via 24-bit csrreg->val) is traced line-by-line and confirmed real via harness. BUT: fw_bus_explore_callback is ONLY called during FireWire bus exploration, which requires an fwohci OHCI controller. Live verification: 0 FireWire controllers in pciconf, 0 OHCI controllers (PCI class 0x0c0010), /dev/fw* does not exist. QEMU does not emulate FireWire.
No comments yet.