β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-4153

amdgpu_atombios_get_clock_info stores VBIOS reference clocks unchecked β€” zero reference_freq reaches PLL/SS divisions (#DE panic) (amdgpu twin of DF-3742)

Summary

The three reference-clock u16 fields are copied into adev->clock with no zero check while neighboring limits ARE defaulted. Zero propagates to amdgpu_pll.c DIV_ROUND_CLOSEST(x, den=0) on every mode set and to the SS step_size denominator in atombios_crtc - #DE kernel panic; DPM-side consumers propagate further (no downstream zero check anywhere, grep verified). Zero-default fix like the existing limit fixups.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-4153 Β· 4 files
FileTypeDescriptionSize
vbios_mutator.py trigger Illustrative trigger (hardware-gated) 1.5 KB view raw
VERDICT.md verdict Full source-trace analysis 3.0 KB ↓ raw
fix.diff suggested-fix Default ppll/spll/mpll reference_freq to 2700/10000/10000 (10kHz units) when the VBIOS value is 0, matching the existing pll_out_min fixups. 1.4 KB view raw
env.txt environment Guest uname + pciconf hardware-gate proof 980 B view raw
VERDICT.md verdict Full source-trace analysis
↓ download raw

DF-4153 β€” Zero VBIOS reference clocks stored unchecked reach PLL/SS divisions (#DE panic) β€” amdgpu twin of DF-3742

File: sys/dev/drm/amd/amdgpu/amdgpu_atombios.c (pass 2)

Reproduced?

No β€” hardware-gated (no AMD GPU on the audit guest; see env.txt). Established at source level.

Source trace

amdgpu_atombios_get_clock_info() copies three BIOS-provided reference clocks with no zero/validity check β€” unlike the neighboring limits which are defaulted (pll_out_min == 0 β†’ 64800 at :610-611, :642-643, :669-670, max_pixel_clock == 0 β†’ 40000 at :708-709):

592:  ppll->reference_freq = le16_to_cpu(firmware_info->info.usReferenceClock);
632:  spll->reference_freq = le16_to_cpu(firmware_info->info_21.usCoreReferenceClock);
659:  mpll->reference_freq = le16_to_cpu(firmware_info->info_21.usMemoryReferenceClock);

ppll[0..AMDGPU_MAX_PPLL-1] are populated by the struct copy at :628-629, and adev->pm.current_sclk/mclk derive from the same table (:677-719).

Downstream divisions with no intervening zero check (grep for reference_freq == 0 across sys/dev/drm/amd/amdgpu/ finds nothing):

  1. Mode set / PLL compute β€” amdgpu_pll.c:187 den = pll->reference_freq (for pixel PLLs = ppll[].reference_freq), then amdgpu_pll.c:92 *fb_div = DIV_ROUND_CLOSEST(nom * *ref_div * post_div, den) β†’ integer division by zero (gcd(nom,0) at :50 is safe β€” the libkern while (b) loop skips β€” but den survives as 0 to :92). Every CRTC mode program via amdgpu_pll_compute reaches this.
  2. Spread-spectrum step size β€” atombios_crtc.c:876 and :879: step_size = (...) / (125 * 25 * pll->reference_freq / 100); β€” the denominator collapses to 0 when reference_freq == 0 β†’ #DE during amdgpu_atombios_crtc_program_pll when SS is enabled (SS comes from the same VBIOS, amdgpu_atombios_get_asic_ss_info).
  3. DPM-side consumers (si_dpm.c:5257/5379, ci_dpm.c:2122/2970/3313, cik.c:842-851, vi.c:328-342) propagate the zero into clock conversions with further divides.

Sibling (noted, different file): amdgpu_atomfirmware.c:290/313 sets the same fields from atomfirmware tables, also unchecked.

Trigger: crafted VBIOS with usReferenceClock == 0 (or the info_21 fields for sclk/mclk paths) β€” driver attach succeeds; first mode set (or DPM init) faults with a kernel divide error β†’ local DoS / panic. This is exactly the pattern accepted as Medium for radeon (DF-3742).

Verdict

INCONCLUSIVE (hardware-gated / not reachable on the audit guest). Source-certain: unchecked zero reaches at least two concrete division sites. Severity Medium (crafted-VBIOS local DoS via panic; hardware-gated delivery).

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_testable
baseline no→ patch + rebuild →patched clean

Fix not testable: single-fix kernel build cannot exercise adv(4)/amdgpu paths without the respective hardware on the guest.

fix.diff authored post-verification from line-accurate source trace (VERDICT.md); env.txt documents absent hardware.
↓ fix.diffper-fix-DF-4153

Confirmed kernel references

Detail

Evidence (decisive lines)

VERDICT.md (division sites traced), fix.diff (zero-defaults), env.txt (guest has no AMD GPU).

PoC changes

Seed replaced with an honest hardware-gated trigger sketch/mutator; no runnable PoC exists for this defect class on the audit guest.

Verified recommended fix

Default ppll/spll/mpll reference_freq to 2700/10000/10000 (10kHz units) when the VBIOS value is 0, matching the existing pll_out_min fixups.

Verdict

INCONCLUSIVE (hardware-gated). amdgpu_atombios_get_clock_info stores usReferenceClock / usCoreReferenceClock / usMemoryReferenceClock into ppll/spll/mpll.reference_freq with no zero check (amdgpu_atombios.c:592,632,659) while neighboring limits ARE defaulted (e.g. :610, :708). Zero reaches unguarded divisions: amdgpu_pll.c:187->92 DIV_ROUND_CLOSEST(x, den=0) at every mode set, and atombios_crtc.c:876/879 ss step_size denominator (12525ref/100 == 0). amdgpu twin of DF-3742 (radeon, Medium).