# DF-5306 VERDICT

**Status: reproduced** (kernel panic / local DoS from crafted USB
descriptors at attach), **impact: panic**, confidence: certain.

## Root cause (path:line)

- `sys/bus/u4b/uvc/uvc_drv.c:2109` —
  `vsnum = hdesc->bLength >= 12 ? hdesc->bIfaceNums : 0;`
  A VC header with `bIfaceNums == 0` (or `bLength < 12`, or a control
  interface with no VC header descriptor at all) yields `vsnum = 0`.
- `sys/bus/u4b/uvc/uvc_drv.c:2112-2116` — the sanity check only warns
  (`DPRINTF`) and clamps `vsnum > 1` down to 1; **`vsnum == 0` is
  accepted**, the streaming-interface loop (2122-2145) never runs,
  `sc->data` stays NULL, and `uvc_drv_parse_standard_ctrl()` returns 0.
- `sys/bus/u4b/uvc/uvc_drv.c:2723-2731` — `uvc_drv_attach()` ignores
  the possibility and calls `uvc_drv_init_video(sc, sc->ctrl, sc->data)`
  with `sc->data == NULL`.
- `sys/bus/u4b/uvc/uvc_drv.c:1513` — `if (data->num_altsetting > 1)`:
  NULL dereference -> kernel panic.  (`uvc_drv_init_cur_fmt_frm()`
  validates its arguments at 1451; `uvc_drv_init_video()` does not.)

## Reproduction

Harness (`uvcharness.ko`, same KLD as DF-5305: real driver sources
compiled in) builds a blob identical to DF-5305's except
`bIfaceNums = 0`, runs the real `uvc_drv_parse_ctrl()`
(`ret=0, sc.data=0` — the exact attach-time state), then calls the real
`uvc_drv_init_video(sc, ctrl, NULL)`:

    Fatal trap 12: page fault while in kernel mode
    fault virtual address = 0xa            <- data->num_altsetting at NULL+10
    Stopped at sysctl_harness+0x30b: cmpb $0x1,0xa(%r9)

Guest died (`db>`), `vm.sh status` = down — full transcript in
`panic.txt`.  This is the real code path a crafted device hits at
attach: probe matches the VC interface, parse "succeeds", init_video
panics.

## Fix validation

`fix.diff` adds two layers:
1. `uvc_drv_parse_standard_ctrl()`: reject `vsnum < 1` or
   `bLength < 12 + vsnum` with EINVAL (also fixes the DF-5307(c)
   1-byte `bIfaceList[0]` over-read at `bLength == 12`);
2. `uvc_drv_attach()`: treat `sc->data == NULL` after parse as EINVAL;
3. defense in depth: `uvc_drv_init_video()` returns NULL for
   `data == NULL` before the dereference.

Applied to the guest's `/usr/src`, harness rebuilt, same trigger:
`parse_ctrl ret=22` (EINVAL) and `init_video returned 0 (no panic)`;
`uptime` confirms the guest stayed up (`fix.log`).

## Impact

Denial of service (kernel panic) at USB device attach.  Requires the
attacker model of this audit (crafted USB device / QEMU-emulatable
redirection); NULL-page deref is not a write primitive, so no
escalation path.

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