# DF-3670 — VERDICT

**Status: inconclusive (runtime) / source-level certain. Impact class: wrong NVM checksum decisions from crafted NVM (attach-time DoS of the NIC / bad-NVM acceptance; persistent NVM corruption via update path). Hardware-gated.**

## Root cause

`ixgbe_calc_eeprom_checksum_generic` (sys/dev/netif/ix/ixgbe_common.c:2211):
the section walk is driven entirely by NVM-resident values:

- `pointer` read at 2233 from EEPROM words `IXGBE_PCIE_ANALOG_PTR..IXGBE_FW_PTR`
- `length` read at 2242 *at that pointer*
- loop at 2250 `for (j = pointer + 1; j <= pointer + length; j++)` with
  `u16 j` (2214) — no bound of `pointer`/`length` against
  `hw->eeprom.word_size`, which itself is hardware/NVM-reported
  (`ixgbe_init_eeprom_params_generic`, 1277-1280: `word_size =
  1 << (eeprom_size + IXGBE_EEPROM_WORD_SIZE_SHIFT)` from `EEC.SIZE`).

Failure modes with crafted NVM:

1. `pointer`/`length` chosen so `pointer + length >= 65536`: `j` wraps at
   65536 while the (int-promoted) comparison still holds — the walk visits
   unintended words; with `word_size > 65536` (EEC.SIZE lie) reads "succeed"
   and the checksum covers the wrong region.
2. Any `pointer >= word_size`: per-word `eeprom.ops.read` fails → attach
   aborts (ixgbe_validate_eeprom_checksum at if_ix.c:615 → "The EEPROM
   Checksum Is Not Valid" → ENXIO): **crafted-NVM NIC-disable DoS**.
3. `ixgbe_update_eeprom_checksum_generic` (2320-2346) writes the wrongly
   computed checksum to NVM word `IXGBE_EEPROM_CHECKSUM` — persistent
   corruption of the adapter NVM (persisted across reboots).

## Upstream divergence — the fix exists in FreeBSD, missing here

Function-level diff against FreeBSD `sys/dev/ixgbe/ixgbe_common.c` (fetched
during this audit to /tmp/opencode/fx_ixgbe_common.c) shows upstream added:

```c
if (pointer >= hw->eeprom.word_size) { ... return IXGBE_ERR_EEPROM; }
if (length  >= hw->eeprom.word_size - pointer) { ... return IXGBE_ERR_EEPROM; }
u32 j; u32 word_end = (u32)pointer + length;
```

DragonFly's file (md5 1a6c0a6673928d2b95a53dfd55c308d2, 2017 shared-code
snapshot) predates it. `fix.diff` in this pack imports the upstream bounds
(minimal form, keeping the local code style).

## Why inconclusive at runtime

The walk executes during `ix_attach` → `ixgbe_validate_eeprom_checksum`
(if_ix.c:614-619). The audit guest has no ixgbe PCI device (env.txt: pciconf
shows only i440FX-bridge Intel devices; dev.ix.* count 0), so the path never
runs. Crafting an NVM requires physical access to the adapter (or a hostile
NIC), placing this in the malicious-hardware trust class — consistent with
DF-3642 (Low, certain, same "flash/NVM correctness" family).

## Fix validation

`fix.diff` applied to guest's md5-identical `/usr/src`; `if_ix.ko` (containing
ixgbe_common.c) rebuilt with `-Werror`, zero errors (`build_patched.log`).
Runtime before/after needs hardware — not available.

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