# DF-2540 — Signed integer overflow in amdsb_watchdog() timeout calculation

## Verdict
**NOT REPRODUCED on this guest** (HW-gated — no AMD SB600/SB7xx southbridge in QEMU).
However, the **code bug is CONFIRMED by source tracing and arithmetic verification**: the
signed integer overflow at line 217 produces a watchdog count of **0** for specific `period`
values, bypassing the max-ticks clamp and programming the hardware to fire immediately.

## Bug analysis

`amdsb_watchdog()` (`sys/dev/misc/amdsbwd/amdsbwd.c:211-228`):

```c
static int
amdsb_watchdog(void *arg, int period)
{
    unsigned int timeout;
    struct amdsbwd_softc *sc = arg;

    timeout = (period * 1000) / sc->ms_per_tick;   // line 217: SIGNED overflow
    if (timeout > sc->max_ticks)                    // line 218: clamp — can't undo overflow
        timeout = sc->max_ticks;
    ...
    amdsbwd_tmr_set(sc, timeout);                   // programs hardware count register
    return period;
}
```

`period` is `int` (from `kern.watchdog.period` sysctl). `period * 1000` is `int × int → int`.
For `period > INT_MAX/1000 = 2147483`, this overflows signed int — **undefined behavior** in C.
On two's-complement hardware (gcc 8.3 default), it wraps.

With `sc->ms_per_tick = 1000` (the only value assigned, `amdsbwd.c:472`):

| `period` | `period*1000` as int32 | `/1000` (C trunc toward 0) | `unsigned int` | `> max_ticks?` | **HW count** |
|----------|------------------------|---------------------------|-----------------|----------------|-------------|
| 2147483  | 2147483000             | 2147483                   | 2147483         | yes → 65535    | 65535 (safe) |
| 2147484  | -2147483296            | -2147483                  | 4292819813      | yes → 65535    | 65535 (safe) |
| **4294967** | **-296**            | **0**                     | **0**           | **NO**         | **0 → FIRE!** |
| 4294966  | -1296                  | -1                        | 4294967295      | yes → 65535    | 65535 (safe) |

**`period = 4294967`**: `4294967 * 1000 = 4294967000`, which as `int32` wraps to `-296`.
Then `-296 / 1000 = 0` (C integer division truncates toward zero, and `|-296| < 1000`).
`timeout = (unsigned int)0 = 0`. Since `0 <= max_ticks(65535)`, the clamp does **NOT** fire.
`amdsbwd_tmr_set(sc, 0)` programs the AMD SB watchdog count register to **0**, causing the
watchdog to fire immediately → **deterministic system reboot**.

The finding's analysis is **correct**: the signed overflow produces count=0 for `period ≈ 4294967`,
bypassing the clamp and causing an immediate reboot on real AMD SB hardware.

## Why it can't be reproduced on this guest

The `amdsbwd` device only attaches when AMD SB600/SB7xx/SB8x hardware is present
(`amdsbwd_identify` checks `pci_find_bsf(0, 20, 0)` for AMD SMBus device IDs at
`amdsbwd.c:245-251`). The QEMU guest uses an **Intel 440FX / PIIX3** chipset — no AMD SB
device exists:

```
$ ls /dev/amdsbwd*          → No such file or directory
$ pciconf -lv | grep AMD    → (nothing — Intel 440FX/PIIX3/PIIX4 only)
```

Without the device, `amdsb_watchdog` is never registered as a `watchdog_list` callback,
so `kern.watchdog.period` changes never reach the vulnerable code. The bug is **latent on
this guest** — real on physical AMD SB hardware, unreachable in QEMU.

## Impact

- **CVSS PR:H** — `kern.watchdog.period` requires root to set.
- **HW-gated** — requires AMD SB600/SB7xx/SB8x southbridge.
- On real hardware: root sets `kern.watchdog.period=4294967` → AMD SB watchdog count=0 →
  immediate reboot. Local DoS via arithmetic logic bug.
- Not remotely exploitable; not unprivileged.

## Fix

Cast `period` to `int64_t` before multiplication to eliminate the signed overflow:

```diff
-	timeout = (period * 1000) / sc->ms_per_tick;
+	timeout = ((int64_t)period * 1000) / sc->ms_per_tick;
```

With the fix, `period=4294967` → `(int64_t)4294967 * 1000 = 4294967000` (fits in int64),
`/1000 = 4294967`, `> max_ticks(65535)` → clamped to 65535. Correct.

Validated: `amdsbwd.ko` rebuilt with the fix (`make KERNCONF=X86_64_GENERIC` in
`sys/dev/misc/amdsbwd/`, rc=0). Behavioral testing not possible (no AMD SB hardware in QEMU);
fix correctness is verified by arithmetic.
