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

Inverted error check at btc_dpm_init:2602-2607 β€” ATOM-computed PLL reference divider used only when radeon_atom_get_clock_dividers FAILS (default used on success)

Summary

'if (ret) pi->ref_div = computed; else pi->ref_div = default;' - success discards the computed divider and takes the default; failure programs ref_div=1 (no uninit read - callee memsets), shrinking MPLL lock time 12x. Correct pattern exists in ni_dpm.c. Hardware stability only. One-token fix.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-3976 Β· 5 files
FileTypeDescriptionSize
README.md β€” 1.4 KB ↓ raw
VERDICT.md β€” 1.1 KB ↓ raw
verdict.json β€” 1.8 KB view raw
manifest.json β€” 470 B view raw
fix.diff β€” 312 B view raw

DF-3976 β€” Inverted error check in btc_dpm_init: computed PLL reference divider used only when radeon_atom_get_clock_dividers FAILS

  • File: sys/dev/drm/radeon/btc_dpm.c:2602-2607
  • Class: CWE-670 wrong logic (Info) β€” family: DF-3652 (ci inverted return). Functional/hardening, no memory-safety impact.

Code

ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
                     0, false, &dividers);
if (ret)
    pi->ref_div = dividers.ref_div + 1;   /* used on FAILURE */
else
    pi->ref_div = R600_REFERENCEDIVIDER_DFLT;  /* default on SUCCESS */

radeon_atom_get_clock_dividers() returns 0 on success; on failure it has already memset dividers to zero (radeon_atombios.c:2838), so the failure arm programs pi->ref_div = 1, and the success arm discards the computed dividers.ref_div. Compare the correct pattern in the same tree (ni_dpm.c:2015-2020: if (ret) return ret; then use dividers).

Impact

pi->ref_div feeds MPLL lock-time programming (rv770_dpm.c:815, MPLL_LOCK_TIME(R600_MPLLLOCKTIME_DFLT * pi->ref_div)): on an ATOM command failure the lock time is programmed 12x too short (ref_div=1 vs default 12) β€” marginal memory-clock PLL locking / display instability. No memory-safety impact (dividers is stack memory but pre-zeroed by the callee, so no uninitialized read reaches it). Info severity, matching DF-3652's treatment of the analogous inverted return.

VERDICT.md
↓ download raw

VERDICT β€” DF-3976

status: inconclusive (hardware-gated Info-severity hardening finding; source-level certainty: certain about the inversion)

The inversion is self-evident against the sibling pattern in ni_dpm.c:2015-2020 and against radeon_atom_get_clock_dividers' contract (returns 0 on success; memsets dividers at radeon_atombios.c:2838 before any failure return). I verified there is no uninitialized-stack read here (the callee zeroes the struct first), which is why this is CWE-670 Info and not CWE-457: the only consequence is pi->ref_div = 0 + 1 = 1 on the failure arm and a discarded computed value on the success arm, feeding MPLL_LOCK_TIME at rv770_dpm.c:815.

No runtime verification possible (no radeon GPU in the guest). fix.diff flips the condition to match the ni pattern.

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

fix.diff authored (condition flip); not runtime-testable without hardware.

findings/poc/DF-3976/fix.diff
↓ fix.diffper-fix-DF-3976

Confirmed kernel references

Detail

Evidence (decisive lines)

README.md code excerpt; ni_dpm.c:2015-2020 shows the correct pattern

PoC changes

No PoC (Info-severity logic inversion; nothing to reproduce without hardware).

Verified recommended fix

Invert the condition: use dividers.ref_div + 1 on success (!ret), default on failure.

Verdict

btc_dpm_init:2602-2607 uses the ATOM-computed ref_div only on the FAILURE arm of radeon_atom_get_clock_dividers and the hardcoded default on success β€” the condition is inverted relative to the ni_dpm.c:2015-2020 pattern. No uninit read (callee memsets dividers, radeon_atombios.c:2838); impact is a wrong pi->ref_div (1 on failure) feeding MPLL lock-time programming (rv770_dpm.c:815) β€” hardware-stability only. Info severity per DF-3652 precedent for inverted returns. Hardware-gated: not runtime-testable in the guest.