DF-5186 / verdict.json
{ "finding_id": "DF-5186", "status": "inconclusive", "verdict": "Code-certain race, target-device-absent on this guest. drm_mode_mmap_dumb_ioctl is dispatched DRM_UNLOCKED|DRM_RENDER_ALLOW (drm_ioctl.c:676, invoked locklessly at drm_ioctl.c:777); the i915 override (.dumb_map_offset=i915_gem_mmap_gtt, i915_drv.c:3301 -> i915_gem.c:2600-2602) and the GEM default both reach drm_gem_create_mmap_offset_size (drm_gem.c:567-606), whose on_map/map_list.key/drm_ht_insert_item/idxunr publication has no synchronization, while the same hash is the authoritative mmap resolver under DRM_LOCK (drm_gem.c:1063-1109). Two barrier-synced MAP_DUMB calls on one fresh handle deterministically corrupt state (proved by the 1:1 kernel transliteration in sim_interleave.c: live-key free_unr + teardown double-free => index aliasing; same drm_hash_item linked into two buckets => drm_ht_find_item returns the wrong object => cross-object/UAF mapping via drm_gem_mmap_single). The QEMU audit guest has no DRM device (std-VGA, no /dev/dri, no drm kld, no vgem in-tree), so the kernel path cannot be entered: PoC builds clean (cc 8.3) and runs, exiting 2 with no /dev/dri node available (run.log). Ready to run on any i915/amdgpu/radeon DragonFly box; smoking gun = MAP_DUMB EINVAL + [drm:drm_gem_create_mmap_offset_size] *ERROR* failed to add to map hash.", "reproduced": false, "impact": "none", "confidence": "likely", "exploit_chain": "video-group user opens /dev/dri/card0 (0660 root:video, drm_drv.c:1178) -> CREATE_DUMB (no auth) -> two threads barrier-synchronized MAP_DUMB on the fresh handle, with create/destroy churn recycling idxunr -> corrupted offset_hash (double free_unr / dual-linked node) -> mmap(card0_fd, KEY|OFF(idx)) resolving an aliased or dangling entry -> wrong-or-freed GEM object mapped: cross-process GPU-buffer disclosure or UAF-class RW mapping. Ceiling not demonstrated: needs DRM hardware this guest lacks.", "evidence": "run.log (PoC exit 2 - no /dev/dri on guest), sim_output.txt (deterministic interleaving A: live-key free + double free_unr + index aliasing; interleaving B: same node in two buckets + drm_ht_find_item(1) returns objA -> wrong-object resolution), env.txt (guest uname/kldstat/no-dri), build.log, VERDICT.md full path trace", "kernel_refs": [ "sys/dev/drm/drm_dumb_buffers.c:115-130", "sys/dev/drm/drm_ioctl.c:676", "sys/dev/drm/drm_ioctl.c:777", "sys/dev/drm/drm_gem.c:567-606", "sys/dev/drm/drm_gem.c:529-546", "sys/dev/drm/drm_gem.c:1063-1109", "sys/dev/drm/drm_hashtab.c:109-133", "sys/dev/drm/i915/i915_drv.c:3301", "sys/dev/drm/i915/i915_gem.c:2600-2648" ], "poc_changes": "n/a (seed written from scratch in this run; self-contained uapi defs because the guest ships no drm headers; pair-barrier churn design so the race hits the first-MAP_DUMB window of every fresh object)", "attempts": 3, "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": 95, "guest_dirty": 0, "build_cmd": "cc -O2 -Wall -pthread -o mapdumb_race mapdumb_race.c && cc -O2 -Wall -o sim_interleave sim_interleave.c", "run_cmd": "./mapdumb_race 20000 && ./sim_interleave", "code_hash": "8d39eec92884fbf04a65c9726e6f48a2a7beda12c59e418f83f7f8a3a7f989de", "notes": "DRM device nodes are root:video 0660 (drmP.h:108-110) - a standard desktop user qualifies. All three in-tree KMS drivers override .dumb_map_offset but i915s override still funnels into the vulnerable drm_gem_create_mmap_offset. In-file drm_mode_create_dumb size math audited correct (64-bit checks at drm_dumb_buffers.c:64-80; PAGE_ALIGN wrap caught on 32-bit). Guest left clean (files under /root/df5186 and /tmp/df5186_race only; no kernel state touched).", "recommended_fix": "Serialize drm_gem_create_mmap_offset_size/drm_gem_free_mmap_offset legacy offset-hash publication with dev->object_name_lock (sleepable, LK_CANRECURSE) - see fix.diff", "fix_status": "not_applicable", "fix_baseline_reproduced": false, "fix_patched_reproduced": false, "fix_verdict": "Baseline cannot be exercised on this guest (no DRM device), so a patched-kernel A/B run is impossible here; fix.diff is line-accurate against drm_gem.c:529-588 and must be validated on DRM hardware (with the patch, concurrent MAP_DUMB can never lose the insert race, so no live-key free_unr / dual-link).", "fix_evidence": "fix.diff" } |