# DF-4579 — radeon (and DF drm core): every failed radeon PCI attach leaks the drm_device — drm_get_pci_dev's error unwind is #if 0'd out

File: `sys/dev/drm/radeon/radeon_drv.c` (884 LOC) — pass 2 (GLM 5.3 re-audit).

## Build/run/expected

Runtime reproduction requires ATI Radeon hardware: the leak fires on the PCI attach
path (`radeon_driver_attach` → `radeon_pci_probe` → `drm_get_pci_dev`) whenever
`radeon_driver_load_kms` fails fatally ("Fatal error during GPU init") or minor
registration fails. The audit guest has no ATI VGA device (virtio-gpu only, see
`env.txt`), so the defect is verified by source trace against the live code path;
there is no runnable trigger on this system.

```sh
# what would trigger it on ATI hardware (or forced):
kldload radeon           # or boot with an ATI card whose init fails
dmesg | grep "Fatal error during GPU init"   # radeon_kms.c:137
# each such failed attach leaks one struct drm_device (drm_dev_alloc) forever
```

## The chain (all path:line verified)

1. `radeon_driver_attach` (radeon_drv.c:812-839) is the live newbus attach entry
   (`DRIVER_MODULE_ORDERED` at :879-880). It calls `radeon_pci_probe` (:834).
2. `radeon_pci_probe` (radeon_drv.c:382-434) calls
   `drm_get_pci_dev(pdev, ent, &kms_driver)` (:433) — **the only live call site of
   `drm_get_pci_dev` in the tree** (the other, drm_pci.c:404, is inside the entirely
   `#if 0`'d `drm_legacy_pci_init`, which also early-returns `-EINVAL` for non-LEGACY
   drivers).
3. `drm_get_pci_dev` (drm_pci.c:309-357) does `dev = drm_dev_alloc(...)` (:318) then
   `ret = drm_dev_register(dev, ent->driver_data)` (:338-340); on failure it jumps to
   `err_agp` — and the entire error block is `#if 0`'d out (drm_pci.c:343-357):
   upstream Linux has `err_free: drm_dev_unref(dev);` there, DragonFly deleted it.
   The function returns `ret` with **`dev` leaked**.
4. `drm_dev_register` (drm_drv.c:877-924) fails whenever:
   - `drm_minor_register` fails (drm_drv.c:884-890), or
   - `driver->load` fails: `radeon_driver_load_kms` returns error after
     "Fatal error during GPU init" (radeon_kms.c:131-138; e.g. failed VRAM/iomap/
     firmware/TTM init — routine with flaky or unsupported ATI hardware).
   Its `err_minors` path (drm_drv.c:915-918) only unregisters the minors — it does
   **not** free `dev` and does not call `driver->unload`.
5. `radeon_driver_load_kms` (radeon_kms.c:95-173) cleans up its own partial state by
   calling `radeon_driver_unload_kms(dev)` on error (:170) — so the leak boundary is
   exactly one `struct drm_device` (plus its embedded mutexes/idr state) per failed
   attach.
6. Back in `radeon_driver_attach`, on `error != 0` the caller correctly frees the
   `pci_dev` mirror via `drm_fini_pdev(&pdev)` (radeon_drv.c:836) — the caller's part
   of the unwind is right; the core's is not.

## Impact

Kernel heap leak (one drm_device allocation per failed attach). Attach happens at
boot on ATI hardware or via `kldload radeon` (root), and can be re-attempted after
each failed probe — a repeated kldload/probe cycle with failing hardware leaks
unboundedly. Not reachable by an unprivileged user. Severity Low.

## Why the guest run cannot reproduce it

`pciconf -l`: only `vgapci0@pci0:0:2:0 card=0x11001af4 chip=0x11111234` (virtio-gpu,
Red Hat vendor 0x1af4) — no ATI 0x1002 device, `/dev/dri` absent, radeon.ko never
loads. QEMU cannot emulate radeon-compatible VGA. Source verification is therefore
the deliverable (VERDICT.md).

## Fix

`fix.diff` restores the upstream error unwind in `drm_get_pci_dev`
(`drm_dev_unref(dev)` on the register-failure path; `drm_dev_unref` exists at
drm_drv.c:789). Authored against the read-only `sys/` tree; not applied.
