DF-5192 / verdict.json
{ "finding_id": "DF-5192", "status": "untested", "reproduced": false, "impact": "none", "confidence": "likely", "verdict": "Latent struct-relative OOB in i915_gem_batch_pool_get: the LRU bucket index n = fls(size >> PAGE_SHIFT) - 1 (sys/dev/drm/i915/i915_gem_batch_pool.c:95) is clamped only from above (lines 96-97). DragonFlys fls(0)==0 (sys/cpu/x86_64/include/cpufunc.h:283-288) means any size < PAGE_SIZE yields n = -1, and &pool->cache_list[-1] (line 98) aliases the live engine pointer (struct layout: engine ptr then cache_list[4], i915_gem_batch_pool.h:13-16, embedded at intel_ringbuffer.h:439) \u2014 the walk at line 100 chases a wild next pointer and list_move_tail at line 142 writes through engine-as-list_head and clobbers pool->engine: a kernel memory-corruption primitive. However it is unreachable on this tree: the only two call sites are i915_gem_execbuffer.c:1153 (literal PAGE_SIZE, n=0) and i915_gem_execbuffer.c:1939 (PAGE_ALIGN(eb->batch_len) gated by eb_use_cmdparser()s && eb->batch_len at i915_gem_execbuffer.c:312-315, evaluated at the same point in i915_gem_do_execbuffer:2326-2333, before the batch_len==0 expansion at 2351-2352), so size >= PAGE_SIZE always. No userspace trigger can exist without first adding a new faulty kernel caller; verification was by exhaustive static call-site proof (no guest run applicable). Filed as Info hardening with a one-line lower clamp.", "exploit_chain": "", "evidence": "findings/poc/DF-5192/VERDICT.md (full reachability proof and the killed alternative classes); README.md (hazard anatomy); fix.diff (one-line clamp, git apply --check verified against read-only sys/). Decisive citations: i915_gem_batch_pool.c:95-98 (unclamped -1 index), i915_gem_execbuffer.c:312-315 (the distant && eb->batch_len guard that currently saves it), i915_gem_execbuffer.c:1153 (constant PAGE_SIZE caller), i915_gem_execbuffer.c:2326-2352 (gate ordering), cpufunc.h:283-288 (fls(0)==0).", "kernel_refs": [ "sys/dev/drm/i915/i915_gem_batch_pool.c:95", "sys/dev/drm/i915/i915_gem_batch_pool.c:96", "sys/dev/drm/i915/i915_gem_batch_pool.c:98", "sys/dev/drm/i915/i915_gem_batch_pool.c:100", "sys/dev/drm/i915/i915_gem_batch_pool.c:142", "sys/dev/drm/i915/i915_gem_batch_pool.h:13", "sys/dev/drm/i915/intel_ringbuffer.h:439", "sys/dev/drm/i915/i915_gem_execbuffer.c:312", "sys/dev/drm/i915/i915_gem_execbuffer.c:1153", "sys/dev/drm/i915/i915_gem_execbuffer.c:1939", "sys/dev/drm/i915/i915_gem_execbuffer.c:2326", "sys/dev/drm/i915/i915_gem_execbuffer.c:2351", "sys/cpu/x86_64/include/cpufunc.h:283" ], "poc_changes": "No PoC exists and none was seeded: the path is unreachable from userspace on this tree (proof in VERDICT.md). Pack is analysis-only by design; no build.sh/run.sh, no guest artifacts.", "attempts": 0, "guest_uname": "n/a (analysis-only; guest not used)", "runtime_sec": 0, "guest_dirty": 0, "build_cmd": "", "run_cmd": "", "code_hash": "480bef1eaa0a879c0ec7ae47935a83344326019d06d02a6515d4f09b41d1f8cd", "notes": "code_hash is sha256 of fix.diff (the packs only code artifact; no runnable PoC source exists for an unreachable path). Pass-2 depth beyond DF-2192: LRU-move/detach race killed (all list mutators under drm.struct_mutex \u2014 get asserted at batch_pool.c:89 via execbuffer.c:2297; fini at intel_engine_cs.c:671 and park-path :1097 via __i915_gem_park asserted at i915_gem.c:153); fini-with-active-objects leak/UAF killed (i915_gem.c:5420-5429 active-ref conversion; no batch_pool_link list_del anywhere; RCU-deferred frees i915_gem.c:5400-5418); fresh-object list_move_tail killed (INIT at i915_gem.c:5099 via i915_gem_internal.c:202); NULL fence clear killed (linux_reservation.c:244-246); 4GiB truncation killed (phys_addr_t + overflows_type, i915_gem_internal.c:186-195); bucket-migration of oversized objects is efficiency-only. DF-2192 (create-path leak at batch_pool.c:133-140) known, not re-reported.", "recommended_fix": "Clamp the bucket index lower bound: if (n < 0) n = 0; beside the existing upper clamp at i915_gem_batch_pool.c:96-97 (see fix.diff).", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "Fix validation not applicable: the bug does not manifest on any current caller (unreachable), so there is no baseline behavior to observe and no patched-kernel differential to measure. The one-line clamp is a pure defense-in-depth guard with zero behavior change for existing callers; verified to apply cleanly (git apply --check) against sys/dev/drm/i915/i915_gem_batch_pool.c without modifying sys/.", "fix_evidence": "findings/poc/DF-5192/fix.diff (git apply --check OK against the read-only tree; never applied)." } |