DF-3856 / verdict.json
{ "finding_id": "DF-3856", "status": "inconclusive", "reproduced": 0, "impact": "none", "confidence": "certain", "verdict": "Source-certain undefined behavior: four combios parser sites use an unchecked BIOS byte as a 32-bit shift count. combios_parse_pll_table() case 1 computes shift = RBIOS8(offset)*8 (0..2040) and shifts with it (radeon_combios.c:3103-3108), feeding WREG32_PLL a value masked with a garbage-derived and/or mask pair at driver init/resume from the PLL INIT / DYN CLK tables (radeon_combios.c:3329-3340, 3407-3410). Voltage-GPIO masks (1 << tmp) at :2752/:2760 (consumed by the r100_pm_misc RMW - see DF-3852), i2c gpiopad masks (1 << clk)/(1 << data) at :654-658, and thermal-controller masks (1 << clk_bit) at :2687 share the defect. C99 6.5.7p3 makes counts >= 32 UB. Harness demonstrates the concrete misbehaviour on the audit toolchain (DragonFly cc 8.3, x86-64): counts silently taken mod 32 - pll case 1 with shift byte 4 yields and_mask 0xffffff0f (byte lane 0) where lane 3 (0x0fffffff) was programmed; 1<<32 gives bit 0; 1<<200 gives bit 8 - wrong PLL/GPIO programming with no trap and no runtime warning. Kernel-side write sinks hardware-gated (no radeon device on guest). Low severity standalone; force-multiplier for the MMIO-injection findings.", "exploit_chain": "crafted or bit-flipped VBIOS -> shift byte >= 4 (pll table) or >= 32 (mask sites) -> UB shifts silently mis-build the mask pair -> WREG32_PLL / r100_pm_misc / GPIO set_masks write wrongly-masked values -> GPU clock/GPIO misprogramming (hang / failed posting)", "evidence": "run.log decisive lines: [pll case1] shift_byte=4 -> shift=32: and_mask=0xffffff0f (UB! count taken mod 32 -> lane 0 ... expected 0x0fffffff), [gpio mask] tmp=32 -> 1<<tmp = 0x00000001 (UB! ...), [gpio mask] tmp=200 -> 1<<tmp = 0x00000100 (UB! ...); fix_apply.log: 3 hunks apply to pristine /usr/src (654, 2686, 3103)", "kernel_refs": [ "sys/dev/drm/radeon/radeon_combios.c:3102-3113", "sys/dev/drm/radeon/radeon_combios.c:2751-2760", "sys/dev/drm/radeon/radeon_combios.c:650-658", "sys/dev/drm/radeon/radeon_combios.c:2669-2687", "sys/dev/drm/radeon/radeon_combios.c:3329-3340", "sys/dev/drm/radeon/radeon_combios.c:3407-3410" ], "poc_changes": "harness written from scratch (no seed); first build failed (nested C comment markers + em-dashes in header comment - gcc stray errors); rewritten; demo bytes changed from 0xff to 0x0f so the wrong byte-lane is visible in and_mask", "attempts": 2, "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": 22, "guest_dirty": 0, "build_cmd": "./build.sh (cc -O2 -Wall -o harness harness.c)", "run_cmd": "./run.sh", "code_hash": "4f1e479ce0b26450e7318646ec7dc461003838ba8c94c7918521f4c0585223f6", "notes": "The voltage-mask site (:2752/:2760) is also covered by DF-3852s fix.diff; the two diffs are independent and both apply. Exact UB output is compiler-dependent - that is the defect (no defined correct behavior exists for these BIOS bytes).", "recommended_fix": "Bound every BIOS-sourced shift count: pll-table case 1 accepts shift bytes <= 3 (skip record otherwise, staying aligned); mask sites accept bit numbers < 32 (fix.diff)", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff applies cleanly to pristine /usr/src (fix_apply.log, hunks at 654/2686/3103); runtime fix validation impossible on this guest (no hardware)", "fix_evidence": "fix.diff; fix_apply.log" } |