# DF-4343 — mn_attach error-path asymmetry: unreleasable/leaked BARs, success-returned failures, dangling sc->node, no detach

- **File:** `sys/dev/netif/mn/if_mn.c`
- **Lines:** 1301-1317 (BAR allocs; `struct resource *res` local-only), 1324-1335 (leaking ENXIO returns), 1353-1355 (mn_reset failure returns success), 1386-1389 (ng_make_node_common failure returns success), 1392-1396 (name-failure frees node, softc keeps dangling pointer, returns success), 1402-1411 (no device_detach)
- **Severity:** Low (privileged attach-time/hardware-error paths; resource-exhaustion and dangling-pointer hygiene, no direct unprivileged trigger)
- **CVSS:** `CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:U/C:N/I:L/A:L`
- **CWE:** CWE-772 (protected resource not freed) / CWE-404 (improper shutdown) / CWE-252 (unchecked return)
- **Confidence:** certain (plain code reading)

## Summary

`mn_attach` violates attach error-path symmetry in five distinct ways:

1. **BAR `struct resource *` handles are discarded.** Both memory BAR
   allocations use a local `res` (`if_mn.c:1302`, `:1311`); only
   `rman_get_virtual()`/`rman_get_start()` are saved into the softc
   (`:1307-1308`, `:1316-1317`). The resource handles themselves are never
   stored, so they can never be `bus_release_resource`'d — on the success
   path they are held forever, and on every error return below they leak.

2. **Each early ENXIO leaks everything allocated before it:** second-BAR
   failure leaks BAR0 (`:1311-1315`); IRQ-alloc failure leaks both BARs
   (`:1324-1327`); `bus_setup_intr` failure leaks both BARs plus the IRQ
   (`:1332-1335`). Failed attaches can be repeated (rescan, slot churn) and
   accumulate leaked bus resources.

3. **Failure returned as success.** When the controller fails the PCI
   bus-master test, `mn_reset` returns 0 and attach does
   `if (!u) return (0);` (`:1353-1355`) — the device reports attach SUCCESS
   while non-functional, with the interrupt live and no netgraph node.
   Likewise `ng_make_node_common` failure prints and `return (0)`
   (`:1386-1389`).

4. **Name-failure path frees the node but leaves `sc->node` dangling**
   (`:1392-1396`): `ng_rmnode` + `ng_unref` drop the creation reference
   (node refs → 0 → kfree) — note `ngmn_shutdown` is a no-op returning
   EINVAL (`if_mn.c:280-285`) so `ng_cutlinks` never runs — and the softc
   (still referenced by `device_set_softc`, interrupts live) keeps pointing
   at freed memory forever. Returns success (0) on top.

5. **No `device_detach` method at all** (`:1402-1411`): IRQ teardown,
   resource release, softc free and netgraph node removal are impossible;
   hot-unplug or module unload leaks the softc, both BARs, the IRQ and the
   node.

## Threat

Attacker relevance is indirect: repeated failed attaches (card mis-seated /
bus-master-disabled slot / IRQ exhaustion) leak kernel bus resources
(CWE-772), and the dangling `sc->node` (item 4) is a latent UAF pointer that
future code paths touching `sc->node` would dereference. Requires the mn
hardware and privileged (re)scan operations — hence Low.

## Exploit / PoC

No runnable PoC beyond source inspection is possible on the audit guest
(no card, driver not built — see run.log / env_guest.txt). Deterministic
source-level demonstration: `grep -n "bus_release_resource" if_mn.c` → no
matches; `grep -n "device_detach" if_mn.c` → no matches; the five code
sites cited above.

## Recommended fix

Retain both BAR handles in the softc and release them (plus the IRQ) on
every error path; return `ENXIO` on `mn_reset`/`ng_make_node_common`
failure; on name failure set `sc->node = NULL` after destroying the node and
return `ENXIO`; add a `device_detach` implementing the inverse of attach.
See fix.diff for the minimal resource/return-value half (full detach
requires lifecycle work out of scope for a minimal patch).
