# DF-1065 — VERDICT

## Verdict
**SOURCE-CONFIRMED (real bug), NOT REPRODUCED AT RUNTIME on this guest.**
The bug is genuine and traced line-by-line in compiled module source. It does
not fire on this guest because the UVC driver never attaches (no USB camera, no
`/dev/video*`). This is the "needs specific HW" / dormant-code case, **not** a
false positive and **not** dead code (`uvc.ko` ships in `/boot/kernel`).

## Mechanism (source trace)
1. `uvc_buf_queue_mmap_locked` (`sys/bus/u4b/uvc/uvc_buf.c:104-129`) returns
   `*paddr = atop(vtophys((uint8_t *)bq->mem + offset))` (`:126`). DragonFly's
   device pager `old_dev_pager_fault` (`sys/vm/device_pager.c:348-390`) installs
   a `PG_FICTITIOUS`, `wire_count=1` fake page whose `phys_addr` is that paddr
   and never evicts it unless a fresh fault occurs.
2. `uvc_buf_queue_free_bufs_locked` (`uvc_buf.c:517-525`) does
   `kfree(bq->mem); bq->mem = NULL; bq->buf_count = 0;` with **no** tracking or
   revocation of any mmap mapping. `kfree` touches no pmap entry, so the user
   pmap entry `[user_va -> phys page of old bq->mem]` persists.
3. Two trigger paths reach the free while a mapping exists:
   - **REQBUFS re-entry** — `uvc_buf_queue_req_bufs` (`uvc_buf.c:~554`) calls
     `uvc_buf_queue_free_bufs_locked(bq)` on entry; a second `VIDIOC_REQBUFS`
     after an `mmap`+touch frees the in-use buffer.
   - **close path** — `uvc_v4l2.c:428-432`, if `uvc_v4l2_has_pri(priv)`, calls
     `uvc_buf_queue_free_bufs(&v->bq)`; mmap mappings survive `close()`.
4. After the free + slab reuse, the user's mapping references freed/reused
   kernel heap: **read = info disclosure**, **write = corruption**. Secondary
   DoS: if the pmap entry is later invalidated and re-faulted, the now-NULL
   `bq->mem` makes `mmap_locked` return `EINVAL`, `dev_dmmap` returns `-1`, and
   `KASSERT(paddr != -1)` at `device_pager.c:361` panics.
5. Reachability for an unprivileged user: `/dev/videoN` is created mode `0666`
   (`uvc_v4l2.c:784`). The only real precondition is an attached UVC camera
   (so the device node exists) — absent on this guest.

## Why not reproduced here
`kldstat` shows only `kernel`, `ehci.ko`, `xhci.ko`; `uvc.ko` is **not loaded**
and `/dev/video*` **does not exist** (`ls /dev/video*` → "No match"). The trigger
cannot even `open()` a device. The guest has no USB Video Class hardware.

## Fix
`fix.diff` adds a per-queue `mapped` flag (set on the first successful fault in
`mmap_locked`), refuses to `kfree` the buffer while mapped (pinned until device
detach), zeroes the buffer before any free as defense-in-depth, and makes
`req_bufs` return `EBUSY` when an existing buffer is still mapped. This closes
both the read and write UAF. The durable upstream fix is a `vm_object`-backed
lifecycle (mappings hold a reference); this is the minimal security mitigation.
**Supersedes** the finding's proposal (which only zeroed before free — that
kills the info-leak read half but leaves the write-corruption half open).

## Fix validation (compile)
The fix **applies** (`git apply --check` clean) and **compiles**: `uvc.ko` was
rebuilt from patched `/usr/src` with `make KERNCONF=X86_64_GENERIC` under
`-Werror`; `uvc_buf.c` compiled with no errors/warnings and `uvc.ko` linked
(57424 bytes), rc=0. Runtime before/after is **not_testable** (no HW to trigger
the bug on either the baseline or patched kernel).

## Exploit chain (n/a — not a write the guest can drive)
No escalation chain was developed because the primitive is unreachable at
runtime on this guest (no USB camera). On a HW-equipped host the primitive
(freed kernel heap read/write via a surviving mmap) is a classic slab-grooming
UAF; the realistic impact ceiling is local unprivileged → root with grooming.
