# DF-0897 — Stack buffer overflow in devfs_rules ioctl

## Summary

Stack buffer overflow via non-NUL-terminated `name`/`linkname` in the
`struct devfs_rule_ioctl` passed to the `DEVFS_RULE_ADD` ioctl on
`/dev/devfs`. The unbounded `strlen(templ->name)` at
`devfs_rules.c:104` scans past `name[PATH_MAX]` into the adjacent
`linkname[PATH_MAX]` array, causing a ~2072-byte string to be stored.
When rules are later applied, `devfs_resolve_name_path()` does
`memcpy(name_buf, rule->name, 2072)` into a `char name_buf[PATH_MAX]`
(1024-byte) stack buffer — a ~1048-byte stack smash with
attacker-controlled content. DragonFly kernels have **no stack canary**
(`-fno-stack-protector`), so this is a code-execution primitive.

## Impact

- **panic** on default GENERIC (demonstrated: Fatal trap 9, frame pointer
  overwritten with attacker-controlled bytes)
- The underlying primitive is a **root→kernel stack smash with code-execution
  potential** (no canary, no SMEP, no SMAP, no KASLR on this guest)
- **Not an unprivileged LPE** — `/dev/devfs` is `0600 root:wheel`
- **Jail escape angle** — jailed root (cr_uid=0) can trigger this if
  `/dev/devfs` is exposed in the jail's devfs mount (non-default)

## Files

| File | Description |
|------|-------------|
| `trigger.c` | PoC: constructs non-NUL-terminated name, issues ADD+APPLY ioctls |
| `build.sh` | Build script |
| `run.sh` | Run script |
| `fix.diff` | Git-apply-able fix (strnlen + bounded memcpy) |
| `VERDICT.md` | Full narrative analysis |
| `run.log` | Unpatched run log (panic) |
| `fix_run.log` | Patched run log (EINVAL, no crash) |
| `fix_build.log` | Single-fix kernel build log |
| `panic.txt` | Kernel panic signature from boot.log |
| `env.txt` | Guest environment (uname, cc, canary check, devfs perms) |
| `manifest.json` | Machine-readable catalog |

## Reproduce

```sh
./build.sh          # cc -O0 -o trigger trigger.c
./run.sh            # must run as root (device is 0600 root:wheel)
```

**Expected on unpatched kernel:** `DEVFS_RULE_ADD` succeeds, then
`DEVFS_RULE_APPLY` triggers a kernel panic (Fatal trap 9, frame pointer
`0x4141414141414141`).

**Expected on fixed kernel:** `DEVFS_RULE_ADD` returns `EINVAL`, no crash.
