# VERDICT — DF-4977

**Status: untested** (restricted enum; the natural-language classification is
"not testable on this guest: no CardBus hardware"). **Reproduced: 0.**

## What the defect is (certain, by code reading)

`cardbus_detach_card()` at `sys/dev/pccard/cardbus/cardbus.c:236-247`:

1. `device_detach(devlist[tmp])` (line 243) — return value **ignored**.
2. `cardbus_release_all_resources(cbdev, dinfo)` (line 244) — releases every resource
   the (possibly still-attached) child driver holds and zeroes its BARs
   (`cardbus.c:300-311`; `rle->res = NULL` at :304, `pci_write_config(..., 0, 4)` at :309).
3. `device_delete_child(cbdev, devlist[tmp])` (line 245) — return value **ignored**.
   DragonFly semantics: `device_delete_child` calls `device_detach(child)` again and
   **returns the error without removing the child** when detach fails
   (`sys/kern/subr_bus.c:1284-1293`):
   ```c
   1292		if ((error = device_detach(child)) != 0)
   1293			return(error);
   ```
   i.e. on a busy child the device stays in `cbdev`'s child list with
   `child->ivars == dinfo` intact.
4. `pci_freecfg((struct pci_devinfo *)dinfo)` (line 246) — unconditional
   `kfree(dinfo, M_DEVBUF)` (`sys/bus/pci/pci.c:2139-2156`).

Net effect when a child's detach fails (EBUSY from an open device / IFF_UP NIC):

* **Use-after-free of `dinfo`**: the surviving child's ivars point at freed memory.
  Next dereference: `cardbus_driver_added` on any later driver kldload
  (`cardbus.c:281-287`: `dinfo = device_get_ivars(dev)`, `pci_print_verbose(&dinfo->pci)`,
  `pci_cfg_restore(dinfo->pci.cfg.dev, &dinfo->pci)`), or any bus method
  (read_ivar/write_ivar/resource ops) on the surviving child. The freed
  `cardbus_devinfo` (~0x200+ bytes, M_DEVBUF zone) is attacker-reclaimable via the
  usual slab grooming if the attacker can drive kernel allocations between the free
  and the reuse — on a machine with the hardware this is a plausible privilege-
  escalation primitive (ivars confusion / config-space restore of a forged
  pcicfgregs), but that chain was **not** developed here because the primitive could
  not even be triggered on the audit guest (no hardware).
* **Resource lifetime violation**: the still-running child driver keeps
  `struct resource *` pointers whose bus space was released at step 2 and whose BARs
  were zeroed — the windows can be re-allocated to another device while the old
  driver keeps doing `bus_space_write` to them → cross-device MMIO aliasing
  (hardware-level memory corruption, device-dependent).

## Trigger requirements (why untested)

* A `cbb` (CardBus bridge) controller with a card inserted — **the audit QEMU guest
  has none** (`env.txt`: `pciconf -l` lists only i440FX/virtio; `kldstat -v` shows the
  cardbus drivers compiled in but idle). QEMU's default machine cannot surface a
  `cbb` device, and DF has no userland way to synthesize a PCI bridge.
* A child driver whose `device_detach` returns non-zero while attached (busy device).
  Candidates in this kernel: `cardbus/if_re`, `cardbus/if_dc`, `cardbus/if_fxp`
  (detach commonly EBUSY while interface up / bpf attached), `pccard/sio` (open tty).
* The card event itself: physical eject, re-insert of another card
  (`cardbus_attach_card` at :168 calls `cardbus_detach_card` first), or
  suspend (`cardbus_suspend` at :121-126). Root can reach the same path via
  `kldunload`-style driver detach, but then it is already privileged.

Severity is filed as **Low** per the audit rubric ("requires specific hardware"),
though the defect class is memcorrupt (UAF + resource lifetime) and would rate
higher on hardware that exposes it.

## Honest classification mapping

* Guest reachable but the target device/feature is absent → per the restricted enum
  for this run the status is recorded as **`untested`** (impact `none`, no dynamic
  evidence). Attempts: 0 (nothing executable without the hardware; the "PoC" is the
  trigger analysis in `README.md` + `trigger.md`).

## Fix validation

Not possible on this guest (same hardware gate); `fix.diff` is authored against the
read-only `sys/` tree from line-accurate reading, never applied there.
`fix_status: not_testable`.

## Key citations

* sys/dev/pccard/cardbus/cardbus.c:236-247 (ignored detach/delete errors + free)
* sys/dev/pccard/cardbus/cardbus.c:300-313 (release_all_resources over live driver)
* sys/dev/pccard/cardbus/cardbus.c:121-126, :168 (suspend / re-insert callers)
* sys/dev/pccard/cardbus/cardbus.c:277-290 (driver_added UAF consumer)
* sys/kern/subr_bus.c:1284-1310 (device_delete_child returns error, keeps child)
* sys/bus/pci/pci.c:2139-2156 (pci_freecfg → kfree(dinfo))

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