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

Integer divide-by-zero on zero MPLL/SPLL reference clock in ci_calculate_mclk_params (usMemoryReferenceClock stored unchecked)

Summary

rdev->clock.mpll.reference_freq is stored unchecked from FirmwareInfo; with 0, ci_dpm.c:2872 (freq_nom / reference_clock) faults directly and :3228 faults via clk_s==0. Panic at DPM init with SS support enabled (caps set whenever the SS table header parses). Guest harness proved 300000/0 -> SIGFPE. Twin of DF-3613/DF-3622.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-3648 Β· 12 files
FileTypeDescriptionSize
README.md doc 801 B ↓ raw
VERDICT.md doc 2.7 KB ↓ raw
fix.diff doc 842 B view raw
env.txt doc 799 B view raw
verdict.json doc 2.9 KB view raw
manifest.json doc 1.4 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
README.md doc
↓ download raw

DF-3648 β€” Integer divide-by-zero on zero MPLL/SPLL reference clock in ci_calculate_mclk_params (usMemoryReferenceClock stored unchecked)

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: [C]

./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).

VERDICT.md doc
↓ download raw

DF-3648 β€” verdict narrative

Finding

Integer divide-by-zero on zero MPLL/SPLL reference clock in ci_calculate_mclk_params (usMemoryReferenceClock stored unchecked)

Kernel references

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-3613 (si) / DF-3622 (amdgpu ci). radeon_atombios_get_clock_info stores usMemoryReferenceClock (DCE4+ path, radeon_atombios.c:1216-1218; CI is DCE8) into rdev->clock.mpll.reference_freq with no sanity check; a crafted FirmwareInfo with that field 0 leaves reference_freq == 0. ci_calculate_mclk_params reads it (ci_dpm.c:2865) and divides tmp = freq_nom / reference_clock (2872) inside the caps_mclk_ss_support block - #DE panic. The sclk path is affected indirectly: clk_s = reference_clock * 5 / (ref_div * ss.rate) evaluates to 0 when reference_clock == 0, and the very next line divides by it (clk_v = ... / (clk_s * 10000), ci_dpm.c:3228) - div-by-zero again. On-guest harness section [C] proved 300000/0 faults with SIGFPE. Kernel path unreachable on this GPU-less guest; inconclusive overall.

Exploitability

Crafted VBIOS whose FirmwareInfo reports usMemoryReferenceClock (or the pre-DCE4 usReferenceClock) as 0, with the SS info table present so caps_*_ss_support is set -> u32 divide by zero at DPM table population -> panic at load. DoS only.

Skip SS programming (or fail DPM init) when rdev->clock.{mpll,spll}.reference_freq is 0. 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_testable
baseline no→ patch + rebuild →patched clean

Fix 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).
↓ fix.diffper-fix-DF-3648

Confirmed kernel references

Detail

Exploit chain

Crafted VBIOS whose FirmwareInfo reports usMemoryReferenceClock (or the pre-DCE4 usReferenceClock) as 0, with the SS info table present so caps_*_ss_support is set -> u32 divide by zero at DPM table population -> panic at load. DoS only.

Evidence (decisive lines)

VERDICT.md (full source trace); harness.c + run.log/run.2.log section [C] (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

Skip SS programming (or fail DPM init) when rdev->clock.{mpll,spll}.reference_freq is 0.

Verdict

Source-certain div-by-zero, radeon/ci twin of DF-3613 (si) / DF-3622 (amdgpu ci). radeon_atombios_get_clock_info stores usMemoryReferenceClock (DCE4+ path, radeon_atombios.c:1216-1218; CI is DCE8) into rdev->clock.mpll.reference_freq with no sanity check; a crafted FirmwareInfo with that field 0 leaves reference_freq == 0. ci_calculate_mclk_params reads it (ci_dpm.c:2865) and divides tmp = freq_nom / reference_clock (2872) inside the caps_mclk_ss_support block - #DE panic. The sclk path is affected indirectly: clk_s = reference_clock * 5 / (ref_div * ss.rate) evaluates to 0 when reference_clock == 0, and the very next line divides by it (clk_v = ... / (clk_s * 10000), ci_dpm.c:3228) - div-by-zero again. On-guest harness section [C] proved 300000/0 faults with SIGFPE. Kernel path unreachable on this GPU-less guest; inconclusive overall.