# DF-5153 — `dpt_pci_attach()` bus_setup_intr failure leaves XPT-registered SIMs, CAM paths, shutdown handler and softc live against released io/irq

**File:** `sys/dev/raid/dpt/dpt_pci.c:163-179` (trigger), `:159` (setup)
**Class:** incomplete error-path unwind → logical UAF of bus resources +
permanent leak + unkillable CAM I/O (CWE-459 Incomplete Cleanup)
**Severity:** Low (hardware-gated: needs a DPT 0x1044:0xa400 HBA *and* an
interrupt-registration failure at attach)
**Distinct from DF-2151** (known, not re-reported): DF-2151 is the wrong-rid
`bus_release_resource` on the `bad:` path. This finding is everything *else*
that path fails to unwind — the CAM/XPT lifetime, the shutdown handler, the
DMA machinery and the softc. (Note the IRQ release at dpt_pci.c:176-177 uses
rid 0, which *is* the rid the IRQ was allocated with at :103-105 — correct;
only the io rid is wrong, and that half is DF-2151.)

## The bug

`dpt_pci_attach` reaches `bus_setup_intr` only after the controller is fully
brought online:

```c
	crit_enter();
	if (dpt_init(dpt) != 0) { ... }          /* DMA tags, CCB array, sg maps */
	/* Register with the XPT */
	dpt_attach(dpt);                          /* dpt_pci.c:159 */
	crit_exit();

	error = bus_setup_intr(dev, irq, 0, dpt_intr, dpt, &ih, NULL);
	if (error) {
		device_printf(dev, "Unable to register interrupt handler\n");
		error = ENXIO;
		goto bad;                          /* dpt_pci.c:168 */
	}
	...
bad:
	if (io)
		bus_release_resource(dev, iotype, 0, io);   /* wrong rid = DF-2151 */
	if (irq)
		bus_release_resource(dev, SYS_RES_IRQ, 0, irq);  /* correct rid */
	return (error);
```

By the time `bus_setup_intr` runs, `dpt_attach` (dpt_scsi.c:1450-1490) has:

* `cam_sim_alloc`'d up to `MAX_CHANNELS` SIMs sharing one devq and
  `xpt_bus_register`'d each (dpt_scsi.c:1466-1473),
* `xpt_create_path`'d wildcard paths for each (dpt_scsi.c:1475-1482),
* released the shared devq (dpt_scsi.c:1485),
* `EVENTHANDLER_REGISTER`'d `shutdown_post_sync → dptshutdown`, discarding
  the tag (dpt_scsi.c:1487-1488),

and `dpt_alloc` (dpt_scsi.c:1153-1169) has TAILQ-link'd the softc onto the
global `dpt_softcs` list (:1165). None of this is undone on the failure
path: `bad:` touches only `io`/`irq`; `dpt_free` is never called; no bus is
deregistered; no sim/path freed; the shutdown handler stays registered; the
softc stays on `dpt_softcs`; the DMA'able CCB array, sg maps and three DMA
tags stay allocated forever.

## Consequences (why it is not merely cosmetic)

1. **Phantom SIM in CAM.** `xpt_bus_register` is global state independent of
   newbus attach status. After the failed attach the bus/sim/paths remain
   fully resolvable; CAM's own boot-time scan (and anything else that
   compiles a path to that bus) reaches `dpt_action` → `dptexecuteccb`,
   which pokes `dpt_outb()` through `dpt->tag/bsh` — a bus_space handle to
   an rman record that was just released (or, with DF-2151's wrong-rid
   no-op, leaked). Cross-device register corruption on x86 PIO; MMIO
   variant touches the re-mapped page owner.
2. **Unkillable I/O.** No interrupt handler was installed, so nothing the
   HBA completes is ever reaped — every command routed to the phantom bus
   hangs in CAM forever (boot-time wedging of the SCSI scan path).
3. **Shutdown-time use of released state.** `dptshutdown`
   (dpt_scsi.c:1717-1733) still fires on every reboot and issues
   `dpt_send_immediate` through the released/leaked register window.
4. **Permanent leak** of the CCB DMA memory, sg maps, three child DMA tags,
   io (via the DF-2151 no-op) — and see DF-5154 for `parent_dmat`, which is
   additionally never destroyed even where `dpt_free` *is* called.

No kernel-heap corruption primitive is in scope here (bus-space logical UAF
plus leak), and the trigger is hardware/boot-time — there is **no
unprivileged trigger and no uid=0 route**; the class does not permit one.

## Reproduction status

`untested` — hardware-gated. Verified on the audit guest
(`pciconf -l` → no vendor 0x1044 device; see `env.txt`): the entry path
cannot fire there, and the defect is not driveable by any userland program
(absent the card). Line-level proof of the unwind gap is in VERDICT.md.
Family precedent: DF-5115 (ips, same shape) was filed `untested` for the
same reason; DF-5141 (mlx) was reproduced only because its primitive was a
genuine double-kfree driveable by a KLD harness — this one has no such
primitive to harness.

## Fix

See `fix.diff`: full reverse-order teardown on the `bus_setup_intr` failure
path (free paths → deregister buses → free sims → deregister the shutdown
handler (tag now stored in the softc) → `dpt_free` → destroy `parent_dmat`),
plus the correct io rid in `bad:` (that hunk overlaps DF-2151's fix and is
included only because the unwind is meaningless while the release is a
no-op).
