OOB heap write/read in fw_bus_explore_callback via unchecked ongoaddr (Config ROM parser)
Summary
When host reads remote FireWire node Config ROM during bus enumeration fw_bus_explore_callback() writes each 4-byte response into fwdev->csrrom[(ongoaddr-CSRROMOFF)/4] BEFORE verifying ongoaddr in range. Sole bounds check at :1558 uses > instead of >= (off-by-one allowing csrrom[0x100]) and reached only AFTER write. Directory-entry jump at :1520 (fc->ongoaddr += csrreg->val*4) has NO bounds check so malicious ROM with Unit-Directory key (0x81/0xd1) and large 24-bit val lands ongoaddr past CSRROMSIZE. Next callback writes attacker-controlled bytes into heap after csrrom[] overwriting fwdev->rcnt fwdev->fc pointer fwdev->status fwdev->link. On 64-bit csrrom[0x101]/[0x102] alias low/high halves of fc pointer; corrupting yields controlled kernel-pointer deref in fwmem_xfer_req. rommax set to ongoaddr with no upper bound so FW_GCROM copyout leaks kernel heap to userspace. Attacker: any device physically on IEEE 1394 bus. No authentication required. Impact: kernel heap corruption with attacker-controlled value and offset.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-2288 Β· 6 files| File | Type | Description | Size | |
|---|---|---|---|---|
| VERDICT.md | verdict | gate analysis + source trace (write-before-check, off-by-one, unbounded dir jump) | 4.8 KB | β raw |
| fix.diff | suggested-fix | bound ongoaddr before write, clamp directory-entry jump, fix > -> >= | 1003 B | view raw |
| build.sh | build-script | documents HW gate (no binary built) | 454 B | view raw |
| run.sh | run-script | prints gate proof | 519 B | view raw |
| env.txt | environment | guest uname + pciconf/ifconfig/usbconfig/kldstat/dmesg | 1.1 KB | view raw |
| gate_proof.txt | gate-proof | pciconf grep fwohci empty, /dev/fw* absent | 61 B | view raw |
DF-2288 β OOB heap write/read in fw_bus_explore_callback (CSR ROM parser)
Verdict: NOT REPRODUCED (HW-gated); REAL BUG IN SOURCE (defense-in-depth fix warranted)
Hardware gate (why the PoC cannot run on this guest)
The DragonFlyBSD audit guest is a QEMU/KVM VM with no FireWire (IEEE 1394) hardware whatsoever. Confirmed at audit time:
$ pciconf -l # no fwohci / firewire bridge present hostb0@pci0:0:0:0: class=0x060000 ... (i440fx hostbridge) isab1@pci0:0:1:0: class=0x060100 ... (PIIX3 ISA bridge) atapci0@pci0:0:1:1: class=0x010180 ... (PIIX3 IDE) vgapci0@pci0:0:2:0: class=0x030000 ... (Bochs/QEMU std VGA) virtio_pci0/1 ... (net + blk) $ ls /dev/fw* # /dev/fw*: No such file or directory $ ifconfig -l # vtnet0 lo0 (no fwip/fwe firewire net iface)
There is no FireWire controller (fwohci) attached, no /dev/fw* character
device, and no firewire network interface. The vulnerable path
fw_bus_explore_callback() runs only in the FireWire stack's bus-enumeration
state machine, which is driven by fwohci interrupt delivery from real 1394
hardware during bus exploration. With no fwohci device and no /dev/fw* node
reachable by the unprivileged maxx user, the callback can never be driven by
attacker-controlled Config-ROM responses on this guest.
The hw.firewire.* sysctl nodes exist only because the firewire subsystem is
compiled into the kernel; they are inert defaults β pciconf -l proves no
controller is probed/attached.
Source trace β the bug is REAL (sys/bus/firewire/firewire.c)
The claim is accurate. The write happens BEFORE the bounds check, the bounds
check is an off-by-one (> instead of >=), and the directory-entry jump
advances ongoaddr with no bounds check at all.
fw_device carries u_int32_t csrrom[CSRROMSIZE/4] = csrrom[0x400/4] =
csrrom[256] (sys/bus/firewire/firewirereg.h:51-54; CSRROMOFF = CSRROMSIZE =
0x400). Valid offsets are csrrom[0..255].
-
Write-before-check.
firewire.c:1500:c fc->ongodev->csrrom[(fc->ongoaddr - CSRROMOFF)/4] = ntohl(rfp->mode.rresq.data);stores the attacker-controlled (peer-supplied) 4-byte Config-ROM quadlet intocsrrom[]indexed byongoaddrunconditionally, then the only bounds check appears ~58 lines later atfirewire.c:1558:c if((fc->ongoaddr - CSRROMOFF) > CSRROMSIZE){ // > should be >= goto nextnode; }Soongoaddr == CSRROMOFF + CSRROMSIZE(index 256, one past end) is written first and only then (incorrectly) allowed through. -
Unbounded directory-entry jump.
firewire.c:1514-1524: when the parser sees a Unit-/Directory-entry key (0x81/0xd1) it doesc fc->ongoaddr += csrreg->val * 4; // firewire.c:1520csrreg->valis a 24-bit field taken directly from the (malicious) ROM with no upper bound. A crafted ROM can therefore advanceongoaddrfar pastCSRROMSIZE, and the next callback iteration writes attacker bytes atcsrrom[(ongoaddr-CSRROMOFF)/4]deep past the end of thefw_deviceheap object. On amd64csrrom[0x101]/[0x102]alias the low/high halves of the followingfcpointer (firewirereg.hfw_device layout), yielding a controlled kernel-pointer dereference infwmem_xfer_req. -
Info-leak path.
rommaxis set toongoaddrwith no upper bound (firewire.c:1501-1503), and the General-Config-ROM copyout (FW_GCROM) later copiescsrrom[]out to userspace, leaking post-buffer kernel heap.
Impact (on real FireWire hardware, absent here): kernel heap write of attacker-controlled value at an attacker-influenced offset, plus a kernel-heap info-leak via FW_GCROM. Trigger: any device physically on the IEEE 1394 bus; no authentication.
Exploit chain status
Not pursuable on this guest β the primitive is gated behind absent FireWire hardware (valid Phase-6 hard blocker: "vulnerable code path dead/unreachable at runtime on this guest AND no harness can exercise it" because it requires a live 1394 peer responding with crafted ROM quadlets). The bug is a real, write-capable heap-corruption primitive on hardware that owns a 1394 controller; the defense-in-depth fix below closes it.
PoC changes
None. No PoC source was authored or runnable: the /dev/fw* device does not
exist and the fwohci controller is absent, so neither a userspace ioctl
reproducer (which would need an attached FireWire peer's responses) nor a kernel
harness can drive fw_bus_explore_callback on this guest. The README claim was
verified purely by source trace.
Recommended fix
Bound ongoaddr before the write and fix the off-by-one. See fix.diff
(supersedes finding proposal by hardening the directory-jump path the finding
markdown focuses on, plus the >β>= correction).
Fix verification
not_testablenot_testable: PoC cannot run on this guest (HW-gated, no target device). fix.diff validated by git apply --check (clean) + line-accurate source trace confirming it closes the cited path.
git apply --check findings/poc/DF-2288/fix.diff -> OK (clean apply). No runtime test possible (HW-gated).
Confirmed kernel references
Detail
Exploit chain
none β valid hard blocker (driver/device path dead at runtime on this guest: no target HW / no attached device). No unprivileged->root path.
Evidence (decisive lines)
usbconfig list -> No device match or lack of permissions.; pciconf -l -> no target controller HW; ifconfig -l -> vtnet0 lo0; kldstat -> kernel/ehci/xhci only; ls /dev/<target> -> No such file or directory; id maxx -> uid=1001 groups=1001 (not operator). Source confirmed at cited lines.
PoC changes
Created findings/poc/DF-2288/{VERDICT.md,fix.diff,build.sh,run.sh,env.txt,gate_proof.txt,manifest.json}. No PoC source (HW-gated).
Verified recommended fix
bound ongoaddr before write, clamp dir-jump, fix > to >=. Full git-apply-able diff in findings/poc/DF-2288/fix.diff (git apply --check OK).
Verdict
NOT REPRODUCED (HW-gated). The bug is REAL in source (traced line-by-line). firewire fw_bus_explore_callback OOB heap write/read; no FireWire controller, no /dev/fw, ifconfig vtnet0 lo0 only. Gate confirmed via usbconfig list (No device match / no /dev/ugen), pciconf -l (no target controller HW), ifconfig (vtnet0 lo0 only), kldstat (no target module), and ls /dev (no target nodes). maxx (uid 1001, not in operator) cannot reach any /dev/usbctl write path. write-before-bounds-check at firewire.c:1500, off-by-one at :1558, unbounded dir-jump at :1520; malicious 1394 peer needed
No comments yet.