DF-3740 / verdict.json
{ "finding_id": "DF-3740", "status": "inconclusive", "reproduced": 0, "impact": "none", "confidence": "certain", "verdict": "Source-certain kernel-stack overflow. radeon_atom_get_mclk_range_table() computes num_entries=(u8)((usModuleSize-32)/24) from the BIOS VRAM modules u16 usModuleSize and copies num_entries BIOS u32s into mclk[MAX_AC_TIMING_ENTRIES=16] (radeon_mode.h:637-649) with NO bound between the u8 count (up to 255 after truncation) and the 16-slot array. The ONLY caller (cypress_dpm.c:1075-1089, cypress_get_memory_clock_range_table) passes a stack local struct atom_memory_clock_range_table range_table = {0} \u2014 so up to 239 BIOS-chosen u32s (956 B) are written past a 68-byte stack object (return address / caller frame). Harness on guest: usModuleSize=0xFFF0 -> num_entries=168 -> 152 OOB u32 writes (608 B past struct end). A truncation underflow (usModuleSize < 32) yields arbitrary num_entries as well. Downstream cypress_retrieve_ac_timing_for_all_ranges() also READS mclk[i] for i<num_entries (OOB stack reads). Not executable in-kernel on this guest (no AMD GPU).", "exploit_chain": "crafted VRAM_Info table (frev1/crev4) with usModuleSize=0xFFF0 on a Cypress/Juniper GPU -> 168-entry fill into 16-slot stack array at DPM init -> overwrites caller frame with BIOS u32s -> crash/controlled-stack-corruption (BIOS-gated privesc-grade primitive)", "evidence": "harness_mclk.c + build.log + run.log + run.stack.log (direct-stack mode); VERDICT.md; kernel refs sys/dev/drm/radeon/radeon_atombios.c:3925-3946", "kernel_refs": [ "sys/dev/drm/radeon/radeon_atombios.c:3925-3946", "sys/dev/drm/radeon/cypress_dpm.c:1075-1089", "sys/dev/drm/radeon/radeon_mode.h:637-649", "sys/dev/drm/radeon/radeon.h:354" ], "poc_changes": "harness written from scratch (no seed PoC): verbatim kernel arithmetic replica with canary-guarded destination model, built and executed on the DragonFly guest (cc 8.3); fixed nested-comment, stddef/stdint includes and volatile divisors during bring-up", "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": 6, "guest_dirty": 0, "build_cmd": "./build.sh", "run_cmd": "./run.sh (after ./build.sh); optional: ./mclk_bin stack (performs the overflow on the harness frame)", "code_hash": "e6d73bf1a7777817b1d3a58561d1223f4a46859e9c950e42fdd44771593c51c4", "notes": "Guest has NO AMD/radeon GPU (virtio-only); /boot/kernel/radeon.ko exists (code shipped in the default install) but cannot attach, so the kernel code path is unreachable at runtime on this guest. Evidence is source-level certainty (path:line traced) plus a verbatim-arithmetic userland harness compiled and executed on the guest (build.log/run.log).", "recommended_fix": "reject/clamp num_entries to MAX_AC_TIMING_ENTRIES", "fix_status": "not_tested", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff authored after source-level verification; cannot be validated on this guest (no AMD GPU; radeon.ko cannot attach). Compiling the module or booting a patched kernel would not exercise the path without hardware.", "fix_evidence": "fix.diff (unified, against read-only sys/ tree; never applied)" } |