Divide-by-zero panic in tonga_thermal_setup_fan_table from VBIOS fan temperatures (usTMed==usTMin or usTHigh==usTMed)
Summary
The function computes t_diff1/t_diff2 from values copied verbatim out of the VBIOS fan table (no distinctness/ordering validation) and divides by both for the slopes. Existing guards do not check the deltas. A crafted VBIOS with equal adjacent temperature points triggers a #DE kernel panic at DPM enable. Known DF-1274 covered only the SS rates; tonga was the missing member of the sibling-driver fan-div0 family (DF-1297/1323/1325/1345). VERIFIED: guest harness performs the identical division and faults SIGFPE rc=132. Guard-deltas fix (the accepted fiji shape).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3910 Β· 11 files| File | Type | Description | Size | |
|---|---|---|---|---|
| trigger_analysis.c | trigger-source | userspace demonstrator of the kernel index/pointer/division arithmetic | 2.1 KB | view raw |
| build.sh | build-script | cc build of the demonstrator | 65 B | view raw |
| run.sh | run-script | runs the demonstrator | 89 B | view raw |
| build.log | build-log | guest compiler output | 11 B | view raw |
| run.log | run-log | guest runtime output (decisive run) | 218 B | view raw |
| env.txt | environment | guest uname + pciconf (no AMD GPU / no MPT HBA) | 838 B | view raw |
| fix.diff | suggested-fix | git-apply-able unified diff | 664 B | view raw |
| fix_build.log | build-log | fix apply + nativekernel rebuild summary, rc=0 -Werror | 6.3 KB | view raw |
| VERDICT.md | verdict | full verification narrative | 2.1 KB | β raw |
| README.md | readme | human-readable summary | 1.7 KB | β raw |
| ../DF-3908/fix_kernel_full.log | build-log | full nativekernel build log shared from DF-3908 pack | 5.6 MB | β download |
DF-3910 β Tonga fan-table slope divide-by-zero (usTMed == usTMin) β kernel #DE panic
File: sys/dev/drm/amd/powerplay/smumgr/tonga_smumgr.c
Lines: 2502-2513 (tonga_thermal_setup_fan_table)
Severity: Medium (local DoS at GPU/DPM enable) β hardware-gated (Tonga/Fiji + crafted VBIOS fan table)
Class: base:dev / CWE-369 (divide-by-zero), pass 2 (the fan table β not covered by DF-1274, which fixed only SCLK/MCLK SS rates at :591/:883)
Build / Run
./build.sh && ./run.sh
Expected output
duty100=200 pwm_diff1=1234 usTMin=4000 usTMed=4000 -> t_diff1=0 evaluating (50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100 ... Illegal instruction (core dumped) <- SIGFPE == kernel #DE trigger rc=132 (42 == SIGFPE/#DE fault demonstrated)
(The userspace division raises SIGFPE exactly the way the kernel path raises a divide-error fault β panic. run.log on the guest shows the actual fault.)
Root cause
process_pptables_v1_0.c:941-986 copies usTMin/usTMed/usTHigh verbatim from
the VBIOS fan table with no distinctness check. tonga_thermal_setup_fan_table
computes t_diff1 = usTMed - usTMin (:2502-2503), t_diff2 = usTHigh - usTMed
(:2504-2505) and divides by both at :2512-2513 without a zero check. A crafted
VBIOS with usTMed == usTMin (or usTHigh == usTMed) panics the kernel during
DPM enable (MicrocodeFanControl cap set, fan present, duty100 != 0 β all
satisfied on real fan-equipped boards).
Fix
fix.diff adds the same guard the sibling drivers' fixes use (cf. DF-1297 ci,
DF-1323 iceland, DF-1325 fiji, DF-1345 polaris10): if either delta is zero,
unset PHM_PlatformCaps_MicrocodeFanControl and return 0. Validated in the
batch nativekernel rebuild: rc=0, -Werror clean (fix_build.log).
DF-3910 β Verification Verdict
Status: inconclusive (reproduced=0) Impact: none on guest (no AMD GPU); userspace harness faults exactly as predicted Confidence: certain (source-level; arithmetic fault demonstrated)
Finding
tonga_thermal_setup_fan_table() divides by VBIOS-supplied temperature
deltas with no zero check:
t_diff1 = usTMed - usTMin; tonga_smumgr.c:2502 t_diff2 = usTHigh - usTMed; :2504 slope1 = (50 + ((16*duty100*pwm_diff1)/t_diff1)) / 100; :2512 <-- div by 0 slope2 = (50 + ((16*duty100*pwm_diff2)/t_diff2)) / 100; :2513 <-- div by 0
usTMin/usTMed/usTHigh come straight from ATOM_Tonga_Fan_Table / ATOM_Fiji_Fan_Table (process_pptables_v1_0.c:941-946 / 978-982) with no validation. Guards present: MicrocodeFanControl cap (:2472), bNoFan (:2476), fan_table_start (:2482), duty100==0 (:2492) β none check the deltas.
Verification
- Source chain certain (above).
- Guest run (run.log): the identical expression with usTMed==usTMin raises SIGFPE ("Illegal instruction (core dumped)", rc=132) β the userspace analogue of the kernel #DE panic. Kernel-path execution requires Tonga/Fiji hardware (absent β env.txt), hence inconclusive, matching the DF-1274 precedent (the SCLK/MCLK SS div0 twin, poc status inconclusive).
Fix validation
Guard added after the t_diff2 computation: zero delta β unset
MicrocodeFanControl, return 0 (identical to the accepted fiji fix DF-1325).
Batch nativekernel rebuild on guest: tonga_smumgr.c compiled -Werror
clean, kernel rc=0 (fix_build.log). fix_status = fixed
(compile-validated).
Distinct from knowns
DF-1274 = spread-spectrum rates (speed_spectrum_rate==0) at :591/:883 β different inputs, different sites; fan-table slopes were not covered.
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
fixedfixed (compile-validated): fix.diff applied to clean guest /usr/src with the batch; nativekernel rebuild rc=0, 0 errors; tonga_smumgr.c compiled with -Werror (full log in DF-3908 pack, line 28191). Runtime re-test impossible on this guest (no AMD GPU).
fix_build.log (apply + compile lines + NK_DONE rc=0); run.log (SIGFPE on zero delta); full build log shared from DF-3908/fix_kernel_full.log.
Confirmed kernel references
Detail
Evidence (decisive lines)
run.log on guest: 'Illegal instruction (core dumped)' from the t_diff1==0 division; VERDICT.md source chain; fix_build.log (-Werror compile of patched file)
PoC changes
Pass-2 reviewer authored trigger/analysis + fix from source; harness built and run on the DragonFly guest (SIGFPE observed); fix compile-validated via full nativekernel rebuild.
Verified recommended fix
Guard t_diff1/t_diff2 == 0: unset PHM_PlatformCaps_MicrocodeFanControl and return 0 (identical to DF-1325 fiji fix).
Verdict
Source-certain divide-by-zero: tonga_thermal_setup_fan_table() divides by t_diff1=usTMed-usTMin / t_diff2=usTHigh-usTMed taken verbatim from the VBIOS fan table (process_pptables_v1_0.c:941-986, no distinctness validation); usTMed==usTMin gives #DE panic at DPM enable. Guest harness performs the identical division and faults with SIGFPE (rc=132), the exact userspace analogue; kernel path hardware-gated. DF-1274 covered only SCLK/MCLK SS rates; fan slopes are the uncovered twin (per-file twins DF-1297/1323/1325/1345).
No comments yet.