# DF-4179 — Verification Verdict

**Status:** inconclusive (hardware-gated: no 3ware controller in the QEMU guest)
**Impact:** none on this guest (OOB struct write into the softc + cross-unit I/O confusion on affected hardware)
**Confidence:** certain (pure bounds bug, provable from source)

## Mechanism (source trace)

1. `twe_ioctl` TWEIO_ADD_UNIT → `twe_add_unit(sc, td->td_unit)` with
   `td_unit` a user-supplied `int` (twe.c:674-678, tweio.h:101-105).
2. Bound check `if (unit < 0 || unit > TWE_MAX_UNITS)` (twe.c:212) —
   **admits unit == TWE_MAX_UNITS == 16** (twereg.h:144), while
   `struct twe_softc::twe_drive` has exactly `TWE_MAX_UNITS` elements
   (twevar.h:136, indices 0..15).  `twe_del_unit` next door already uses
   the correct `>=` (twe.c:291) — asymmetric, classic off-by-one.
3. `dr = &sc->twe_drive[unit]` (twe.c:226) — one struct past the array.
   In `struct twe_softc`, `twe_drive[]` is immediately followed by
   `twe_aen_queue[TWE_Q_LENGTH]` (twevar.h:136-139), so the OOB struct
   overlays the AEN ring buffer.
4. `drives->data[unit]` (twe.c:228) reads byte 16 of the unit-summary
   parameter (the array logically has 16 entries; the underlying 512-byte
   DMA buffer makes the read itself stay in-bounds — the value is
   controller-controlled).  If the online bit is set:
   - `twe_get_param_4(..., &dr->td_size)` (twe.c:236) — OOB 4-byte write,
   - `td_state` (twe.c:242), `td_type` (twe.c:261), `td_heads`,
     `td_sectors`, `td_cylinders`, `td_twe_unit = unit` (twe.c:264-272) —
     OOB writes of controller-derived/computed values,
   - `twe_attach_drive(sc, dr)` writes `dr->td_disk` (an 8-byte kernel
     pointer, twe_freebsd.c:570) OOB and creates a ghost twedN child.
5. The ghost disk's `td_twe_unit == 16` is copied into the **4-bit**
   `cmd->io.unit` field on every I/O (twe.c:448, twereg.h:187) →
   truncates to 0 → the ghost disk's reads/writes are directed at **unit
   0** (silent cross-unit data corruption).
6. Cleanup never happens: `twe_shutdown` iterates `i < TWE_MAX_UNITS`
   (twe_freebsd.c:471) and `twe_del_unit(16)` is rejected by the correct
   `>=` — the ghost child outlives the driver state it references.

## Why it cannot be reproduced on this guest

No 3ware PCI device (vendor 0x13c1) and no /dev/twe* node exist in the
QEMU guest; `twe_addunit16` builds and runs, `open("/dev/twe0")` fails
with ENOENT (run.log).  Control node is additionally 0600 root:operator
(twe_freebsd.c:339-342).

## Fix validation

One-line `>` → `>=` (twe.c:212); applies cleanly and batch-compiled into
X86_64_GENERIC with the rest of this batch (fix_build.log).  Behavior on
hardware: TWEIO_ADD_UNIT(16) now returns EINVAL — the exact success
criterion encoded in twe_addunit16.c.

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