# VERDICT — DF-5316

**Status: REPRODUCED** (unprivileged local user, fresh boot) — impact
`dos`/policy-bypass: an unprivileged user holding an FWRITE ugen
control-node fd can change the USB device configuration (unconfigure,
reconfigure, force driver detach/re-attach + re-enumeration) although
the very same operation via the raw control-request path
(`USB_REQUEST` with `UR_SET_CONFIG`) is privilege-gated in the same
file.

## Root cause

`ugen_check_request()` gates raw `UR_SET_ADDRESS` / `UR_SET_CONFIG` /
`UR_SET_INTERFACE` control requests behind
`caps_priv_check_self(SYSCAP_NODRIVER)` (sys/bus/u4b/usb_generic.c:874-887,
the comment even says *"These requests can be useful for testing USB
drivers"*), and `ugen_re_enumerate()` (USB_DEVICEENUMERATE) is gated the
same way (:952).  But the ioctl shortcuts:

* `USB_SET_CONFIG` → `ugen_set_config()` (usb_generic.c:2096-2102 → :605-625)
* `USB_SET_ALTINTERFACE` → `ugen_set_interface()` (:2114-2121 → :628-652)

perform the equivalent (stronger, even: they kick the explore thread to
re-enumerate, re-probe and re-attach drivers via
`usbd_start_set_config` / `usbd_set_alt_interface_index` +
`usb_probe_and_attach`) with **no privilege check at all** — only
`FWRITE` on the fd (:2097, :2115).

## Reproduction (`run.log`)

Unprivileged maxx (uid 1001) on `/dev/usb/0.2.0`:

1. `USB_REQUEST(SET_CONFIGURATION)` → **EPERM** (gate works);
2. `USB_SET_CONFIG(255 = USB_UNCONFIG_INDEX)` → **0**, and
   `USB_GET_CONFIG` then reports `curr_config_index = 255`: the device
   was genuinely unconfigured (driver detach cycle) by uid 1001;
3. `USB_SET_CONFIG(0)` → **0**, device reconfigured back.

Impact ceiling: unprivileged device reconfiguration/driver-rebinding
(DoS on other users' or the system's USB devices — e.g. dropping a
umass mid-I/O by unconfiguring it, or re-claiming interfaces), plus the
 inconsistency itself (one more way for an unprivileged process to
 disturb devices the SYSCAP gate was written to protect).  Not a memory
 corruption; severity Medium (matches "requires unusual
 config/privilege... local DoS" only partially — it needs just the
 standard libusb-access device permissions, hence Medium not Low).

## Fix validation (`run.patched.log`, `fix.diff`)

Two-line gate added to both functions (mirroring the
`ugen_re_enumerate` pattern).  Patched kernel: `USB_SET_CONFIG(255)`
and `USB_SET_ALTINTERFACE` both return **EPERM** for uid 1001 and the
device stays configured (`curr_config_index = 0`); the raw-request path
is unchanged.  No functional regression for privileged callers (root
still passes `SYSCAP_NODRIVER`).

## Kernel references

- sys/bus/u4b/usb_generic.c:874-887 (raw-request gate)
- sys/bus/u4b/usb_generic.c:952 (re-enumerate gate)
- sys/bus/u4b/usb_generic.c:605-625 (ugen_set_config, no gate)
- sys/bus/u4b/usb_generic.c:628-652 (ugen_set_interface, no gate)
- sys/bus/u4b/usb_generic.c:2096-2102, :2114-2121 (ungated dispatch)

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