# DF-0661 — Kernel stack overflow via unchecked VLA in ngdread/ngdwrite

## Finding

`sys/netgraph/ng_device.c` declares VLAs sized by user-controlled `uio_resid`
(size_t) on the kernel stack with no upper-bound check:

- `ngdread` (line 509): `char buffer[uio->uio_resid+1];`
- `ngdwrite` (line 562): `char buffer[uio->uio_resid];`

A `write(fd, buf, 1<<20)` overflows the ~16 KB kernel stack → DOUBLE FAULT
panic. `/dev/ngdN` is mode 0600 (root-only).

## How to reproduce

### Prerequisites

- DragonFlyBSD 6.5-DEVELOPMENT guest (`#0` unpatched kernel)
- `ng_device` is NOT shipped as a prebuilt module and its source uses the
  obsolete `cdevsw` API. A faithful port to `dev_ops` is provided as
  `ng_device_ported.c` (only the device-registration boilerplate changes; the
  VLA bug in ngdread/ngdwrite is preserved verbatim).

### Build (as root in guest)

```sh
# Push ng_device_ported.c, trigger.c into /root/ng_device_build/
cd /root/ng_device_build
cp /usr/src/sys/netgraph/ng_device.h .
printf "KMOD=\tng_device\nSRCS=\tng_device.c\n.include <bsd.kmod.mk>\n" > Makefile
make KERNBUILDDIR=/usr/obj/usr/src/sys/X86_64_GENERIC
cc -O2 -o trigger trigger.c
```

### Run (as root in guest)

```sh
kldload netgraph
kldload ng_echo
kldload /root/ng_device_build/ng_device.ko
ngctl mkpeer device: echo lower downstream    # spawns /dev/ngd0
/root/ng_device_build/trigger /dev/ngd0 1048576   # 1 MiB write → stack overflow
```

### Expected behavior

- **Vulnerable kernel (#0):** `write()` enters `ngdwrite()`, materializes a
  1 MiB VLA on the ~16 KB kernel stack → RSP lands in unmapped memory →
  **DOUBLE FAULT panic**. The ssh session dies; the panic is captured in the
  serial console log.

- **Patched module (fix.diff applied):** `write()` returns `-1` with
  `errno=EFBIG` (27). No panic. Guest stays alive. Small writes (≤ 10240
  bytes) still work normally.

## Fix

Bound `uio_resid` to `NGD_QUEUE_SIZE` (10240) before the VLA declaration in
both functions. See `fix.diff`.

## Files in this evidence pack

| File | Description |
|------|-------------|
| `trigger.c` | Minimal trigger: opens /dev/ngdN, write(fd, buf, N) |
| `ng_device_ported.c` | Faithful port of ng_device.c to dev_ops API (VLA bug preserved) |
| `build_module.sh` | Script to build ng_device.ko + trigger in the guest |
| `setup_and_trigger.sh` | Script to load modules, create hook, trigger |
| `build.sh` | Reproducible build script |
| `run.sh` | Reproducible run script |
| `build.log` | Module build output |
| `run.log` | Baseline (unpatched) run documentation |
| `fix_build.log` | Patched module build output |
| `fix_run.log` | Patched module test output (EFBIG, no panic) |
| `panic.txt` | DOUBLE FAULT panic signature from serial console |
| `env.txt` | Guest environment (uname, cc version, module list) |
| `fix.diff` | Git-apply-able fix for sys/netgraph/ng_device.c |
| `VERDICT.md` | Full analysis and verdict |
| `manifest.json` | Machine-readable catalog |
