# 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 as `fw->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,
  `bcmp` at `fw->data + 1310892` into 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) passes
  `git apply --check` against the pristine tree, and the patched
  `oce_sysctl.c` syntax-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.
