# DF-5122 — Legacy `drm_mmap` path: page/byte key mismatch + token double-count + PFN/byte inconsistency — latent defects in a path unreachable on all shipped drivers

Severity: **Info** (hardening / triage-correction) · Confidence: **certain** (all claims verified by source citation; no runtime trigger exists on this or any stock system)

## What this is

A pass-2 structural finding on `sys/dev/drm/drm_vm.c`. It documents that the
legacy `d_mmap` handler `drm_mmap()` contains *three additional* correctness
defects beyond the known trio (DF-2124/2125/2126), **and** that the entire
handler is unreachable for every DRM driver DragonFly ships — which
materially informs triage of DF-2124 and DF-2126 (they live in dead code),
while DF-2125 (the fictitious helpers) *is* reachable at runtime via
`ttm_bo_vm.c:667` / `i915_gem.c:2391`.

## The three defects (all in `drm_mmap`, drm_vm.c:44-139)

1. **Hash-key scale mismatch** — `drm_vm.c:91` looks up `dev->map_hash` with
   the raw **byte** mmap offset, but keys are inserted and removed as
   **page numbers** (`drm_bufs.c:98` `hash->key = user_token >> PAGE_SHIFT`,
   `drm_bufs.c:511-512`). A lookup can therefore only succeed by numeric
   coincidence (byte offset == someone's page-number key). For a normal
   client that mmaps at the token it was given (`user_token`, bytes), the
   lookup *always* misses → `-EINVAL`. 

2. **Token double-count in the physical address** — on a coincidental hit,
   `drm_vm.c:121` computes `phys = map->offset + offset` and `:130`
   `vtophys((char *)map->handle + offset)` where `offset` is the *absolute*
   file offset (== the token), not the offset *within* the map. The correct
   arithmetic is `map->offset + (offset - user_token)`. As written, a hit at
   token T maps `map->offset + T` (and for `_DRM_SHM`, `vtophys` of
   `handle + T`, an arbitrary kernel-virtual expression).

3. **Return-convention inconsistency** — the DMA branch returns a raw byte
   address (`drm_vm.c:74` `ap->a_result = phys`), while the map branch
   returns a PFN (`:137` `ap->a_result = atop(phys)`). The consumer,
   `old_dev_pager_fault()` (`sys/vm/device_pager.c:360`), feeds the result
   to `pmap_phys_address()`, which on pc64 is `ptob(ppn)`
   (`sys/platform/pc64/x86_64/pmap.c:5985-5989`) — i.e. the **PFN
   convention** is required; the DMA branch is off by 4096× (this is the
   same family as DF-2126 but a distinct defect: DF-2126 is about
   *pagelist contents*, this is about the *missing atop()*).
   Also note Linux's original `drm_mmap` bounds the mapping against
   `map->size`; the DFly port has no equivalent (the per-page protocol of
   `old_dev_pager_ctor`, `device_pager.c:329-332`, is the only bound).

## Why the path is unreachable (the reachability proof)

* `vm_mmap()` dispatches a VCHR mmap first through `d_mmap_single`
  (`sys/vm/vm_mmap.c:1372-1378`) and only falls back to the old device
  pager (`d_mmap`) when that returns **ENODEV** (`vm_mmap.c:1380-1386`).
* `drm_mmap_single` (`sys/dev/drm/drm_drv.c:1256-1274`) returns ENODEV only
  when `dev->drm_ttm_bdev == NULL` **and** the driver lacks
  `DRIVER_GEM`.
* Every DRM driver shipped in `sys/dev/drm/` sets `DRIVER_GEM`
  (i915: `i915_drv.c:3284`; radeon: `radeon_drv.c:671`;
  amdgpu: `amdgpu_drv.c:1304`), and radeon/amdgpu additionally set
  `drm_ttm_bdev` (`radeon_ttm.c:913`, `amdgpu_ttm.c:1796`).
* Therefore `drm_mmap()` (`.d_mmap = drm_mmap`, `drm_drv.c:1154`) can never
  be invoked on a stock system; the only callers of `dev_dmmap` for the DRM
  cdev are the fallback path that cannot be taken.

Contrast: the fictitious helpers in the same file
(`vm_phys_fictitious_reg_range` / `to_vm_page` / `unreg_range`,
drm_vm.c:141-227) **are** hot: registered at GPU attach
(`i915_gem_gtt.c:2968`, `radeon_device.c:1493`, `amdgpu_device.c:2648`) and
consulted on every GPU VM fault (`ttm_bo_vm.c:667`, `i915_gem.c:2391`).
DF-2125 applies to those and remains a live finding.

## Reproduce (static)

No runtime reproduction exists or is possible on the QEMU guest: it has no
Intel/AMD GPU (only the QEMU bochs display, `env.txt`), so the DRM core
never attaches and `/dev/dri` does not exist. The verification for this
finding is the source-level reachability proof above; see `VERDICT.md`.

## Recommended fix

Preferred: **delete the dead handler** (drop `.d_mmap = drm_mmap` from
`drm_cdevsw` and the `drm_mmap` body) — no shipped driver can reach it.
If a legacy (non-GEM/non-TTM) driver is ever ported, the key scale, token
rebasing and `atop()` must all be fixed together (see `fix.diff` for the
corrected arithmetic in advisory form).
