# DF-4931 VERDICT

**Status: reproduced (logic level, verbatim userland replica on the audit guest);
kernel trigger hardware-gated (no RV740 GPU in the guest — 0 PCI 0x1002 devices),
per the DF-4857/DF-4858 convention for this driver family.**

## The defect

`rv740_populate_sclk_value` and `rv740_populate_mclk_value` compute the
spread-spectrum depth `clk_v` with 32-bit unsigned numerators whose operands are
VBIOS-derived:

- sclk — `sys/dev/drm/radeon/rv740_dpm.c:166`
  `u32 clk_v = 4 * ss.percentage * fbdiv / (clk_s * 10000);`
  `ss.percentage` is u16 from the VBIOS `ASIC_InternalSS_Info` table
  (`radeon_atombios.c:1546` area); `fbdiv` is the engine PLL feedback divisor
  computed at `:144-146` and is inherently large (~1.8e7 for a 740 MHz engine
  clock — the accepted DF-4857 pack's "ok-mode" control measured fbdiv=18204444
  on the sibling rv730 path).
- mclk — `sys/dev/drm/radeon/rv740_dpm.c:259-260`
  `u32 clk_v = 0x40000 * ss.percentage * (whole_fb_div + (frac_fb_div / 8)) / (clk_s * 10000);`
  `whole_fb_div`/`frac_fb_div` come from the AtomBIOS memory-PLL computation
  (`:205-208`).

C evaluates the full numerator product (left-to-right, both operands u32)
before dividing, so any product > 2^32-1 wraps. Thresholds with ordinary
values:

- sclk: wraps whenever `percentage * fbdiv > 2^30`; with fbdiv ≈ 3.6e6 that is
  **percentage > 59, i.e. any engine SS deeper than ~0.6%** (in 0.01% units).
- mclk: wraps whenever `percentage * whole_fb_div > 16384`; with fb ≈ 200 that
  is **percentage > 82 (~0.8%)**.

The wrapped quotient then lands in the 26-bit `CLK_V` field of
`CG_SPLL_SPREAD_SPECTRUM_2` (`:172-173`, mask `0x3ffffff` — rv740d.h:108) and the
26-bit `CLKV` field of `MPLL_SS1` (`:262-263`, rv740d.h:112), while the *correct*
value also fits the field — so the wrap is completely silent: SSEN gets armed
(`:170`) with a wrong (often near-zero) depth on every SS-enabled board whose
VBIOS SS percentages cross the (very low) threshold.

This is a sibling of the accepted DF-4858 (rv730 wrong-variable store —
different mechanism, same terminal effect: SS enabled with wrong/zero depth) and
is arithmetic-adjacent to DF-1992 (div-by-zero in the same blocks — different
defect class: this is CWE-190 wrap, not CWE-369; DF-1992 is NOT re-reported
here). The rv740 stores themselves are correct (rv740_dpm.c:262-266 programs
CLKV into mpll_ss1 and CLKS into mpll_ss2 — the DF-4858 typo shape does NOT
exist in rv740).

## Reproduction (run.log, audit guest, cc 8.3)

Baseline = kernel arithmetic verbatim:

| case | numerator exact | u32 wrapped | programmed clk_v | correct clk_v |
|---|---|---|---|---|
| S1 sclk 6% SS | 8,621,623,200 | 31,688,608 | **0** (SSEN, zero depth) | 191 |
| S2 sclk 30% SS | 43,108,116,000 | 158,443,040 | 3 | 957 |
| M1 mclk 2% SS | 10,485,760,000 | 1,895,825,408 | 227 | 1258 |
| M2 mclk 5% SS | 26,214,400,000 | 444,596,224 | 53 | 3146 |

All four exact values fit the 26-bit field → silent misprogramming; exit 98.
Fixed build (`-DFIX_DF4931`): every programmed depth equals the 64-bit exact
value; exit 0.

## Impact ceiling

Wrong SMC payload contents for GPU firmware only: spread spectrum armed with a
wrong depth (engine and/or memory clock). Fixed-size register words, no OOB, no
kernel memory corruption, no pointer involvement, no escalation chain. Realistic
worst case is mclk/sclk instability or a GPU wedge (functional DoS of the
graphics stack) on SS-enabled RV740-family boards. Same threat position as
DF-1992 (VBIOS-supplied values; no unprivileged write path — DPM tables build at
init / root-driven power-state transitions).

## Fix validation

`fix.diff` (64-bit numerators, `u64 clk_v`/`(u64)` casts, field-masked stores):
applied to the guest's `/usr/src` (patched rv740_dpm.c md5
`3892509a4dee23072ec4bd42e5a68b72`, pristine `98e600ce…`), `radeon.ko` rebuilt
under `-Werror` — compile+link OK (`radeon_module_build.log`, rv740_dpm.o in the
link line). Harness fixed mode matches exact math. Guest source then reverted
(md5 re-verified pristine). No .orig leftovers.

## 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.
