DF-4412 / verdict.json
{ "finding_id": "DF-4412", "status": "not_reproduced", "reproduced": 0, "impact": "none", "confidence": "likely", "verdict": "Kernel heap OOB write by trace (radeon_vm.c:135 snapshot vs :149 live re-read of vm->max_pde_used; neither call site holds vm->mutex - radeon_gem.c:569 and radeon_cs.c:191 both precede the mutex_lock at radeon_gem.c:583 / radeon_cs.c:564), but the audit guest has no radeon GPU (/dev/dri absent, QEMU std VGA only) so the race cannot be exercised at runtime. Trigger compiles and runs, exits at open(/dev/dri/card0)=ENOENT (run.log). Analysis-classified impact: kernel heap corruption from an unprivileged DRI client (High); not a false positive - every element of the chain is unconditional source fact, only the timing is untested.", "exploit_chain": "win TOCTOU race (fresh drm fd per round) -> list[idx]/list_add() in radeon_vm_get_bos() write ~48-byte kernel-pointer slots past the kvmalloc_array -> corrupt adjacent kmalloc-zone objects -> victim-object pivot -> uid=0 (sketch, untested without HW)", "evidence": "VERDICT.md (race layout + line cites); run.log (device-absent); fix.diff (snapshot fix)", "kernel_refs": ["sys/dev/drm/radeon/radeon_vm.c:135", "sys/dev/drm/radeon/radeon_vm.c:149", "sys/dev/drm/radeon/radeon_vm.c:535", "sys/dev/drm/radeon/radeon_gem.c:569", "sys/dev/drm/radeon/radeon_cs.c:191"], "poc_changes": "initial draft used kernel uapi include (broken chain on DFly: uapi/linux/types.h wants asm/int-ll64.h); replaced with self-contained radeon_abi.h; USE_VM moved to a RADEON_CHUNK_ID_FLAGS chunk (drm_radeon_cs_chunk has no flags member); -pthread added", "attempts": 1, "guest_uname": "DragonFly dfbsd 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": 12, "guest_dirty": 1, "build_cmd": "cc -O2 -Wall -pthread -o /tmp/trigger_race DF-4412/trigger_race.c", "run_cmd": "/tmp/trigger_race", "code_hash": "f1448775c361fffdfaae4dbb072ac2d02267c47f215b21e534245c807cb0f7e1", "notes": "Hardware precondition absent on guest (no radeon emulation exists in QEMU). compiler-reload reasoning in VERDICT.md (list_add call + stores may alias vm).", "recommended_fix": "Snapshot vm->max_pde_used into a local before kvmalloc_array and use the snapshot as the loop bound", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "fix validation impossible on this guest: the bug itself cannot be triggered (no radeon GPU), so baseline vs patched comparison has no observable. fix.diff is line-accurate against the traced root cause and applies to sys/dev/drm/radeon/radeon_vm.c.", "fix_evidence": "fix.diff (snapshot of max_pde_used for both alloc and loop bound)" } |