Integer divide-by-zero in spread-spectrum programming when the VBIOS SS rate is 0 (ci_calculate_mclk_params / ci_calculate_sclk_params)
Summary
radeon_atombios_get_asic_ss_info copies ss->rate raw from the VBIOS (no zero check); ci_dpm.c:2876 divides reference_clock*5/ss.rate and :3227 divides by (reference_divider*ss.rate) -> u32 #DE -> kernel panic at DPM init whenever the SS table has a matching entry with rate==0. Guest harness proved 100*5/0 -> SIGFPE with the exact u32 semantics. Twin of DF-3612/DF-3621.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3647 Β· 12 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | doc | 810 B | β raw | |
| VERDICT.md | doc | 2.8 KB | β raw | |
| fix.diff | doc | 1011 B | view raw | |
| env.txt | doc | 799 B | view raw | |
| verdict.json | doc | 3.0 KB | view raw | |
| manifest.json | doc | 1.3 KB | view raw | |
| harness.c | doc | 5.7 KB | view raw | |
| build.sh | doc | 65 B | view raw | |
| run.sh | doc | 89 B | view raw | |
| build.log | log | 0 B | β download | |
| run.log | log | 556 B | view raw | |
| run.2.log | log | 556 B | view raw |
DF-3647 β Integer divide-by-zero in spread-spectrum programming when the VBIOS SS rate is 0 (ci_calculate_mclk_params / ci_calculate_sclk_params)
File: sys/dev/drm/radeon/ci_dpm.c (pass 2, GLM 5.3 re-audit)
Severity: Medium | CWE-369 Divide By Zero | confidence: certain
Reproduce
This pack carries a userland logic harness (harness.c) built and run ON THE
AUDIT GUEST with the exact kernel types; decisive section: [B]
./build.sh ./run.sh
Expected decisive line: SIGFPE (kernel: #DE panic)
The kernel code path itself requires a Sea Islands radeon GPU + crafted VBIOS; the guest is virtio-only (no AMD PCI device, no /dev/dri, no drm kld) β see env.txt.
Full narrative: VERDICT.md. Proposed fix: fix.diff (authored against the read-only sys/ tree; never applied there).
DF-3647 β verdict narrative
Finding
Integer divide-by-zero in spread-spectrum programming when the VBIOS SS rate is 0 (ci_calculate_mclk_params / ci_calculate_sclk_params)
Kernel references
sys/dev/drm/radeon/ci_dpm.c:2876sys/dev/drm/radeon/ci_dpm.c:3221sys/dev/drm/radeon/ci_dpm.c:3227sys/dev/drm/radeon/radeon_atombios.c:1546sys/dev/drm/radeon/ci_dpm.c:5953
Was it reproduced?
No β not on the kernel path. The audit guest is virtio-only (0 AMD PCI devices, /dev/dri absent, no radeon/drm kld; env.txt), so sys/dev/drm/radeon/ci_dpm.c can never execute there. Per the pass-2 instruction for this hardware-gated file, the verdict is inconclusive (source-level certainty certain) rather than reproduced.
Logic-level proof (guest harness)
harness.c models the exact loop/index/division with the exact kernel types and was compiled and executed on the audit guest (cc -O2 -Wall, DragonFly 6.5-DEVELOPMENT). Decisive output, stable across 2 runs (run.log, run.2.log):
SIGFPE (kernel: #DE panic)
Root cause and reasoning
Source-certain div-by-zero, radeon/ci twin of DF-3612 (si) / DF-3621 (amdgpu ci). radeon_atombios_get_asic_ss_info() copies ss->rate straight from the VBIOS (radeon_atombios.c:1546, usSpreadRateInKhz) with no zero check and returns true on a matching entry. ci_calculate_mclk_params() then computes clks = reference_clock * 5 / ss.rate (ci_dpm.c:2876) and ci_calculate_sclk_params() computes clk_s = reference_clock * 5 / (reference_divider * ss.rate) (ci_dpm.c:3227). Both are u32 divisions; a zero rate raises #DE in kernel context -> panic. Reachable whenever caps_mclk_ss_support/caps_sclk_ss_support are set (they are set unconditionally when the ASIC_InternalSS_Info header parses, ci_dpm.c:5953-5957) and the SS assignment table contains a matching entry with rate==0 - trivially crafted. On-guest harness section [B] proved 100*5/0 faults with SIGFPE (userland analogue of #DE). Kernel path unreachable on this GPU-less guest, so overall inconclusive.
Exploitability
Crafted VBIOS with an ASIC_InternalSS_Info assignment whose usSpreadRateInKhz is 0 and whose target-clock range covers the boot mclk/sclk -> u32 divide by zero -> kernel panic at DPM enable. DoS only. (Hardware-gated; harness proved the arithmetic fault.)
Recommended fix
Reject SS entries with rate == 0 (skip SS programming / return -EINVAL) in ci_calculate_mclk_params and ci_calculate_sclk_params. See fix.diff.
Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
Fix verification
not_testableFix validation would require a CI-class GPU with a crafted VBIOS (baseline panic/corruption) and a single-fix kernel build; the audit guest is virtio-only, so the fix is source-reviewed only (fix.diff).
fix.diff in this pack; not applied to sys/ (read-only audit target).
Confirmed kernel references
Detail
Exploit chain
Crafted VBIOS with an ASIC_InternalSS_Info assignment whose usSpreadRateInKhz is 0 and whose target-clock range covers the boot mclk/sclk -> u32 divide by zero -> kernel panic at DPM enable. DoS only. (Hardware-gated; harness proved the arithmetic fault.)
Evidence (decisive lines)
VERDICT.md (full source trace); harness.c + run.log/run.2.log section [B] (SIGFPE (kernel: #DE panic)); env.txt (guest has no AMD GPU: pciconf 0x1002 count=0, /dev/dri absent, no drm kld); fix.diff
PoC changes
n/a β no seeded PoC for pass-2; harness written fresh (models the exact kernel types; divisors made volatile so -O2 cannot fold the #DE)
Verified recommended fix
Reject SS entries with rate == 0 (skip SS programming / return -EINVAL) in ci_calculate_mclk_params and ci_calculate_sclk_params.
Verdict
Source-certain div-by-zero, radeon/ci twin of DF-3612 (si) / DF-3621 (amdgpu ci). radeon_atombios_get_asic_ss_info() copies ss->rate straight from the VBIOS (radeon_atombios.c:1546, usSpreadRateInKhz) with no zero check and returns true on a matching entry. ci_calculate_mclk_params() then computes clks = reference_clock * 5 / ss.rate (ci_dpm.c:2876) and ci_calculate_sclk_params() computes clk_s = reference_clock * 5 / (reference_divider * ss.rate) (ci_dpm.c:3227). Both are u32 divisions; a zero rate raises #DE in kernel context -> panic. Reachable whenever caps_mclk_ss_support/caps_sclk_ss_support are set (they are set unconditionally when the ASIC_InternalSS_Info header parses, ci_dpm.c:5953-5957) and the SS assignment table contains a matching entry with rate==0 - trivially crafted. On-guest harness section [B] proved 100*5/0 faults with SIGFPE (userland analogue of #DE). Kernel path unreachable on this GPU-less guest, so overall inconclusive.
No comments yet.