# DF-5014 — mps attach unwind: sc->facts leak and parent DMA tag destroyed over live children

## What
The unwind contract between `mps_pci_attach()` (sys/dev/raid/mps/mps_pci.c:234-237)
and `mps_attach()` (sys/dev/raid/mps/mps.c:1024-1215) is broken on two families
of early-failure paths — beyond the known DF-2044 (never-allocated IRQ release,
not re-reported here):

1. **`sc->facts` leaked** — `mps_attach()` returns error *without* calling
   `mps_free()` at:
   - mps.c:1043-1044 (`mps_get_iocfacts` fails: IOC wedged / not answering),
   - mps.c:1072-1073 (`mps_transition_ready` fails after the diag reset
     forced by missing EVENT_REPLAY capability).
   The `kmalloc(sizeof(MPI2_IOC_FACTS_REPLY))` from mps.c:1041-1042 is never
   freed; `mps_pci_free()` does not know about it.

2. **parent DMA tag destroyed over live child tags** — whenever `mps_free()`
   bails out early (mps.c:1323-1325 `mps_detach_sas`/`mps_detach_log` error,
   mps.c:1331-1334 `mps_transition_ready` error — realistic exactly when the
   IOC is wedged, e.g. after mps.c:1128-1133 transition-operational failure),
   the queue/request/reply/sense/chain/buffer DMA tags and their memory stay
   allocated while control returns to `mps_pci_attach()`, whose
   `mps_pci_free()` then destroys `mps_parent_dmat` (mps_pci.c:289-291).
   `bus_dma_tag_destroy()` (sys/platform/pc64/x86_64/busdma_machdep.c:334-346)
   keeps **no parent↔child reference count**: the parent tag memory is freed
   silently, leaving every child tag with a dangling `dmat->parent` pointer
   (latent UAF of the tag object) and leaking all queue DMA memory
   (`map_count` on the parent is 0, so the EBUSY guard never fires).

Both fire only at boot/hotplug on failing hardware (wedged or absent IOC
mid-attach) — resource-leak / latent-dangling-pointer class, no attacker-
controlled input. Same family context: DF-2044 (known), DF-4868/4869, DF-4363.

## Reproduction status
HW-gated: no LSI SAS2008-class controller on the audit guest, mps cannot
attach; both defect paths are unconditional control flow (cited above), no
runtime PoC possible on this guest.

## Fix
`fix.diff`: free `sc->facts` (and NULL it) on the two early-error returns in
`mps_attach()`. DF-2044's NULL-guard for the IRQ teardown in `mps_pci_free()`
should ride along in the same commit (not duplicated here to keep this diff
scoped to the new finding).
