# DF-5643 VERDICT — smbus_detach ignores sc->owner: softc freed under owner and parked waiters (trap + post-free write)

**Status: REPRODUCED, fix validated.** Impact: panic (Fatal trap 12) +
post-free read/write on M_BUS (demonstrated), root-gated detach trigger.

## What was proven, on what code

Same rig as DF-5642 (see that pack). `struct smbus_softc.owner`
(`smbus.h:34`) is the exclusion state `smbus_request_bus` maintains
(`smbconf.c:126-141`); `smbus_detach` (`smbus.c:105-115`) never reads it,
so `device_detach(smbus0)` succeeds under a verifiable owner, and
`device_detach` → `device_set_driver(dev, NULL)` (`subr_bus.c:2150`) →
`kfree(dev->softc)` (`subr_bus.c:1941-1946`) frees the softc underneath:

**RUN B (baseline, `run_b.log` + `panic.txt`)** — the owner's release is
the exact `smbioctl` exit path (`smb.c:356`):

```
[df5642] GRAB: request(fakesmbb0, DONTWAIT)=0 owner=0xfffff8011745d1e0
[df5642] VETO: pre-detach owner=0xfffff8011745d1e0 (must be non-NULL)
[df5642] VETO: device_detach(smbus0)=0 <<< BUS DETACHED UNDER ITS OWNER
[df5642] VETO: post-detach softc=0 (NULL = freed under the owner)
[df5642] RELFREE: calling smbus_release_bus(smbus0, fakesmbb0) with softc=0
Fatal trap 12: page fault while in kernel mode
fault virtual address = 0x0
Stopped at smbus_release_bus+0x78: cmpq %r13,(%r12)     (sc->owner == dev; sc = NULL; smbconf.c:166)
```

**RUN C (baseline, `run_c.log`)** — parked waiter (`tsleep(sc)`,
`smbconf.c:93`; ps shows `df5642_park` on `smbreq`):

```
[df5642] PARK-T: calling request(nexus0, WAIT|NOINTR) softc=0xfffff8008d560cc8
[df5642] VETO: device_detach(smbus0)=0 <<< ... post-detach softc=0
[df5642] WAKUAF: wakeup(freed sc=0xfffff8008d560cc8)
[df5642] PARK-T: request RETURNED 0 (post-free resume)
```

The waiter resumed INSIDE `smbus_request_bus` on freed memory: read
`sc->owner` (`smbconf.c:128`) from the freed block, took the grant
branch, **wrote its device_t into the freed block** (`smbconf.c:134`),
and returned SUCCESS — an 8-byte pointer write into freed M_BUS heap.
In production the stray wake is deliverable by any other client's
release: `smbus_release_bus` broadcasts `wakeup(sc)` unconditionally
(`smbconf.c:177`), and the reallocated softc sits at the same address
the parked waiter holds. Nothing in `smbus_detach` wakes or drains
parked requesters (they also park unkillably per DF-5638's shape).

## Fix validation (`fix.diff` shared with DF-5642, `run_b_fixed.log`,
## `run_c_fixed.log`)

`smbus_detach` now returns EBUSY while `sc->owner != NULL`:

```
[df5642] VETO: device_detach(smbus0)=16 (vetoed: GOOD)
[df5642] VETO: post-detach softc=0xfffff8008d382380   (intact)
[df5642] RELFREE: returned 0                            (no trap)
```

and on the parked-waiter choreography (`run_c_fixed.log`): the waiter
parks on the LIVE softc (same address before/after the vetoed detach),
the owner releases cleanly, the waiter is granted properly (error=0 on
the live softc). Baseline trap and post-free write eliminated.

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