# DF-1048 PoC — umcs7840_calc_baudrate divide-by-zero (CWE-369)

Kernel: `sys/bus/u4b/serial/umcs.c:1056-1070`. Calling
`umcs7840_calc_baudrate(0, …)` (reachable via `tcsetattr(B0)` →
`ucom_param` → `umcs7840_pre_param`) evaluates `d[9] / 0`: an OOB read of
one `uint32_t` past the 9-element `umcs7840_baudrate_divisors` array
followed immediately by an integer divide-by-zero. On x86-64 `div` with a
zero divisor raises `#DE` — a fatal trap in kernel mode → **panic**.

## Files

| file | purpose |
|------|---------|
| `harness.c`  | **primary deliverable** — extracts `umcs7840_baudrate_divisors[]` and `umcs7840_calc_baudrate` verbatim from `umcs.c:1052-1070` and replays the exact kernel arithmetic with rate=0. Proves the divide-by-zero (userspace SIGFPE = kernel #DE trap) and that the fix eliminates it. Built at `-O0` and `-O2`. |
| `trigger.c`  | live `tcsetattr(fd, TCSANOW, {c_ospeed:B0})` PoC — the canonical runtime trigger for a host that **does** have an MCS7820/MCS7840 USB-serial adapter attached (`/dev/cuaU0` must exist). |
| `build.sh`   | builds harness (O0+O2) and trigger |
| `run.sh`     | runs the harness; runs the live trigger only if `/dev/cuaU0` exists |
| `fix.diff`   | git-apply-able fix: add `rate == 0 ||` guard to `umcs7840_calc_baudrate` |
| `VERDICT.md` | full analysis (mechanism, trace, harness proof, fix validation) |

## Build & run (on the audit guest or any DragonFly host)

```sh
./build.sh
./run.sh
```

## Expected on the unpatched kernel

The harness shows:
```
== BUGGY version ==
  rate=0          -> *** DIVIDE BY ZERO (SIGFPE / #DE trap) ***
== FIXED version ==
  rate=0          -> returned rc=-1 divisor=0xdead clk=0xff
```
(`SIGFPE` in userspace is the analog of the kernel's `#DE` / "Fatal trap 17"
panic.)

On a host with a real MCS7840 adapter, `./trigger /dev/cuaU0` instead
panics the kernel:
```
Fatal trap 17: divide-by-zero fault in kernel mode
...
umcs7840_calc_baudrate(...) at umcs.c:1066
umcs7840_pre_param(...) at umcs.c:667
ucom_param(...) at usb_serial.c:1683
panic: trap type 17, code=0
```

## Why a harness (not a live panic) on the audit VM

The QEMU guest has **no USB host controller**, so no `umcs` device attaches
and no `/dev/cuaU*` node exists — the live `tcsetattr(B0)` path is
untestable here. The harness reproduces the exact buggy arithmetic in
userspace, where the same `#DE` fault surfaces as `SIGFPE` (exit 136).

## After applying fix.diff

`umcs7840_calc_baudrate(0, …)` returns `-1` → `umcs7840_pre_param` returns
`EINVAL` → `tcsetattr` returns `-1/EINVAL` to the user. No panic.
