# DF-5489 VERDICT — static, code-certain, NOT executed (Info class)

**Finding:** the VISOR branch of `uvisor_init()` (uvisor.c:380-428) never
validates `actlen` after `usbd_do_request_flags(..., &coninfo,
USB_SHORT_XFER_OK, &actlen, USB_DEFAULT_TIMEOUT)` (uvisor.c:387-389).
That is the raw request entry point — the zeroize-on-error /
zero-pad-on-short protection in `usbd_do_request_proc()`
(usb_request.c:782-787) does not apply — so a short or zero-length (both
legal under SHORT_XFER_OK) vendor response leaves the 18-byte stack
buffer partially uninitialized. The `#ifdef USB_DEBUG` consumer
(uvisor.c:400-426) then reads `UGETW(coninfo.num_ports)` and
`connections[i].port` / `.port_function_id` and prints them (DPRINTF),
disclosing up to ~18 stale kernel-stack bytes to console/msgbuf on a
USB_DEBUG kernel with `hw.usb.uvisor.debug >= 1`.

## Why not executed

- The guest's X86_64_GENERIC kernel is not built with USB_DEBUG, so the
  consumer does not exist in the running kernel.
- No QEMU Visor VID:PID device model exists (`-device usb-serial` is a
  Netchip 0525:7701 that binds uftdi, not uvisor).
- Even with both, the observable is a weak debug-log disclosure of
  number-formatted stack bytes — no memory-safety consequence (the loop
  count is clamped, uvisor.c:401-403; there is no OOB).

## Production impact: none (dead store)

Outside `#ifdef USB_DEBUG`, `coninfo` is never read after the request;
`num_ports` never feeds `ucom_attach()` (uvisor hardwires nports=1,
uvisor.c:341). So this is a hardening/hygiene finding in the exact shape
of the family's DF-5448 (uvscom) / DF-5438 (ulpt) / DF-5455 (umoscom,
where the buffer DID have a consumer → Low) entries. It is filed so the
next refactor that starts consuming connection info (e.g. a multi-port
uvisor like FreeBSD's) does not inherit an unvalidated device buffer.

## Line-accurate confirmation (guest tree == audited tree,
uvisor.c sha256 b742032f…d703844438)

- Request: uvisor.c:382-389 (wLength 18 = sizeof(coninfo) — buffer size
  itself is correct; only completeness is unchecked).
- Missing check: immediately after uvisor.c:391-393's error check; the
  PALM4 branch demonstrates the intended pattern at uvisor.c:447-451
  (`if (actlen < 12)` — which correctly covers the offsets its code
  later reads: 1, 8, 9).
- Uninit consumers (USB_DEBUG only): uvisor.c:400 (`UGETW(coninfo.num_ports)`),
  uvisor.c:407 (`port_function_id`), uvisor.c:424-425 (`port` printed).
- No zeroization: call goes to `usbd_do_request_flags` directly; the
  `_proc` wrapper that would zero-pad (usb_request.c:780-787) is bypassed.

## Fix validation

`fix.diff` adds the missing `actlen < UVISOR_CONNECTION_INFO_SIZE` →
`USB_ERR_INVAL` guard (mirroring uvisor.c:447-451). The patched
production uvisor.c compiled -Werror clean as a kmod on the guest
(fix_compile.log, RC=0). Not runtime-tested (see above) — fix_status
build-validated only.

## Guest hygiene

Guest untouched by this finding's verification (build-only scratch dirs
removed; production uvisor.c md5 unchanged 28d0d390d06dd00f9dbfc03106b453a7).

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