# DF-1151 — divide-by-zero in `ci_thermal_setup_fan_table` (radeon)

## Verdict
**NOT REPRODUCED** on this guest (defense-in-depth source bug confirmed; path
unreachable on the default GENERIC DragonFlyBSD kernel running in QEMU).
Real source-level defect; fix.diff authored.  This is the radeon-driver twin
of DF-1143 (the same defect exists in both `sys/dev/drm/radeon/ci_dpm.c` and
`sys/dev/drm/amd/amdgpu/ci_dpm.c`, which were forked from a common ancestor).

## Mechanism (source trace, bug confirmed real)
In `sys/dev/drm/radeon/ci_dpm.c:991`, `ci_thermal_setup_fan_table()` computes
the fan PWM slope from three VBIOS-supplied u16 temperatures:

```c
/* sys/dev/drm/radeon/ci_dpm.c:1018-1025 */
t_diff1 = rdev->pm.dpm.fan.t_med - rdev->pm.dpm.fan.t_min;   /* L1018 */
t_diff2 = rdev->pm.dpm.fan.t_high - rdev->pm.dpm.fan.t_med;  /* L1019 */
...
slope1 = (u16)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100); /* L1024 */
slope2 = (u16)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100); /* L1025 */
```

The temperatures are populated directly from the AtomBIOS PowerPlay table
(`sys/dev/drm/radeon/r600_dpm.c:897-899`):
```c
rdev->pm.dpm.fan.t_min  = le16_to_cpu(fan_info->fan.usTMin);
rdev->pm.dpm.fan.t_med  = le16_to_cpu(fan_info->fan.usTMed);
rdev->pm.dpm.fan.t_high = le16_to_cpu(fan_info->fan.usTHigh);
```

A VBIOS image with `usTMin == usTMed` or `usTMed == usTHigh` makes the kernel
divide by zero at L1024/L1025 → `#DE` → panic during DPM enable.

## Why it does NOT reproduce on this guest
Same reasons as DF-1143:
1. **radeon driver is not in the GENERIC kernel.** `grep radeon
   sys/config/X86_64_GENERIC` is empty; the driver ships only as
   `radeon.ko` (and ~150 radeonkmsfw_*.ko firmware modules).
   `nm /boot/kernel/kernel.debug | grep -ciE 'radeon|amdgpu'` ⇒ **0**.
   No radeon module is loaded on the running guest.
2. **No AMD GPU in the QEMU guest** (serial-console VM, no PCI GPU).
3. **Threat model is malicious-VBIOS**, not unprivileged local.

## Exploit chain
none — primitive (kernel #DE / DoS) requires AMD hardware + module load +
attacker-controlled VBIOS, none of which exist on this guest.

## PoC changes
none — no executable PoC is possible; the path is dead code in the running
kernel and depends on hardware this guest does not have.

## Recommended fix
Mirror the DF-1143 fix: guard zero deltas before the divide. See `fix.diff`
— applies cleanly with `git apply` (validated).  Matches the finding
markdown's proposal.
