# DF-2003 — VERDICT

## Verdict: CONFIRMED (source-trace), HW-gated — inconclusive at runtime

The unbounded busy-wait DoS is real and confirmed by a complete source trace.
It cannot be exercised on this audit guest because the `ipmi0` device requires
SMIC-type IPMI hardware + a BMC, which is not present (no `/dev/ipmi0`, no SMIC
interface in `dmesg`). Per the standard HW-gated pattern, runtime reproduction
is `inconclusive` / `reproduced=0` / `impact=none`, with the bug proven by code
inspection.

## Mechanism (confirmed path:line)

1. **Three unbounded polling loops** —
   `sys/dev/misc/ipmi/ipmi_smic.c:53-81`:
   - `smic_wait_for_tx_okay` (53-61): `do { flags = INB(sc, SMIC_FLAGS); } while (!(flags & SMIC_STATUS_TX_RDY));`
   - `smic_wait_for_rx_okay` (63-71): `do { ... } while (!(flags & SMIC_STATUS_RX_RDY));`
   - `smic_wait_for_not_busy` (73-81): `do { ... } while (flags & SMIC_STATUS_BUSY);`

   Each is a tight `INB` spin with: **no tick-based timeout**, **no `DELAY()`
   between polls**, and **no `signal_pending()` / `sc->ipmi_detaching` check**.

2. **`MAX_TIMEOUT` exists but is unused here** —
   `sys/dev/misc/ipmi/ipmivars.h:219` defines `#define MAX_TIMEOUT 6 * hz`.
   The sibling KCS transport uses it at `ipmi_kcs.c:60,66,83,89` together with
   `DELAY(100)`. The entire 407-line `ipmi_smic.c` has **zero** references to
   `MAX_TIMEOUT` and **zero** `DELAY` calls — SMIC is the only IPMI backend
   without bounded polling.

3. **Reachable from the `smic_loop` kthread** —
   `ipmi_smic.c:355-376`: the kthread loops on `ipmi_dequeue_request` →
   `smic_polled_request` (366) → the wait functions. If the BMC never asserts
   the expected flag, the kthread is trapped in the `INB` spin forever.

4. **Detach/shutdown wedge** —
   `sys/dev/misc/ipmi/ipmi.c:895`: `ipmi_detach` does
   `lksleep(sc->ipmi_kthread, ..., 0)` with `timeout=0` (infinite). A stuck
   kthread can never reach `kthread_exit()` (`ipmi_smic.c:375`), so
   `kldunload ipmi` and clean shutdown hang indefinitely.

## Impact

- Permanent 100% CPU consumption on one core (unkillable kernel thread).
- Inability to `kldunload ipmi`.
- Inability to cleanly shut down.
- All subsequent IPMI requests (including watchdog resets) blocked → may lead
  to a watchdog-triggered hard reset with no graceful path.

**Threat positions (realistic):** a local `operator`-group user submitting an
IPMI request against an unresponsive BMC; the kernel's own boot-time
`GET_DEVICE_ID` (`ipmi.c:732-735`) or watchdog (`ipmi.c:688-705`) hitting a
faulty BMC; or a compromised BMC (explicit threat model) intentionally
withholding the flag. The PoC needs no attacker control of the BMC — any BMC
malfunction in the request window triggers the permanent hang.

## Exploit chain

Not applicable — this is a pure DoS (CWE-835 infinite loop), not a memory-
corruption primitive. The impact ceiling is permanent kernel-thread hang +
CPU DoS + shutdown/module-unload wedge, fully characterized above.

## PoC changes

- Added `df2003_confirm.c` — a static structural check documenting the three
  unbounded loops, the unused `MAX_TIMEOUT`, the KCS contrast, and the
  detach-wedge path.
- Added `build.sh` / `run.sh`.
- Authored `fix.diff` — bounds all three wait functions with
  `MAX_TIMEOUT` + `DELAY(100)` (matching the KCS pattern), changes their
  return type to `int` (1=ok, 0=timeout) with a diagnostic `device_printf` on
  timeout. **Matches** the finding markdown's proposal. On timeout the
  function returns 0; the caller's subsequent `INB` reads a still-busy/wrong
  status, the existing `if (status != expected)` check fires, and the error
  propagates up to `smic_polled_request` → `smic_loop`, which sets `ir_error`
  and calls `ipmi_complete_request`, letting the kthread loop back to
  `ipmi_dequeue_request` where it can check `ipmi_detaching` and exit cleanly.

## Fix

`fix.diff` replaces the three unbounded `do/while` spins with bounded
`do { INB; if (flag) return 1; DELAY(100); } while (ticks - start < MAX_TIMEOUT)`
loops, matching the KCS transport's proven pattern. `git apply --check` passes.
Validated by a clean kernel build in Phase 8.
