# DF-4983 VERDICT — cxm_iic_detach() can never invalidate cxm_softc.iicbus

**Status: untested at runtime (hardware-gated). Defect certain from source.**

## Proof (no runtime needed)

`cxm_iic_detach()` — sys/dev/video/cxm/cxm_i2c.c:220-246 — line 229:

```c
BUS_WRITE_IVAR(device_get_parent(dev), dev, CXM_IVAR_IICBUS, 0);
```
return value ignored.

`cxm_write_ivar()` — sys/dev/video/cxm/cxm.c:2100-2126 — lines 2115-2118:

```c
case CXM_IVAR_IICBUS:
        if (sc->iicbus)              /* (a) */
                return EINVAL;       /* (b) */
        sc->iicbus = val ? *(device_t *)val : NULL;   /* unreachable for val==0 */
```

- `cxm_iic_attach()` (cxm_i2c.c:189-194) is the ONLY writer of this ivar;
  it runs before `cxm_iic_detach()` can ever run (a device whose attach
  failed is never detached in the DF newbus).
- Therefore at (a) `sc->iicbus != NULL` is ALWAYS true when called from
  `cxm_iic_detach` → (b) always returns EINVAL → the NULL store is
  unreachable → `sc->iicbus` survives `cxm_iic_detach` pointing at the
  iicbus device_t that `device_delete_child(dev, child)` then destroys
  (cxm_i2c.c:240-243).
- Contrast with the sibling pointer `sc->cxm_iic`, which IS correctly
  nulled via `bus_child_detached` (cxm.c:2060-2068) and is used as the
  guard at cxm.c:622 — the asymmetry confirms intent vs. effect.

Consequence: `sc->iicbus` is a stale `device_t` after iic teardown. Every
sensor sub-driver dereferences it (27 uses in cxm_saa7115.c alone, e.g.
cxm_saa7115.c:678 `cxm_saa7115_reset(sc->iicbus, ...)` →
`iicbus_start(iicbus, ...)` at cxm_saa7115.c:574; cxm_msp34xxx.c:295+;
cxm_tuner.c; cxm_eeprom.c).

## Reachability

- Non-racy internal paths currently never deref after invalidation:
  cxm's own attach-fail and detach orders put iic teardown last / guard
  with `sc->cxm_iic` (cxm.c:622, 1923-1929, 1966-1973). Checked both
  orders — clean.
- Racy path: an in-flight `/dev/cxm0` ioctl touching a sensor while
  `kldunload cxm` runs `cxm_detach` → `cxm_iic_detach` (no-op clear) →
  iicbus freed → `iicbus_start(freed)` UAF. The *serialization hole* is
  the known DF-4753/DF-4419 family; the present finding contributes the
  second, permanently-unrecoverable stale object from the i2c glue file.
- Hardware gate: cxm_iic attaches only under a probed cxm device
  (Conexant iTVC15/16; Hauppauge PVR-250/350). Guest has none (verified
  in the same session as DF-4982's env.txt: cxm.ko resident, /dev/cxm
  never created). No local trigger exists to synthesize the
  parent-child attach without the card.

## Severity rationale

Low: exploitation requires (1) the rare capture card, (2) a concurrent
root kldunload against an unprivileged user's ioctl — the user-visible
step of the known family race — and (3) winning the race window. The
defect itself (dead invalidation hook) is certain; impact rides the
already-filed race. Filed as a distinct pass-2 finding because it lives
in cxm_i2c.c's own code (line 229) and because the fix is local and
cheap.

## Fix validation

Not applicable — no baseline reproducible on the guest (no card).
`fix.diff` (cxm.c write_ivar 0-case clear) makes line 229 actually
invalidate; set-once semantics for non-zero preserved.

## Bottom line

One-line dead-cleanup bug, certain from source, arms the known cxm
detach race with a second freed object; fix is a 5-line ivar semantics
change.

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