# DF-4075 VERDICT — source-level certain, chip-gated (no LSI mps HBA on audit guest)

## Shape (i): NULL-deref panic
- mps_update_events():1719 `error = mps_request_polled(sc, cm)`; :1720-1723 set error when reply is
  NULL / bad status; :1724 then calls `mps_print_event(sc, reply)` UNCONDITIONALLY.
- On a polled timeout (mps_request_polled:2150-2157: 1000 iterations x 50 ms = 50 s with no reply),
  cm->cm_reply is NULL (never assigned; also zeroed by every prior mps_free_command — mpsvar.h:520).
- mps_print_event() (mps_table.c) dereferences `event->EventDataLength` immediately ⇒ NULL deref ⇒
  panic. Reachable at attach (mps_attach_log -> mps_register_events -> mps_update_events) and on
  every event re-registration, whenever the IOC stays silent ~50 s without faulting.

## Shape (ii): timed-out command freed while still posted
- mps_request_polled() returns ETIMEDOUT with the request still posted to the controller
  (no cancellation, no MPS_CM_FLAGS_COMPLETE).
- Callers free immediately: mps_get_portfacts `done:` (:592-594 frees even on error),
  mps_update_events (:1727).
- A late reply then hits mps_intr_locked:1581 `cm = &sc->commands[desc->AddressReply.SMID]`
  (SMID valid — DF-1369 covers invalid SMIDs): the cm is on the free list or REALLOCATED to a new
  request ⇒ spurious MPS_CM_FLAGS_COMPLETE / wakeup for the new owner, cm_reply assigned onto a
  free-list command, and mps_free_command later recycles the stale reply busaddr via
  mps_free_reply (mpsvar.h:518-519) ⇒ reply-frame double-recycle / command-state corruption.

## Distinct from knowns
DF-4014 = mps_user.c ioctl wait path (frees cm + DMA buffer, device DMA writeback).
DF-4015 = ioctl command leak. DF-1369 = SMID bounds. This finding is the mps.c core polled path.

## Fix
NULL-guard the print; on timeout do not free a still-posted command (complete-with-error or defer
reclamation to reinit).

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