DF-3828 / verdict.json
{ "finding_id": "DF-3828", "status": "not_reproduced", "reproduced": 0, "impact": "none", "confidence": "certain", "verdict": "Source-certain divide-by-zero family in the DCE11 display watermark math: dce_v11_0_latency_watermark() divides by available_bandwidth at dce_v11_0.c:908-909 and by wm->disp_clk at :910, all before the functions only guard (num_heads==0, :918) and with no divisor validation on any caller path. Zero inputs traced end-to-end: amdgpu_atombios_get_clock_info() copies VBIOS ulDefaultEngineClock/ulDefaultMemoryClock into default_sclk/default_mclk with no zero-guard (amdgpu_atombios.c:677-680 - unlike neighboring fields at :610/:642/:669/:694/:708) and assigns them to pm.current_sclk/current_mclk even on parse failure (:718-719); with DPM disabled, dce_v11_0_program_watermarks (:1064-1065) feeds them straight into the bandwidth terms, which collapse to 0, and a mode-set ioctl (dce_v11_0.c:2106 call chain) takes #DE -> kernel panic on any Carrizo/Stoney/Polaris/VEGAM machine in that state: local DoS by an unprivileged DRM client. The arithmetic primitive is proven on the guest: the exact replica of available_bandwidth()+latency_watermark() traps with SIGFPE (signal 8 = #DE, exit 136) in 2/2 runs while the healthy-clock control returns normally (run.log, run.2.log, dmesg in VERDICT.md). Kernel-path reproduction is impossible on this guest - it has no AMD display ASIC (bochs VGA only, no /dev/dri, env.txt) - hence not_reproduced for the kernel reach; impact ceiling on equipped hardware: dos via panic.", "exploit_chain": "unprivileged user opens /dev/dri/card0 (graphics/console user) -> drm_mode_setcrtc on any connector -> dce_v11_0_crtc_do_set_base -> dce_v11_0_bandwidth_update (dce_v11_0.c:2106) -> dce_v11_0_program_watermarks -> dce_v11_0_latency_watermark -> div by available_bandwidth==0 -> #DE -> panic. Precondition: pm.current_sclk or current_mclk == 0 (VBIOS zero default clocks / failed clock-info parse with DPM off).", "evidence": "run.log + run.2.log (SIGFPE exit=136 twice, healthy control clean); VERDICT.md (full chain incl. amdgpu_atombios.c zero-guard omission and the killed IV-ring OOB theories); env.txt (no AMD ASIC on guest)", "kernel_refs": [ "sys/dev/drm/amd/amdgpu/dce_v11_0.c:908", "sys/dev/drm/amd/amdgpu/dce_v11_0.c:910", "sys/dev/drm/amd/amdgpu/dce_v11_0.c:918", "sys/dev/drm/amd/amdgpu/dce_v11_0.c:1064", "sys/dev/drm/amd/amdgpu/amdgpu_atombios.c:677", "sys/dev/drm/amd/amdgpu/amdgpu_atombios.c:718" ], "poc_changes": "Authored from scratch (no seed). v1 constant-folded the zero divisor into ud2/SIGILL under -O2; inputs moved to argv so the trap is the genuine #DE -> SIGFPE (signal 8), matching the kernel fault class.", "attempts": 3, "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": 58, "guest_dirty": 0, "build_cmd": "cc -O2 -Wall -o /tmp/wm_div0 /tmp/wm_div0.c", "run_cmd": "/tmp/wm_div0; echo exit=$?", "code_hash": "031faf3e676decc0be6d5c7def0e032f0fe49c20621636c5e8023156f5561a4a", "notes": "DF-3665 (evergreen latency_watermark div0) family twin, hunted per checklist item (a). Sibling divides at :967/:987 (num_heads) are protected by the caller guard at :1050; check_latency_hiding :1004 (src_width) needs a zero-width mode - folded into the same finding. IV-ring OOB candidates at :3239-3242 and :3332-3333 killed by the amdgpu_irq_dispatch registered-src_id contract (amdgpu_irq.c:414-432).", "recommended_fix": "Validate available_bandwidth and wm->disp_clk non-zero before the divides in dce_v11_0_latency_watermark (bail to 0 like the num_heads==0 path), guard mode->clock in program_watermarks, and add the missing zero-guards for default_sclk/default_mclk in amdgpu_atombios_get_clock_info.", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff guards all three divides plus the mode->clock divides and the VBIOS zero-clock seeding. A patched-kernel build cannot be exercised on this guest: amdgpu never attaches without an AMD ASIC, so there is no observable kernel behavior difference - hardware fix validation is not_testable here.", "fix_evidence": "fix.diff; VERDICT.md" } |