oce_img_flashing_required bcmp's the image CRC at a fixed ~1.31 MB offset with no fw->datasize check β sibling OOB-read site missed by DF-1573
Summary
The crc offset is computed from constants and bcmp'd against fw->data without any bounds check, BEFORE the image-size gate at :389. A ~4KB crafted image that passes the build/imageid/cookie checks makes the kernel read ~1.3MB past the firmware allocation. Guard-page replica on the guest (read at +1310892 -> SIGSEGV). Datasize-plumbing fix (3 hunks, syntax-validated).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4385 Β· 11 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 1.5 KB | β raw | |
| VERDICT.md | β | 3.2 KB | β raw | |
| trigger.c | β | 2.0 KB | view raw | |
| build.sh | β | 88 B | view raw | |
| run.sh | β | 89 B | view raw | |
| run.log | β | 136 B | view raw | |
| hw_probe.log | β | 34 B | view raw | |
| fix.diff | β | 1.4 KB | view raw | |
| env.txt | β | 478 B | view raw | |
| manifest.json | β | 793 B | view raw | |
| verdict.json | β | 2.3 KB | view raw |
DF-4385 β oce_img_flashing_required reads 4 bytes at a fixed ~1.31 MB firmware offset with no bounds check
- File:
sys/dev/netif/oce/oce_sysctl.c:449-472(called from:334) - Class: CWE-125 out-of-bounds read (kernel), firmware-image-shaped
- Threat model: root writes
hw.oceN.fw_upgrade=<name>; the referenced image was registered viafirmware_get(). The image bytes are attacker- controlled if the file placed in/boot/kernelis hostile. Sibling of DF-1573 (which enumerated sites 257, 263, 265-273, 297, 322, 515 β this site was missed).
Build / run
No Emulex NIC on the verification guest (run.log: 0 19a2: PCI devices,
no hw.oce sysctl tree), so the kernel path is hardware-gated. The pack
contains:
trigger.cβ host-independent replica of the exact arithmetic (crc_offset = hdrs_size + img_offset + img_size - 4) showing the read lands ~1.31 MB into an image that may be a few KB, plus the OOB fault demonstration via mmap guard page.run.shβ guest hardware-gating probe (producesrun.log).fix.diffβ targeted fix (passfw->datasizein, validate beforebcmp).
Expected
./trigger (on any UNIX-y host with cc): prints the computed read offset,
then SIGSEGV: OOB read when the CRC read crosses the guard page β proving
the kernel would read past the firmware buffer on a truncated-but-cookie-
valid image. On the audit guest without oce hardware the path is dormant;
the demonstration is the replica + source trace in VERDICT.md.
DF-4385 VERDICT
Finding
oce_img_flashing_required() computes the CRC location of an image component
from constants plus the parsed header sizes and reads 4 bytes there without
ever consulting fw->datasize:
sys/dev/netif/oce/oce_sysctl.c:458βcrc_offset = hdrs_size + img_offset + img_size - 4;sys/dev/netif/oce/oce_sysctl.c:460βp += crc_offset;(p starts asfw->data)sys/dev/netif/oce/oce_sysctl.c:468βbcmp(flashed_crc, p, 4);
Caller: oce_be3_flashdata() case IMG_REDBOOT (:334) passes
img_offset=262144, img_size=1048576, hdrs_size=bin_offset β so the read
address is fw->data + bin_offset + 1310716. The image-size gate that would
have caught this (:389, p + size > fw->data + fw->datasize) executes only
after the switch β i.e. after oce_img_flashing_required() has already read.
Reachability: root writes hw.oceN.fw_upgrade=<image> (oce_sys_fwupgrade,
:208); firmware_get() must resolve the name (registered from
/boot/kernel). Every prior gate is satisfiable with a tiny crafted file:
build[0]=='3' + one image_hdr with imageid==1 (:265-273) + a 32-byte
cookie match anywhere after the headers (:297-303). A 4 KB file passes all
three, then the driver reads at +1.31 MB β ~1.3 MB past the end of the
firmware malloc() allocation (kernel heap OOB read; page-granular fault
possible if the walk crosses an unmapped boundary).
Relationship to DF-1573 (do-not-re-report boundary)
DF-1573 enumerated its sites precisely: 257, 263, 265-273, 297, 322 (BE3
flash path) and 515 (Lancer size -= data_written). oce_img_flashing_required
(449-472) is a separate function executing before every gate DF-1573
relies on, and is not in that list. This is the missed sibling site, not a
re-derivation.
Verification (Phase V)
Kernel-path reproduction is hardware-gated: this guest has no Emulex oce(4)
device (hw_probe.log: zero 19a2: PCI devices, no hw.oce sysctl tree),
so hw.oceN.fw_upgrade does not exist to write. Demonstrated instead:
trigger.cβ exact-arithmetic replica with a guard page: on the guest,bcmpatfw->data + 1310892into a 4096-byte readable region faults (run.log:Segmentation fault, exit 139). This proves the primitive: the kernel dereference is ~1.3 MB past the allocation.fix.diff(3 hunks: prototype, call site, definition) passesgit apply --checkagainst the pristine tree, and the patchedoce_sysctl.csyntax-checks cleanly with the guest's kernel toolchain (cc 8.3 -nostdinc, kernel include set, 0 errors).
Bottom line
Real, code-certain, sibling-site OOB read on the root-only firmware upgrade
path β same severity class as DF-1573 (Low: requires root + hostile image
file, defense-in-depth against malicious firmware). Fix is one bounds check;
fix.diff is line-accurate and compile-validated. Full runtime PoC requires
an Emulex BE3 adapter.
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_testablenot_testable at runtime (no oce NIC on guest); fix.diff (3 hunks) git-apply --check OK against pristine sys/ and syntax-validated with the guest kernel toolchain (0 errors).
fix.diff; guest cc -fsyntax-only of patched oce_sysctl.c: 0 errors.
Confirmed kernel references
Detail
Evidence (decisive lines)
run.log (guest: read at +1310892 of 4096-byte image -> SIGSEGV), trigger.c (exact arithmetic replica), VERDICT.md (path:line trace), fix.diff (git apply --check OK, syntax-validated on guest toolchain)
PoC changes
n/a - pass-2 finding authored fresh; replica written for this pack
Verified recommended fix
pass fw->datasize into oce_img_flashing_required and reject hdrs_size+img_offset+img_size > fw_datasize before the bcmp
Verdict
oce_img_flashing_required (oce_sysctl.c:449-472) bcmp's 4 bytes at fw->data + bin_offset + 262144 + 1048576 - 4 with no fw->datasize check, executing before the size gate at :389; a ~4KB cookie-valid hostile image makes the kernel read ~1.3MB past the firmware allocation. Sibling site missed by DF-1573 (which enumerated 257/263/265-273/297/322/515 only). Kernel-path run is hardware-gated (no 19a2: PCI device on guest, hw_probe.log); primitive proven by guard-page replica (SIGSEGV exit 139, run.log) and source trace. Root-only + hostile-file threat model: Low, defense-in-depth.
No comments yet.