# DF-5002 VERDICT — UNTESTED dynamically; defect certain by inspection

**Bottom line:** the two ivars allocations in mii.c
(`mii_attach_args` per PHY child at mii.c:157-161, `mii_probe_args` for
the bus at mii.c:263-267) have no corresponding free anywhere in the
kernel — newbus never frees ivars (`device_delete_child`,
sys/kern/subr_bus.c:1284-1310, drops the pointer; only ever set to NULL
at device creation, subr_bus.c:1216). Every failed `mii_probe()` leaks
one `mii_probe_args` immediately (mii.c:274-278; bge retries the probe
up to 5× per attach, if_bge.c:2582-2589), and every miibus destroy (NIC
detach — module unload or CardBus/USB hot-removal; if_rue USB NICs use
miibus) leaks the bus args plus one child args per PHY (~104-152 bytes
per cycle).

## Why untested (and why that is honest)

- The QEMU guest has no miibus-attached NIC (its NICs don't use miibus),
  so neither leak path can be driven dynamically on this guest. Creating
  a synthetic miibus would require a custom fake NIC driver whose
  miibus_readreg/writereg emulate a PHY — that exercises my test scaffold,
  not the shipping code, so the static proof plus the compile-checked fix
  is the stronger evidence.
- Static proof: (a) allocation sites mii.c:157-161 / mii.c:263-267
  (M_DEVBUF, M_WAITOK); (b) `rg 'kfree' sys/dev/netif/mii_layer/` yields
  only tlphy.c:183 / mlphy.c:218,426 (`devlist`, M_TEMP — unrelated);
  (c) newbus ivars semantics: subr_bus.c:1216 (init NULL),
  1284-1310 (delete frees device struct only), 1809-1820
  (get/set ivars — plain pointer ops); (d) NIC detach paths all delete
  the miibus child (if_bge.c:2727, if_nfe.c:678, if_xl.c:1581, if_vr.c:831,
  if_vge.c:1086, ...), confirming the free-in-`miibus_detach` placement is
  reached on every destroy.

## Impact ceiling

Slow, bounded kernel-heap exhaustion (CWE-401). The leaked blocks are
never referenced again (no UAF composition). Realistic amplifiers:
bge 5×-retry on PHY-less cards at every attach; USB dongle
replug cycles (physical access) on if_rue. No C/I impact; severity Low.

## Fix

`fix.diff` (applies cleanly; compiles under -Werror as a KLD source on
the guest — fixcheck-build.log):
- `miibus_detach()`: free each child's `mii_attach_args` (children still
  enumerated there), then the bus's own `mii_probe_args`; NULL the ivars
  pointers via `device_set_ivars()` after each free.
- `mii_probe()` ENXIO path: free `args` before `device_delete_child()`.

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