# DF-5188 — VERDICT

**Status: untested (by construction — the target code exists in no kernel artifact).**
**Impact: none today; latent 8x heap OOB write + unbounded `agp_memory` leak if the backend is ever compiled in.**
**Confidence: certain** (on every claim below; each is source- or binary-verifiable in one command).

## 1. What was audited

`sys/dev/drm/ttm/ttm_agp_backend.c` — full 150-line read (pass 2, GLM 5.3).
Pass 1 recorded no findings for this file (DB check: `findings` has zero rows
for it; the only ttm-family findings are on ttm_bo/ttm_bo_util/ttm_bo_vm/
ttm_page_alloc/ttm_execbuf_util/ttm_bo_manager/ttm_module/ttm_memory — see
DF-1445..DF-5138, none on this file).

## 2. Reachability — refuted at three independent layers

1. **Build system**: the only Makefile referencing the file is
   `sys/dev/drm/drm/Makefile`, where both `drm_agpsupport.c` and
   `ttm_agp_backend.c` sit **commented out** under the banner
   `# if CONFIG_AGP is set` (`Makefile:110-112`). No other Makefile in the
   tree mentions it (`rg -l ttm_agp sys/ --glob Makefile` → that one file).
2. **Kconfig**: `sys/dev/drm/kconfig.h` defines 15 CONFIG_ macros, none of
   them `CONFIG_AGP`; therefore `IS_ENABLED(CONFIG_AGP)` expands to 0
   (`sys/dev/drm/include/linux/kconfig.h:36-39`), and the only in-tree
   callers — `sys/dev/drm/radeon/radeon_ttm.c:705,769,824` — compile their
   `ttm_agp_tt_create/populate/unpopulate` call sites out entirely.
3. **The file cannot compile even if added**: `#include <asm/agp.h>`
   (`ttm_agp_backend.c:43`) — no such header exists anywhere under `sys/`;
   the only visible `struct agp_memory` declarations are the native
   `sys/dev/agp/agppriv.h:55-65` (members `am_id/am_size/am_type/am_obj/
   am_physical/am_offset/am_is_bound` — none of the `pages`, `page_count`,
   `is_flushed`, `type`, `is_bound` members used at `ttm_agp_backend.c:64-91`)
   and the empty forward declaration in
   `sys/dev/drm/include/linux/agp_backend.h:30-31`. Call arities also match
   nothing: `agp_free_memory(mem)` (1 arg, `:92`), `agp_bind_memory(mem, off)`
   (2 args, `:78`), `agp_unbind_memory(mem)` (1 arg, `:91`) versus the native
   prototypes `agpvar.h:100-116` (2, 3, and 2 args).

**Runtime confirmation** (guest, `dfbsd-qemu/vm.sh run_root`, no mutation):
`nm /boot/kernel/drm.ko | grep -ci agp_tt` → **0**. The 22,447,656-byte
`/boot/kernel/drm.ko` built Jun 29 2026 contains no `ttm_agp_*` symbol; the
only `agp`-matching strings are kld dependency metadata
(`_mod_metadata_md_drm_on_agp`). See `runtime_absence.log`.

Conclusion: no syscall, ioctl, mmap, net, or mount path can reach any
instruction of this file on any DragonFly configuration, current tree.

## 3. The latent hazards (why this is filed at Info rather than dropped)

The file shows signs of an **abandoned half-port** to the native API: the
alloc call was renamed from Linux's `agp_allocate_memory(agp_bridge,
num_pages, AGP_USER_MEMORY)` to `agp_alloc_memory(agp_be->bridge,
AGP_USER_MEMORY, ttm->num_pages)` — the native name and argument order
(`agpvar.h:100`) but with a **page count fed to a `vm_size_t bytes`**
parameter:

- `agp_generic_alloc_memory` (`sys/dev/agp/agp.c:456-473`) page-align-checks
  the byte size, charges it against `as_maxmem`, and sizes the backing
  `vm_object` via `atop(round_page(size))` (`agp.c:472`).
- On x86-64, passing `num_pages` bytes for a `num_pages`-page BO
  under-allocates by exactly `PAGE_SIZE / 8 = 8x`.
- The bind loop then stores `num_pages` page pointers
  (`ttm_agp_backend.c:65-72`). Any future shim that derives `mem->pages`
  from the (under-sized) native object turns this into a kernel heap OOB
  write with attacker-influenced contents (page pointers of an
  unprivileged-created TTM BO).

Second latent hazard — lifecycle leak: `ttm_agp_unbind` returns at `:91`
after `agp_unbind_memory()` on a bound region **without freeing or NULLing
`agp_be->mem`**, and `ttm_agp_bind` overwrites `agp_be->mem` at `:73`
without freeing the previous allocation (and leaves it set on the
`agp_bind_memory` failure path `:78-80`). Revived, every AGP aperture
rebind leaks one `agp_memory` + page array — unbounded kernel memory
exhaustion by an unprivileged DRM client.

FreeBSD's drm2 has exactly the LinuxKPI AGP shim this file is missing, so
"revive CONFIG_AGP" is a plausible future change that would walk into both
landmines unless this is on record.

## 4. Phase V

Not applicable in the strong sense: the trigger target (compiled code) does
not exist in any kernel image; there is nothing to build or run. The
verification that *was* performed is the three-layer reachability refutation
above plus the runtime symbol-absence check. Per the orchestrator's status
vocabulary this is recorded as `untested` with `impact: latent` and
`attempts: 1` (the nm check). No `fix.diff`: the fix is deletion or
completion of the port, not a one-line patch to live code; the recommended
disposition in README.md §"Recommended disposition" covers both.

## 5. Classes considered and killed (pass-2 depth)

- Populate/pages/counts OOB (`:60-72`): real *as latent unit bug*, dead as
  shipped — this finding.
- Unbind/bind/destroy double-free (`:85-106`): destroy path
  (`ttm_tt_destroy` → unbind-then-destroy, and the `:102-103` re-unbind)
  ends in `agp_free_memory` on the not-bound member — no double-free even
  hypothetically; the defect is the *leak*, covered above.
- `ttm_agp_tt_create` (`:114-134`): M_WAITOK NULL-check is dead code,
  error path frees correctly — nothing.
- `ttm_agp_tt_populate/unpopulate` (`:137-149`): thin wrappers into
  `ttm_pool_(un)populate` — that surface is already filed
  (DF-1663, DF-4507); nothing new here.
- Build gating: refuted above (Makefile:110-112, kconfig.h, radeon guards).

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

(No fix.diff for this item: documented recommendation only - see Fix above.)
