Integer divide-by-zero on zero MPLL reference clock in ci_calculate_mclk_params (usMemoryReferenceClock stored unchecked)
Summary
adev->clock.mpll.reference_freq is assigned verbatim from FirmwareInfo.usMemoryReferenceClock with no zero fixup (unlike pll_out_min). ci_calculate_mclk_params divides freq_nom by it inside the caps_mclk_ss_support block; freq_nom cannot be 0 (mclk==0 rejected), so a zero reference clock plus any parseable SS header is an unconditional #DE panic at ci_dpm_enable -> ci_populate_all_memory_levels. Twin of si_dpm DF-3613. The SPLL reference clock is only ever a multiplier in this file - the mpll path is the sole reference-clock divide.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3622 Β· 8 files| File | Type | Description | Size | |
|---|---|---|---|---|
| ci_ss_div0.c | β | 3.1 KB | view raw | |
| build.sh | β | 92 B | view raw | |
| run.sh | β | 116 B | view raw | |
| build.log | β | 393 B | view raw | |
| run.log | β | 393 B | view raw | |
| env.txt | β | 547 B | view raw | |
| VERDICT.md | β | 2.4 KB | β raw | |
| fix.diff | β | 576 B | view raw |
DF-3622 VERDICT β divide-by-zero on zero MPLL reference clock
Bottom line
Real bug, source-certain; runtime inconclusive (no AMD GPU on guest).
ci_calculate_mclk_params() divides by adev->clock.mpll.reference_freq
without checking it (ci_dpm.c:2977):
u32 reference_clock = adev->clock.mpll.reference_freq; /* :2970 */
...
tmp = (freq_nom / reference_clock); /* :2977 β #DE if 0 */
The value is copied verbatim from the VBIOS FirmwareInfo table
(usMemoryReferenceClock) at amdgpu_atombios.c:659-660 β with no zero
fixup, in contrast to the neighboring pll_out_min fields that do get
== 0 β 64800 corrections (:642-643, :668-670). A crafted VBIOS with
usMemoryReferenceClock == 0 plus any parseable ASIC_InternalSS_Info
header (needed for caps_mclk_ss_support, ci_dpm.c:6052-6056, which gates
the divide) triggers the division at driver enable time.
freq_nom is memory_clock * 2|4 * (1 << post_div) and cannot be zero
(mclk == 0 rejected at ci_dpm.c:3480-3481), so zero reference clock is an
unconditional #DE β panic during
ci_dpm_enable β ci_populate_all_memory_levels β ci_populate_single_memory_level
β ci_calculate_mclk_params (called at ci_dpm.c:3107), i.e. at boot/bind
and on every resume.
Note the sibling ci_calculate_sclk_params only ever multiplies by the
SPLL reference clock β the mpll path is the only reference-clock divide
in this file. (For completeness: ci_program_display_gap divides by
refresh_rate, but that is guarded 0β60 at ci_dpm.c:2133-2134.)
Verification narrative
- Guest lacks any AMD ASIC β kernel path unexecutable β inconclusive; module presence verified (amdgpu.ko loads).
- The shared
ci_ss_div0.cexecuted on the guest demonstrates sink [C]: the exactfreq_nom / reference_clockdivision withusMemoryReferenceClock = 0(run.log). - Twin of si_dpm DF-3613.
Fix
fix.diff returns -EINVAL from ci_calculate_mclk_params when the mpll
reference clock is zero (SS setup cannot be computed); enable then fails
cleanly instead of panicking. Not testable on this guest.
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.diff fails enable cleanly on zero reference clock instead of panicking; not testable without AMD hardware.
fix.diff; no AMD ASIC on guest
Confirmed kernel references
Detail
Exploit chain
crafted VBIOS -> driver bind/resume -> integer #DE in kernel thread -> panic (DoS). No memory-corruption path.
Evidence (decisive lines)
run.log sink [C] block; amdgpu_atombios.c:659-660 contrast with the pll_out_min zero-fixups at :642/:668 in VERDICT.md.
PoC changes
shared binary with DF-3621; sink [C] is the DF-3622-specific demonstration
Verified recommended fix
Return -EINVAL from ci_calculate_mclk_params when adev->clock.mpll.reference_freq == 0 (see fix.diff), or zero-fixup usMemoryReferenceClock in amdgpu_atombios_get_clock_info like pll_out_min.
Verdict
Source-certain kernel divide-by-zero: ci_calculate_mclk_params (ci_dpm.c:2977) divides freq_nom by adev->clock.mpll.reference_freq, which amdgpu_atombios_get_clock_info stores verbatim from FirmwareInfo.usMemoryReferenceClock (amdgpu_atombios.c:659-660) with no zero fixup. A crafted VBIOS with zero usMemoryReferenceClock plus a parseable ASIC_InternalSS_Info header (to set caps_mclk_ss_support, ci_dpm.c:6052-6056, gating the divide) yields an unconditional #DE panic at ci_dpm_enable (memory-level population, ci_dpm.c:3107) on boot and resume. Runtime inconclusive: no AMD ASIC on the guest; the trapping arithmetic demonstrated by the shared ci_ss_div0.c (run.log sink [C]).
No comments yet.