32-bit arithmetic overflow in SMU7 fan-RPM math: 60 * crystal_clock_freq * 10000 wraps for 25/27 MHz VI reference clocks, skewing reported fan speed (hwmon fan1_input/fan1_target) and the programmed TACH target by a constant ~7.09x (DF-4761 vega10 twin)
Summary
Both RPM directions evaluate the constant product in u32 - for SMU7's 25/27 MHz xclk the product is 1.5e10 and wraps before the division: reported RPM wrong and the TACH TARGET_PERIOD short by exactly 7.09x for every request. Telemetry/hw-reliability only. Guest demo of the exact expressions; kernel path hw-gated. u64-cast fix (same as DF-4761).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4892 Β· 6 files| File | Type | Description | Size | |
|---|---|---|---|---|
| rpm_wrap_demo.c | β | 2.2 KB | view raw | |
| build.sh | β | 210 B | view raw | |
| run.sh | β | 131 B | view raw | |
| run.log | β | 1.7 KB | view raw | |
| VERDICT.md | β | 2.5 KB | β raw | |
| verdict.json | β | 2.6 KB | view raw |
DF-4892 VERDICT β arithmetic defect certain; kernel path untested (no SMU7 hardware on guest)
Bottom line
smu7_thermal.c:100 and :273 compute 60 * crystal_clock_freq * 10000 in
u32 before dividing. For SMU7 parts amdgpu_asic_get_xclk() returns
spll.reference_freq = 25000/27000 kHz (vi.c:326-349), so the product is
1.5e10/1.62e10 and wraps to 2115098112/3315098112 β a factor-of-~7.09 error
that propagates BOTH to the RPM reported via hwmon fan1_input/fan1_target
(amdgpu_pm.c:1204/:1266) and to the TACH TARGET_PERIOD programmed by
fan1_target writes (amdgpu_pm.c:1297, root-only). Identical shape and
severity class to DF-4761 (vega10_thermal, Info).
Why untested
Verification of the kernel path requires Tonga/Fiji/Polaris/CZ hardware
(fan controller registers + tach); the QEMU guest has no AMD GPU, so the
PHM_READ_VFPF_INDIRECT_FIELD reads cannot execute. Per contract
(Low/Info findings) PoC verification is skipped. The arithmetic itself is
demonstrated by rpm_wrap_demo (run.log, executed on the guest userspace),
which evaluates the exact source expressions in u32 vs u64: wrap YES for
xclk=25000/27000, reported-RPM error up to 1.29e10x, TARGET_PERIOD off by a
constant 7.09x for every RPM request.
Verified-by-inspection details
8 * speedat :273 cannot overflow (speed <= fanInfo.ulMaxRPM from the atom pptable, u32 but small; speed==0 and min/max range checked at :260-266).smu7_thermal_get_temperature()(:286-302): 10-bit field, 0x200 sentinel, 511*1000 fits int β clean.smu7_thermal_set_temperature_range()(:311-338): inputs clamped to [0,255] degC before the /1000 writes; DIG_THERM_INTH/INTL/DPM fields fit β clean.- percent paths (:54-81, :195-225): u64 do_div math, outputs clamped β clean.
hwmgr->fan_ctrl_enabled = trueeven when the SMC StartFanControl message fails (:171-177) andsmu7_thermal_start_smc_fan_controlignores its return (:427-431) β thermal-correctness only, not security; noted, not filed.
Fix
u64-cast before the division at both sites (see README.md / finding fix block).
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.
(No fix.diff for this item: documented recommendation only - see Fix above.)
Fix verification
not_testablefix not built/validated: requires SMU7 hardware to exercise the fan-controller path; the one-line u64-cast fix is identical in shape to the DF-4761 fix and is arithmetically sufficient (demo's u64 column = correct values)
findings/poc/DF-4892/run.log u32 vs u64 columns
Confirmed kernel references
Detail
Evidence (decisive lines)
run.log: 'xclk=25000 u32: 2115098112 u64: 15000000000 wrap: YES' + TARGET_PERIOD 'off by 7.09x' rows; smu7_thermal.c:100/:273; vi.c:326-349; smu7_hwmgr.c:5086-5087; amdgpu_pm.c:1204/1266/1297
PoC changes
wrote rpm_wrap_demo.c evaluating the exact kernel expressions in u32 vs u64 (userspace arithmetic demo; kernel path hardware-gated)
Verified recommended fix
u64-cast the product before dividing at smu7_thermal.c:100 and :273: (uint64_t)60 * crystal_clock_freq * 10000 / ...
Verdict
DF-4761 twin confirmed by inspection: smu7_thermal.c:100 and :273 compute 60crystal_clock_freq10000 in u32; vi_get_xclk() returns 25/27 MHz-class reference_freq for SMU7 parts, so the product wraps (1.5e10 -> 2115098112) before the division, skewing both the hwmon-reported fan RPM and the programmed TACH TARGET_PERIOD by a constant ~7.09x. Info severity: telemetry/hw-reliability only (write path root-only), no memory safety. Kernel-path PoC not executed: the QEMU guest has no AMD GPU (no SMU7 fan controller), and Info findings are skipped per contract; arithmetic divergence demonstrated by the userspace demo (run.log) evaluating the exact source expressions in u32 vs u64.
No comments yet.