# DF-5154 — `dpt_pci_attach()` leaks `parent_dmat` on the `dpt_init()` failure path (`dpt_free()` never destroys the glue's DMA tag)

**File:** `sys/dev/raid/dpt/dpt_pci.c:134-156`
**Class:** resource leak on error path (CWE-401)
**Severity:** Info (one-shot, hardware-gated, boot/kldload-time only)
**Distinct from DF-2151** (known, not re-reported): DF-2151 is the wrong-rid
`bus_release_resource`; this is the DMA-tag lifecycle gap. Also distinct from
DF-5153 (the `bus_setup_intr`-failure unwind): that path additionally leaks
`parent_dmat` too, but *this* finding is the one that fires even on the
earlier, otherwise-correct `dpt_init` failure path where `dpt_free` **is**
called.

## The bug

The PCI glue creates the parent DMA tag (dpt_pci.c:134-143):

```c
	if (bus_dma_tag_create(/*parent*/NULL, ..., &dpt->parent_dmat) != 0) {
		dpt_free(dpt);
		error = ENXIO;
		goto bad;
	}
	...
	if (dpt_init(dpt) != 0) {          /* dpt_pci.c:151 */
		dpt_free(dpt);             /* <-- frees children only */
		error = ENXIO;
		crit_exit();
		goto bad;
	}
```

`dpt_free` (dpt_scsi.c:1172-1204) unwinds exactly the objects `dpt_init`
created, stepping `init_level` 5→0: `dccb_dmamap` unload/free/destroy,
`dccb_dmat`, `buffer_dmat`, the sg-map list and `sg_dmat`. It never touches
`parent_dmat` — the tag the **glue** created before `dpt_init` ran. `rg
parent_dmat sys/dev/raid/dpt/` shows the full picture: created once
(dpt_pci.c:143), consumed as the parent of the three child tags
(dpt_scsi.c:1235/1356/1370), **destroyed nowhere**. On the `dpt_init`
failure path the tag (and its reference on the bus DMA machinery) leaks
permanently. The success path never destroys it either — but there the
driver intentionally keeps it for the device lifetime (there is no detach
method at all), so only the error path is a defect.

## Impact

Bounded: one `bus_dma_tag_t` + policy copy leaked per failed attach of a DPT
0x1044:0xa400 controller. Requires the real HBA present and `dpt_init`
failing (board config handshake failure, DMA tag creation failure inside
dpt_init, CCB allocation failure). No unprivileged trigger; no memory-safety
consequence; correctness/hygiene only. Filed as hardening completeness so
the family's teardown story is whole (mlx/ips/ida/amr/mfi siblings each got
their unwind findings this pass).

## Fix

`fix.diff`: destroy `parent_dmat` after `dpt_free(dpt)` on the
`dpt_init`-failure path (child tags are destroyed by `dpt_free`, so the
parent destroy afterwards is legal). DF-5153's fix performs the same
destroy on the later `bus_setup_intr`-failure path.
