# VERDICT — DF-5122

**status: untested** (runtime verification not possible: guest has no DRM hardware)
**reproduced: false · impact: none · confidence: certain (static proof)**

## Narrative

This is a *static, structural* finding: `drm_mmap()` in
`sys/dev/drm/drm_vm.c:44-139` is dead code on every stock DragonFly system,
and it carries three latent defects that would be memory-safety-relevant if
the path were ever re-enabled.

### Step 1 — who calls `drm_mmap`, and with what offset?

`drm_mmap` is wired only as the cdevsw `.d_mmap` hook (`drm_drv.c:1154`).
On DragonFly, `d_mmap` is invoked exclusively through the *old device
pager*:

* `old_dev_pager_ctor` (`sys/vm/device_pager.c:329-332`) — at `mmap()` time,
  walks **every page offset** of the requested mapping (`foff`,
  `foff+PAGE_SIZE`, …) and requires each `dev_dmmap()` call to succeed;
* `old_dev_pager_fault` (`device_pager.c:360`) — at fault time, per page.

But the old device pager is only used for a cdev when
`vm_mmap()`'s `d_mmap_single` dispatch returns ENODEV
(`sys/vm/vm_mmap.c:1372-1386`). `drm_mmap_single` (`drm_drv.c:1256-1274`)
returns ENODEV only for a driver with neither TTM (`drm_ttm_bdev`) nor
`DRIVER_GEM`. All shipped drivers satisfy one of the two:

| driver | evidence |
|---|---|
| i915 | `DRIVER_GEM` at `i915_drv.c:3284` (no `drm_ttm_bdev` assignment anywhere in `i915/`) |
| radeon | `DRIVER_GEM` at `radeon_drv.c:671`; `drm_ttm_bdev` set at `radeon_ttm.c:913` |
| amdgpu | `DRIVER_GEM` at `amdgpu_drv.c:1304`; `drm_ttm_bdev` set at `amdgpu_ttm.c:1796` |

**Conclusion: `drm_mmap()` is unreachable on stock systems.** DF-2124 (the
NULL `filp->private_data` panic) and DF-2126 (pagelist KVA-as-PFN) both
live inside this dead handler — their real-world severity ceiling is
therefore lower than a live-path bug; they are correctness debt, not
attack surface, *today*. (Any future port of a DRI1-era non-GEM driver
would resurrect all of it, which is why deletion is recommended.)

### Step 2 — the three latent defects (proven by citation)

1. **Key scale mismatch.** Insert: `hash->key = user_token >> PAGE_SHIFT`
   (`drm_bufs.c:98`); remove: `drm_ht_remove_key(..., user_token >>
   PAGE_SHIFT)` (`drm_bufs.c:511-512`); lookup: `drm_ht_find_item(&dev->
   map_hash, offset, ...)` with `offset` = raw **byte** file offset
   (`drm_vm.c:91`, `ap->a_offset` byte-accumulated in
   `device_pager.c:329`/`360`). `drm_ht_find_key` compares keys for full
   equality (`drm_hashtab.c:83`) — a hit requires the byte offset to
   numerically equal a page-number key. A well-behaved client (mmap at
   `user_token`) therefore *always* gets `-EINVAL`; only a client that
   mmaps at a page-number-key *value* can hit, and then:
2. **Token double-count.** `drm_vm.c:121` `phys = map->offset + offset`
   and `:130` `vtophys((char *)map->handle + offset)` add the *absolute*
   mmap offset to the map base instead of the offset *within* the map
   (`offset - user_token`). On the only reachable hit shape, the mapped
   physical page is `map->offset + K` where `K` is the (page-scaled) key —
   an attacker-influenced page *beyond* the map base, not the map's first
   page; for `_DRM_SHM` the `vtophys()` argument is `handle + K`, an
   essentially arbitrary kernel-virtual address.
3. **PFN/byte inconsistency.** `device_pager.c:360` interprets the
   `d_mmap` result through `pmap_phys_address()` = `ptob(ppn)`
   (`pmap.c:5985-5989`), i.e. a PFN is required. The map branch complies
   (`atop(phys)`, `drm_vm.c:137`); the DMA branch does not
   (`ap->a_result = phys`, `:74`) — off by 4096×, a sibling of (but
   distinct from) DF-2126's pagelist-contents confusion.

Also absent: any `map->size` bound on the mapping (Linux's original
drm_mmap checks the mapping length against `map->size`); the only bound is
the per-page ctor loop.

### Step 3 — what *is* live in this file

The fictitious-segment helpers (`drm_vm.c:141-227`) are live at runtime on
GPU systems: registered at attach (`i915_gem_gtt.c:2968`,
`radeon_device.c:1493`, `amdgpu_device.c:2648`), consulted on every GPU VM
fault (`ttm_bo_vm.c:667`, `i915_gem.c:2391`). DF-2125 (lockless
segment race) applies to them and is *not* downgraded by this finding.

### Why no runtime PoC

The audit guest is QEMU/KVM with a bochs display device and no
Intel/AMD GPU (`env.txt`: `pciconf -l` shows only `vgapci0 … chip=0x11111234`,
`ls /dev/dri` → No such file). The DRM core never attaches, so neither the
live GEM/TTM paths nor the dead legacy path exist at runtime. Even on a
GPU-equipped machine, the dead path cannot be triggered (Step 1). The
correct verification for this class is the source reachability proof,
which is complete and certain.

## Fix validation

Not applicable (Info-class hardening finding; the advisory `fix.diff` was
not built into a kernel — the path is unreachable, so no behavior could
change observably).

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