# DF-4400 — tws_intr_resp invokes req->cb with no state validation (double completion / NULL cb)

## What
`sys/dev/raid/tws/tws_cam.c:1156-1173`:

```c
while ( tws_get_response(sc, &req_id, &mfa) ) {
    ...
    if ( req_id == TWS_INVALID_REQID ) { ... tws_err_complete(sc, mfa); continue; }
    sc->reqs[req_id].cb(&sc->reqs[req_id]);   /* <-- no bounds, no state check */
}
```

Two distinct defects beyond DF-1590 (which covers the out-of-bounds *index*):

1. **No busy-state validation.** `req->cb` is only initialized when a request is
   allocated (`tws_get_request`, `tws.c:803-814`, which also sets `cb = NULL`) or
   explicitly by the submitter; it is **never cleared on release**. A firmware-fed
   *in-range* `req_id` that is stale (duplicate response for an already-completed
   request, or a response for a FREE slot) invokes the old callback:
   - stale `tws_scsi_complete` (`tws_cam.c:738`) on a completed request →
     `xpt_done(ccb)` a **second time** on a ccb CAM may already have recycled, and
     `callout_stop(req->ccb_ptr->ccb_h.timeout_ch)` on dead ccb memory;
   - if the slot was reallocated, `req->ccb_ptr` is the *new, in-flight* ccb → the
     new transaction is completed early while the firmware still owns it
     (biodone of an in-flight bio — the tws/twa sibling bug DF-4178's signature).
2. **NULL callback call.** `tws_get_param()` deliberately submits with
   `req->cb = NULL` (`tws_cam.c:924`) because it polls for the response
   (`:941-942`). If an interrupt ever delivers that response first,
   `sc->reqs[3].cb(...)` is a **NULL function-pointer call → panic**. (Today this
   is latent: `tws_get_param` runs only at attach with interrupts masked,
   `tws.c:547` / `tws_hdm.c:112-114` — but nothing enforces it.)

## Impact
Device-fed trigger (misbehaving/duplicating firmware — same threat model as
DF-1590): kernel NULL-call panic or CAM use-after-free / double-done list
corruption. The response loop also terminates only when the firmware stops
producing responses (`tws_get_response` false), so a hostile controller can keep
the interrupt handler spinning through arbitrary stale callbacks.

## Trigger
No local trigger — requires the controller to emit a duplicate/stale response.
Documented in VERDICT.md; `trigger.c` is a compile-only stub that documents the
expected response word (16-bit `request_id` bitfield, `tws_hdm.h:348-353`).

## Status
QEMU guest has no 3ware HBA → inconclusive; logic proven from source.
