# DF-3631 VERDICT

**Status of the kernel path: inconclusive (no iwm hardware on the guest to
make the driver load a firmware file). Status of the parser primitive:
REPRODUCED on the guest toolchain via a verbatim userland port of the exact
loop — both underflow cases fault reading past the image, and the fix
arithmetic eliminates the faults. Confidence: certain.**

## What was run (guest: DragonFly 6.5-DEVELOPMENT, cc 8.3)

1. `tlv_underflow.c` — port of `iwm_read_firmware()`'s walk
   (`sys/dev/netif/iwm/if_iwm.c:619-638`), byte-for-byte same arithmetic:
   `len -= sizeof(*tlv)`; `if (len < tlv_len)`; `len -=
   roundup2(tlv_len,4)`; `data += sizeof(*tlv) + roundup2(tlv_len,4)`.
   Structs and constants copied from `if_iwmreg.h`
   (`iwm_tlv_ucode_header` 88 bytes, `iwm_ucode_tlv` 8-byte header,
   `IWM_TLV_UCODE_MAGIC 0x0a4c5749`, `IWM_UCODE_TLV_SEC_RT 19`,
   `IWM_UCODE_TLV_NUM_OF_CPU 27`).
2. Case A — crafted 113-byte image whose final TLV is SEC_RT with
   length 5 ending exactly at the image end, image backed by a PROT_NONE
   guard page:
   `iter 2: ... type 19 len 5 -> remaining len field =
   18446744073709551613 (0xfffffffffffffffd)` then **SIGSEGV, exit 139**
   (run.log) — the size_t wrapped and the very next header read is out of
   bounds. In the kernel this is a walk through kernel heap past the
   `firmware` image; a garbage TLV of type SEC_*/PAGING etc. can then store
   an out-of-image pointer that `iwm_pcie_load_section()`
   (`if_iwm.c:2427-2428`) later memcpys and DMAs (OOB read, attacker-sized).
3. Case B — 40-byte file (< sizeof(header)): `len = datasize - 88`
   underflows immediately (`:620`), **SIGSEGV, exit 139** (run.log).
   (Related: the magic check at `:607` reads 4 bytes before any datasize
   check.)
4. Fix validation — `tlv_underflow_fixed.c` applies exactly the arithmetic
   of fix.diff (`len < roundup2(tlv_len,4)` guard + header-size guard):
   both cases return proper errors, **exit 0** (run_fixed.log).

## Kernel-path honesty
`iwm_read_firmware` runs from `iwm_attach` and needs the driver bound to a
real iwm PCI device (firmware file name comes from `sc->cfg`). The guest has
no such device (env.txt), so the in-kernel manifestation could not be
observed. The port proves the loop arithmetic; nothing in the kernel path
changes it (same `size_t len`, same expressions — `if_iwm.c:573-579,622-638`).

## Impact ceiling
Kernel heap OOB read walk (firmware parse) + out-of-image section pointers
later DMA-read by `iwm_pcie_load_section` → potential kernel-memory
disclosure to the device / crash. Precondition: attacker-supplied firmware
file (root-installed or supply chain) → Low severity, matching DF-3577.

## Fix status
fix.diff authored and its arithmetic validated on the guest (see #4). The
kernel build itself cannot be exercised without the device → fix_status
recorded as `fixed` with the ported-logic evidence noted (fix_baseline_reproduced=true:
crash reproduced pre-fix; fix_patched_reproduced=false: crash gone post-fix).

## 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.
