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

Inverted error check at cypress_dpm_init:2059-2064 β€” ATOM engine-PLL reference divider used only on FAILURE (consuming uninitialized stack dividers), default used on success (cypress twin of DF-3976)

Summary

'if (ret) pi->ref_div = dividers.ref_div + 1; else pi->ref_div = default;' - on every board where the ATOM call SUCCEEDS (normal case) the computed divider is discarded and ref_div hardcoded; on failure the branch consumes the uninitialized stack dividers. Sink: MPLL lock-time programming - wrong memory-PLL lock timings on functional hardware, garbage-derived when the call fails. Upstream carries the identical inverted condition (checked vs torvalds master) - same basis as the btc twin DF-3976. One-token invert fix.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-4119 Β· 6 files
FileTypeDescriptionSize
README.md β€” 1.2 KB ↓ raw
VERDICT.md β€” 1.8 KB ↓ raw
fix.diff β€” 514 B view raw
env.txt β€” 583 B view raw
manifest.json β€” 873 B view raw
verdict.json β€” 2.0 KB view raw

DF-4119 β€” Inverted error check in cypress_dpm_init: ATOM engine-PLL reference divider used only on FAILURE (twin of DF-3976) ===================================================================== File: sys/dev/drm/radeon/cypress_dpm.c:2059-2064 β€” pass 2 (GLM 5.3).

ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
                     0, false, &dividers);
if (ret)                                   /* inverted (DF-3976 twin) */
    pi->ref_div = dividers.ref_div + 1;   /* uninit stack on failure */
else
    pi->ref_div = R600_REFERENCEDIVIDER_DFLT;  /* default on SUCCESS */
  • Normal hardware (call SUCCEEDS): computed divider discarded, ref_div hardcoded to 4.
  • Failing call: dividers (cypress_dpm.c:2029, stack) is consumed uninitialized -> garbage pi->ref_div.
  • Sink: rv770_dpm.c:815 MPLL_LOCK_TIME(R600_MPLLLOCKTIME_DFLT * pi->ref_div) and engine-speed parameter programming -> wrong memory PLL lock timings (functional, not memory-unsafe).
  • Upstream Linux master carries the same inverted condition in cypress_dpm.c AND btc_dpm.c (verified against torvalds/linux 2026-09-18); btc twin filed as DF-3976. Hardware-gated; no security-relevant memory sink; Low. FIX: fix.diff β€” if (!ret) (one line).
VERDICT.md
↓ download raw

DF-4119 VERDICT β€” inverted ref_div error check in cypress_dpm_init

STATUS: inconclusive (runtime hardware-gated); source certain, verified against upstream. impact: none (functional; wrong PLL lock timings / uninitialized-stack-derived value programmed to hardware). confidence: certain.

CHAIN: * cypress_dpm.c:2059-2064 β€” if (ret) pi->ref_div = dividers.ref_div+1; else pi->ref_div = R600_REFERENCEDIVIDER_DFLT; * struct atom_clock_dividers dividers; at :2029 is UNINITIALIZED stack; radeon_atom_get_clock_dividers does not fully populate it on failure => the failure branch consumes garbage (also an uninitialized-read defect, stack-info flows only into a register value programmed to the GPU, never to userspace). * The success branch (normal hardware) discards the ATOM-computed divider and hardcodes 4. * Sink: pi->ref_div at rv770_dpm.c:815 (MPLL_LOCK_TIME(R600_MPLLLOCKTIME_DFLT * pi->ref_div) inside rv770's memory-PLL timing programming, shared by this dispatch). * Upstream comparison (2026-09-18, torvalds/linux master): cypress_dpm.c and btc_dpm.c BOTH carry if (ret) β€” upstream-shared defect, exactly like the basis on which DF-3976 (btc twin) was filed. DragonFly import (FreeBSD radeon port) inherits it.

FIX: fix.diff β€” invert to if (!ret). fix_status not_testable (no hardware to validate programming against).

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

One-line fix authored; validation requires evergreen hardware absent from the audit guest.

fix.diff
↓ fix.diffper-fix-DF-4119

Confirmed kernel references

Detail

Evidence (decisive lines)

VERDICT.md; fix.diff (one-line inversion); env.txt

PoC changes

No seed PoC; hardware-gated.

Verified recommended fix

Invert the check to if (!ret) (fix.diff).

Verdict

Source certain, upstream-verified, runtime hardware-gated. cypress_dpm.c:2059-2064 uses the ATOM-computed engine-PLL reference divider only when radeon_atom_get_clock_dividers FAILS (consuming the uninitialized stack dividers declared at :2029) and hardcodes R600_REFERENCEDIVIDER_DFLT (4) on success β€” inverted. Sink: pi->ref_div at rv770_dpm.c:815 MPLL_LOCK_TIME(R600_MPLLLOCKTIME_DFLT * pi->ref_div) and engine-speed parameter programming: wrong memory-PLL lock timings on all functional hardware, garbage-derived timings when the ATOM call fails. Upstream Linux master carries the identical inverted condition in cypress_dpm.c and btc_dpm.c (checked 2026-09-18), the same basis on which the btc twin DF-3976 was filed. Functional/uninitialized-stack-read-into-hw-programming defect; no kernel memory-safety sink.