# DF-5158 — ata_ati_chipinit AHCI fallback leaves dangling ctlr->r_res2 → double bus_release_resource at detach

File: `sys/dev/disk/nata/chipsets/ata-ati.c` (pass 2, GLM 5.3)

## What

`ata_ati_chipinit()` (ata-ati.c:94-120) has an AHCI fast path for ATI SB6xx/7xx/8xx
parts programmed as AHCI (subclass SATA + progif AHCI 1.0). It calls
`ata_ahci_chipinit(dev)` and treats **ENXIO as "fall back to compat IDE mode and
attach anyway"** (ata-ati.c:113). But `ata_ahci_chipinit()`'s error paths release
`ctlr->r_res2` **without NULLing the pointer**:

- `ata-ahci.c:80-83` BAR(5) alloc failure → r_res2 = NULL (clean), return ENXIO.
- `ata-ahci.c:85-90` interrupt setup failure → releases r_res2, pointer left
  dangling, return ENXIO. (Unreachable via ATI: `ata_setup_interrupt` already
  succeeded at ata-ati.c:99.)
- `ata-ahci.c:94-97` **AHCI controller reset timeout** (`ata_ahci_ctlr_reset`
  returns ENXIO after 1000 ms, ata-ahci.c:135-141) → releases r_res2, pointer
  left dangling, return ENXIO. **Reachable via ATI.**

On the reachable path (reset timeout), `ata_ati_chipinit` falls through to
`ctlr->setmode = ata_ati_setmode; return 0;` (ata-ati.c:118-119) — attach
**succeeds** with a stale, already-freed `ctlr->r_res2` in the softc.

The only later dereference is `ata_pci_detach()` (ata-pci.c:267-269):

```c
if (ctlr->r_res2) {
        bus_release_resource(dev, ctlr->r_type2, ctlr->r_rid2, ctlr->r_res2);
        ctlr->r_res2 = NULL;
}
```

→ **double release of an rman resource that was already freed** → rman list
corruption / use-after-free → kernel panic on detach (kldunload / PCI hot-unplug /
driver re-init).

Secondary defect on the same line: `if (ata_ahci_chipinit(dev) != ENXIO) return 0;`
treats *any* future non-ENXIO error return as success. Today `ata_ahci_chipinit`
returns only {0, ENXIO}, so the live bug is the stale-pointer one.

## Trigger preconditions

1. ATI/AMD SB600/SB700/SB800-family SATA controller (vendor 0x1002, ids
   `ATA_ATI_IXP600_S1/S2`, `IXP700_S1..S4`, `IXP800_S1/S2`) programmed by BIOS
   with subclass `PCIS_STORAGE_SATA` + progif `PCIP_STORAGE_SATA_AHCI_1_0`.
2. `ata_ahci_ctlr_reset()` times out (GHC_HR never clears within 1 s) — i.e. a
   wedged/faulty controller or a pre-reset register state that sticks.
3. Driver detach afterwards (module unload / hot-unplug) — privileged action.

Net: privileged local DoS on flaky hardware; no info leak, no arbitrary write.
Severity **Low** (HW-fault-gated + already-privileged trigger), CWE-459
(incomplete cleanup) shading into CWE-416 at detach.

## Why untested on the guest

The audit QEMU guest has an Intel PIIX3 IDE controller (`atapci0@pci0:0:1:1:
chip=0x70108086`) — no ATI 0x1002 IDE/SATA PCI ID exists on the bus, so
`ata_ati_ident()` (ata-ati.c:66-70) never matches and the code path cannot be
instantiated. Triggering additionally requires an AHCI reset timeout, which is a
hardware fault state, not something QEMU's ich9/piix models produce for an ATI
device class that QEMU does not emulate at all. See `env.txt`.

The code flow itself is statically proven above (attach-success-with-stale-pointer
follows mechanically from the cited lines).

## Fix

`fix.diff` (in this directory) — two hunks:
1. `ata-ahci.c`: NULL `ctlr->r_res2` at both release-on-error sites (root cause;
   fixes every vendored caller of `ata_ahci_chipinit`, not just ATI).
2. `ata-ati.c`: treat only `== 0` as AHCI success so any non-zero error falls
   back to compat mode instead of masquerading as success.

fix_status: `not_testable` — no ATI hardware on the guest (see env.txt); the
diff is line-accurate against the audited tree but could not be boot-validated.

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