# DF-3642 — e1000_erase_flash_bank_ich8lan: flash address accumulates across erase retries; erase failures reported as success

## What / where

`sys/dev/netif/ig_hal/e1000_ich8lan.c:e1000_erase_flash_bank_ich8lan` (lines 4692-4802),
the ICH8/PCH hardware-sequencing flash bank erase used by every NVM (EEPROM-image) commit
on em(4)-driven Intel GbE MACs (ICH8..I219). Three coupled defects in the retry loop:

1. **Address accumulation (4779):** `flash_linear_addr += (j * sector_size);` sits *inside*
   the `do { ... } while (++count < ICH_FLASH_CYCLE_REPEAT_COUNT)` retry loop instead of
   the outer `for (j ...)` loop. Every retry after a flash-cycle error (`flcerr` →
   `continue`) issues the next erase at a *higher* address: base + n·j·sector_size after n
   retries. With 256-byte sectors (`iteration` = 16) the drift reaches ~10·Σj·256 ≈ up to
   tens of KB past the intended sector, i.e. erase commands against the wrong sectors of
   the flash (both NVM banks, and the tail of whatever the GbE flash-region grant covers).
2. **Retry budget never reset per sector (4798 / 4701):** `count` is a function-scope
   variable; the 10-retry budget is shared across *all* `j` iterations, so later sectors
   can silently get zero retries.
3. **Unconditional success (4801):** when the retry budget is exhausted via the `flcerr`
   path, the `do/while` simply falls through and the function returns `E1000_SUCCESS`
   even though the last erase failed; the caller then programs dwords into an un-erased
   bank (the subsequent write failures cascade through `retry_write_flash_*`).

## How it is reached (no user syscall needed)

`em_attach` → `e1000_validate_nvm_checksum` (`if_em.c:781`, retried at `:787`) →
`hw->nvm.ops.validate` = `e1000_validate_nvm_checksum_ich8lan` (`e1000_ich8lan.c:4364`) →
if the NVM image lacks the VALID_CSUM bit (`:4395`), it *writes and updates* the NVM
(`:4397-4400`) → `e1000_update_nvm_checksum_ich8lan` (`:4214`) →
`e1000_erase_flash_bank_ich8lan(hw, bank)` (`:4246` / `:4252`).

So the erase engine runs at driver attach whenever the card's NVM content lacks the
checksum-valid bit — a malicious/counterfeit PCIe GbE device, a bit-corrupted NVM, or a
reflashed card is sufficient; no local privilege is required on the host.

## Impact

Flash-content corruption outside the intended bank (wrong sectors erased → invalid NVM
image / bricked NIC config; bounded by the PCH flash-controller region grants, so the
BIOS/ME regions stay protected on conforming parts), plus wasted write cycles into an
un-erased bank. Availability/integrity of the device, not kernel memory. Severity: Low
(hardware/NVM-content precondition).

## Reproduce (source-level)

```
sh findings/poc/DF-3642/trace.sh        # regenerates trace.log with all cited lines
git apply --check findings/poc/DF-3642/fix.diff
```

Runtime reproduction requires physical Intel ICH8/PCH GbE MAC hardware whose flash reports
cycle errors; the audit QEMU guest has only virtio NICs (see guest_env.txt), so the defect
is proven at source level and confirmed byte-identical in FreeBSD HEAD (upstream-inherited).

## Expected result after fix

Each erase command targets `bank_base_addr + j*sector_size` regardless of retry count; a
sector whose retry budget is exhausted returns `-E1000_ERR_NVM` and aborts the commit
instead of silently "succeeding".
