Divide-by-zero panic in iceland_thermal_setup_fan_table from unchecked VBIOS fan temperatures
Summary
iceland_thermal_setup_fan_table at iceland_smumgr.c:2122-2129: t_diff1=usTMed-usTMin, t_diff2=usTHigh-usTMed from VBIOS (process_pptables_v1_0.c:941-946 no monotonicity check). :2128 slope1=.../t_diff1, :2129 slope2=.../t_diff2. Crafted VBIOS usTMed==usTMin -> divide-by-zero #DE panic. Sibling of DF-1128/DF-1204/DF-1274/DF-1297/DF-1323. Fix: check t_diff1!=0 && t_diff2!=0.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-1323 Β· 11 files| File | Type | Description | Size | |
|---|---|---|---|---|
| trigger.c | trigger-source | function-level harness: iceland smumgr fan table t_diff div-by-zero | 2.5 KB | view raw |
| fix.diff | suggested-fix | git-apply-able diff that adds the guard verified at the function level | 974 B | view raw |
| build.sh | build-script | exact build: cc -O2 -Wall -o trigger trigger.c | 125 B | view raw |
| run.sh | run-script | exact run: ./trigger | 111 B | view raw |
| run.log | run-log | decisive harness output BEFORE-FIX + AFTER-FIX | 177 B | view raw |
| fix_build.log | build-log | single batched patched-kernel build (rc=0); proves all 15 fixes compile | 5.6 MB | β download |
| env.txt | environment | uname, guest cc version, patch list | 500 B | view raw |
| VERDICT.md | verdict | narrative analysis: mechanism, why not live, fix | 1.9 KB | β raw |
| README.md | readme | human-facing reproduce instructions | 2.1 KB | β raw |
| ../fix_build_combined.log | build-log | Combined 41-finding kernel build (rc=0, -Werror clean) | 5.6 MB | β download |
| ../fix_build_summary.txt | build-summary | Summary of the combined 41-finding kernel build | 826 B | view raw |
DF-1323 β iceland_thermal_setup_fan_table divide-by-zero (t_diff1 / t_diff2)
Summary
Guard: if (t_diff1 == 0 || t_diff2 == 0) { disable microcode fan control; return 0; } before computing slope1/slope2.
How to reproduce
This bug lives in a device driver not reachable from the booted QEMU guest as
an unprivileged user (maxx) because the required hardware is absent (AMD GPU,
RAID HBA, sound PCI, AMD SCSI) or the trigger requires a malicious hypervisor
(virtio_net, virtio_scsi). The bug is reproduced at the function level by
porting the cited code path into a userspace harness that drives it with the
attacker-controlled inputs the original code fails to validate.
Build
cc -O2 -Wall -o trigger trigger.c
Run
./trigger
Expected
- BEFORE-FIX section shows the bug signature (SIGFPE for div-by-zero, OOB index report for overflows, wraparound count for underflows, over-read length for info leaks).
- AFTER-FIX section shows the guard from
fix.diffcleanly rejecting the attacker input.
The same harness was compiled and run on the patched single-fix kernel
(DragonFly 6.5-DEVELOPMENT #1) β output is identical because the harness
intentionally demonstrates both the unpatched and patched function logic side
by side, and the userspace behavior of those branches is independent of the
kernel. The patched kernel build (fix_build.log) confirms all 15 fix.diffs
compile cleanly in the real kernel / module context.
Impact classification
dos β gated by absent hardware / malicious-hypervisor precondition on
this guest; live trigger from maxx is not possible. See VERDICT.md for
the threat-model analysis.
Files
trigger.cβ function-level harness porting the cited code path.fix.diffβ git-apply-able unified diff againstsys/.build.sh/run.shβ exact repro commands.run.logβ decisive harness output (BEFORE-FIX + AFTER-FIX).fix_build.logβ patched kernel build log (proves all 15 fixes compile).VERDICT.mdβ full narrative analysis.manifest.jsonβ machine-readable catalog.
Host has no gcc; harnesses built in guest as maxx with cc (DragonFly gcc 8.3).
DF-1323 β VERDICT
REPRODUCED at the function level (impact: dos).
Mechanism
iceland_thermal_setup_fan_table() computes t_diff1 = usTMed - usTMin and t_diff2 = usTHigh - usTMed from VBIOS-supplied fan-control parameters (process_pptables_v1_0.c:941-946). slope1 at :2128 divides by t_diff1; slope2 at :2129 divides by t_diff2. No monotonicity or zero check exists. duty100==0 is guarded at :2117 but t_diff is not. A crafted/corrupt VBIOS where usTMed==usTMin or usTHigh==usTMin causes #DE (SIGFPE) panic.
Why not live-reproduced on the QEMU guest
AMD GPU (iceland/Tonga/Fiji) hardware is absent from the QEMU guest; the amdgpu module loads only when matching PCI hardware probes. The bug fires at adapter-init / fan-table-setup time, driven by VBIOS, not by any unprivileged-guest-user syscall.
Recommended fix
After computing t_diff1/t_diff2 in iceland_thermal_setup_fan_table(), check 'if (t_diff1 == 0 || t_diff2 == 0)' and if so, clear PHM_PlatformCaps_MicrocodeFanControl and return 0 β mirroring the existing duty100==0 guard.
Kernel references (confirmed during verification)
- sys/dev/drm/amd/powerplay/smumgr/iceland_smumgr.c:2122-2123 (t_diff1/t_diff2 computed)
- sys/dev/drm/amd/powerplay/smumgr/iceland_smumgr.c:2128-2129 (unguarded divisions)
- sys/dev/drm/amd/powerplay/smumgr/iceland_smumgr.c:2117-2121 (existing duty100 guard as model)
Build/run
- Build harness:
cc -O2 -Wall -o trigger trigger.c - Run harness:
./trigger - Apply fix:
cd /usr/src && patch -p1 < fix.diff - Build single-fix kernel:
make -j6 nativekernel KERNCONF=X86_64_GENERIC(validated β seefix_build.log; all 15 fixes compile cleanly in one batched build, rc=0).
Tested kernels
- baseline:
DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64 - patched :
DragonFly 6.5-DEVELOPMENT #1: Mon Jul 20 21:51:01 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64
Fix verification
fixedVALIDATED via batched single-fix kernel build: the amdgpu module (containing iceland_smumgr.c) compiles cleanly with the fix applied (rc=0). Baseline #0 unpatched. The harness BEFORE-FIX section reproduces the SIGFPE; AFTER-FIX shows the guard returning cleanly β that before/after delta is the behavioral proof. No live trigger on this guest because the amdgpu module attaches only on AMD Iceland GPU HW which is absent.
baseline #0 amd_smumgr.c BEFORE-FIX: SIGFPE β integer divide by zero in slope1/slope2. patched #1 cc6aa06b: same harness AFTER-FIX: t_diff==0 detected, return 0; amdgpu module build rc=0.
Confirmed kernel references
- s
- y
- s
- /
- d
- e
- v
- /
- d
- r
- m
- /
- a
- m
- d
- /
- p
- o
- w
- e
- r
- p
- l
- a
- y
- /
- s
- m
- u
- m
- g
- r
- /
- i
- c
- e
- l
- a
- n
- d
- _
- s
- m
- u
- m
- g
- r
- .
- c
- :
- 2
- 1
- 2
- 2
- s
- y
- s
- /
- d
- e
- v
- /
- d
- r
- m
- /
- a
- m
- d
- /
- p
- o
- w
- e
- r
- p
- l
- a
- y
- /
- s
- m
- u
- m
- g
- r
- /
- i
- c
- e
- l
- a
- n
- d
- _
- s
- m
- u
- m
- g
- r
- .
- c
- :
- 2
- 1
- 2
- 8
- s
- y
- s
- /
- d
- e
- v
- /
- d
- r
- m
- /
- a
- m
- d
- /
- p
- o
- w
- e
- r
- p
- l
- a
- y
- /
- s
- m
- u
- m
- g
- r
- /
- i
- c
- e
- l
- a
- n
- d
- _
- s
- m
- u
- m
- g
- r
- .
- c
- :
- 2
- 1
- 2
- 9
Detail
Exploit chain
none β pure divide-by-zero DoS class. No memory-corruption primitive; no escalation chain derivable.
Evidence (decisive lines)
BEFORE-FIX (amd_smumgr.c): SIGFPE β integer divide by zero in slope1/slope2 (VBIOS t_diff==0). AFTER-FIX: t_diff==0 detected, fan control disabled (return 0). Patched-kernel build (all 15 fixes) rc=0. See findings/poc/DF-1323/run.log and fix_build.log.
PoC changes
Wrote fresh trigger.c (amd_smumgr.c) harness porting the slope computation with attacker-supplied usT* values, plus build.sh/run.sh/README.md/VERDICT.md/manifest.json and fix.diff.
Verified recommended fix
fix.diff adds 'if (t_diff1 == 0 || t_diff2 == 0) { phm_cap_unset(...MicrocodeFanControl); return 0; }' after the t_diff2 computation, mirroring the existing duty100==0 guard. Matches finding proposal. Full diff in findings/poc/DF-1323/fix.diff.
Verdict
REPRODUCED at function level. iceland_thermal_setup_fan_table() at iceland_smumgr.c:2122-2123 computes t_diff1=usTMed-usTMin and t_diff2=usTHigh-usTMed from VBIOS, then divides at :2128-2129 without zero check. The duty100==0 guard at :2117 is the model. A crafted/corrupt VBIOS with usTMed==usTMin causes #DE (SIGFPE) panic at adapter-init. Harness amd_smumgr.c ports the slope computation and observes SIGFPE on the vulnerable path; fixed path returns 0 cleanly. AMD Iceland GPU is absent from the QEMU guest.
No comments yet.