DF-5188 / verdict.json
{ "finding_id": "DF-5188", "status": "untested", "verdict": "ttm_agp_backend.c is dead code with zero runtime reachability: it is commented out of the only Makefile that lists it (sys/dev/drm/drm/Makefile:110-112, # if CONFIG_AGP is set), CONFIG_AGP is not among the 15 defines in sys/dev/drm/kconfig.h so IS_ENABLED(CONFIG_AGP)=0 compiles out the sole in-tree callers (radeon_ttm.c:705,769,824), and the file cannot compile anyway (asm/agp.h at :43 exists nowhere under sys/; the Linux-style struct agp_memory members pages/page_count/is_flushed/type/is_bound used at :64-91 exist in no header a DRM build sees; agp_free_memory/agp_bind_memory/agp_unbind_memory arities at :78,:91-92 match no available prototype). Runtime-confirmed: nm /boot/kernel/drm.ko | grep -ci agp_tt = 0. The file is an abandoned half-port toward the native API whose landmines are on record for whoever revives it: (1) ttm_agp_backend.c:60 passes ttm->num_pages (a page count) as the vm_size_t bytes parameter of agp_alloc_memory (agpvar.h:100; agp.c:456-473 sizes the backing vm_object from that byte count) \u2014 an exact 8x under-allocation on x86-64 while the bind loop at :65-72 writes num_pages page pointers, i.e. a kernel heap OOB write once a shim exists; (2) ttm_agp_unbind returns at :91 on a bound region without freeing or NULLing agp_be->mem and ttm_agp_bind overwrites agp_be->mem at :73 without freeing the prior allocation \u2014 an unbounded agp_memory leak per AGP rebind cycle. Filed Info: no demonstrated impact on any current kernel configuration.", "reproduced": false, "impact": "latent: 8x heap OOB write of page pointers + unbounded kernel agp_memory leak, only if the dead backend is ever compiled in; impact today: none", "confidence": "certain", "exploit_chain": "", "evidence": "findings/poc/DF-5188/VERDICT.md sections 2-3 (three-layer reachability refutation with path:line + latent hazard derivation); runtime_absence.log (nm drm.ko: 0 agp_tt symbols, guest uname 6.5-DEVELOPMENT #0 Thu Jul 2 06:02:54 UTC 2026); README.md provenance table; sys/dev/drm/drm/Makefile:110-112; sys/dev/drm/kconfig.h (no CONFIG_AGP); sys/dev/drm/radeon/radeon_ttm.c:703-708,767-771,822-826; sys/dev/agp/agpvar.h:100-116; sys/dev/agp/agppriv.h:55-65; sys/dev/agp/agp.c:456-473; sys/dev/drm/include/linux/agp_backend.h:30-31", "kernel_refs": [ "sys/dev/drm/ttm/ttm_agp_backend.c:43", "sys/dev/drm/ttm/ttm_agp_backend.c:60", "sys/dev/drm/ttm/ttm_agp_backend.c:65-72", "sys/dev/drm/ttm/ttm_agp_backend.c:73", "sys/dev/drm/ttm/ttm_agp_backend.c:78-80", "sys/dev/drm/ttm/ttm_agp_backend.c:89-94", "sys/dev/drm/drm/Makefile:110-112", "sys/dev/agp/agpvar.h:100", "sys/dev/agp/agp.c:456-473", "sys/dev/agp/agppriv.h:55-65", "sys/dev/drm/radeon/radeon_ttm.c:705", "sys/dev/drm/radeon/radeon_ttm.c:769", "sys/dev/drm/radeon/radeon_ttm.c:824" ], "poc_changes": "n/a \u2014 no PoC exists or can exist for code present in no binary; the verification artifact is the reachability refutation (source citations + nm symbol-absence on the shipped drm.ko)", "attempts": 1, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64", "runtime_sec": 25, "guest_dirty": 0, "build_cmd": "n/a (no buildable target \u2014 file excluded from all Makefiles)", "run_cmd": "vm.sh run_root nm /boot/kernel/drm.ko | grep -ci agp_tt # -> 0", "code_hash": "", "notes": "Guest was already up; used read-only for the symbol-absence check, no mutation, no reset needed (guest_dirty=0). No fix.diff: recommended disposition is deletion of the dead file or completion of the port (bytes-vs-pages at :60, free-previous at :73, free+NULL in the bound branch of ttm_agp_unbind) \u2014 see README.md. ttm family now complete for pass 2 (ttm_tt/bo/bo_util/bo_vm/bo_manager/execbuf/memory/module/page_alloc previously filed; this file is the dead AGP tail).", "recommended_fix": "Delete ttm_agp_backend.c (and the commented #SRCS block), or if AGP support is revived: fix the unit confusion (agp_alloc_memory(bridge, type, (vm_size_t)ttm->num_pages << PAGE_SHIFT) at :60), free the prior agp_be->mem before the overwrite at :73, and free+NULL in the is_bound branch of ttm_agp_unbind (:90-91)", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "n/a \u2014 dead code, nothing to validate a fix against", "fix_evidence": "" } |