# DF-4336 — VERDICT

**Status: untested** — the defect lives in the twa(4) reset state machine;
exercising it requires a real 3ware 9000-series controller whose firmware
hangs or whose command queue saturates past request deadlines.  The audit
guest has no twa hardware (`/dev/twa*` absent, 0 PCI vendor-0x13c1 devices;
see ../DF-4335/build.log).  No software-only entry point exists.

**Confidence: likely** — the missing entry guard is certain from the code;
the severity of the resulting interleavings on real hardware is an
engineering judgment (wedge/reset-storm is the realistic ceiling; no
deterministic kernel-memory corruption was derivable because every queue
operation is individually `gen_lock`-protected, tw_cl.h:270-313).

## Trace

1. `tw_cl_reset_ctlr` (tw_cl_io.c:1049-1130) begins
   `ctlr->reset_in_progress = TW_CL_TRUE;` at **1060** and clears it at
   **1123** — the flag is never *checked* at entry, by itself or by any
   caller.
2. Caller A — watchdog callout thread (tw_osl_freebsd.c:469-477):
   `i_need_a_reset = tw_cl_is_reset_needed(...); if (i_need_a_reset) { ...
   tw_cl_reset_ctlr(ctlr_handle); }`.  The callout is MPSAFE
   (tw_osl_freebsd.c:422-424) and takes no lock.
3. Caller B — ioctl thread in `tw_osli_fw_passthru`
   (tw_osl_freebsd.c:1005-1011): after a 60 s passthru timeout,
   `if (!tw_cl_is_reset_needed(...)) tw_cl_reset_ctlr(...)`.  The
   reset-needed test and the call are not atomic w.r.t. the watchdog
   setting the flag; and once the flag is set the watchdog calls
   unconditionally, even while caller B is mid-reset (the flag is cleared
   only at the END of a reset, tw_cl_io.c:1124).
4. Concurrent bodies: two `tw_cli_soft_reset` runs race the single
   firmware phase-1 notification (tw_cl_io.c:1208-1213, up to 60 s each),
   interleave `tw_cli_init_connection` credit renegotiation
   (tw_cl_io.c:1090-1101), interleave RESET_Q→PENDING requeues
   (tw_cl_io.c:1113-1116) with the other reset's drains
   (tw_cl_io.c:1071-1073), and the first finisher clears
   `reset_in_progress` (1123) while the second is still resetting —
   re-opening the submission gate (tw_cl_io.c:142-143, 338-339) into an
   active reset.

## Impact ceiling

Controller reset storm / permanent I/O wedge (all disks behind the
controller stall; each passthru owner loops on 60 s timeouts).  Kernel
memory-safety effects were investigated and NOT established: individual
queue ops are gen_lock-serialized, drains partition requests atomically,
and the mid-submission window (tw_cl_io.c:1064-1069 comment) hands the
request to a post-reset controller rather than to another owner.  Filed as
Low (specific-hardware DoS / state-machine race), not memcorrupt.

## Fix

`tw_cl_reset_ctlr` should decline to run when a reset is already in flight
(test-and-set `reset_in_progress` under `gen_lock`, return `TW_OSL_EBUSY`),
and `reset_needed` should be latched at reset *start* so a concurrent
watchdog tick re-arms the *next* reset instead of recursing into this one.
No fix.diff build validation possible on this guest (hardware absent) —
`fix_status: not_testable`.

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

(No fix.diff for this item: documented recommendation only - see Fix above.)
