# DF-3547 — use-after-free of `struct ngd_private` in ng7 ng_device cdevsw methods vs `ng_device_disconnect`

## One-line summary
`ng_device_disconnect()` calls DragonFly's **asynchronous** `destroy_dev()` and then
immediately frees `priv`; every cdevsw method (`ngdopen/ngdclose/ngdread/ngdwrite/ngdpoll`)
still reaches `priv` through `dev->si_drv1`, producing a kernel heap use-after-free
(read+write) once the node type is built.

## IMPORTANT STATUS NOTE (read first)
`sys/netgraph7/ng_device.c` is **dead code in this tree**: it does not compile against
DragonFly headers (it is unmodified FreeBSD porting rot from the 2008 ng7 import —
`struct cdevsw`, `d_open_t`, `msleep`, `IF_LOCK`, `_IF_ENQUEUE`, `IFQ_IS_EMPTY`,
`IFQ_SET_MAXLEN`, `m_uiotombuf`, `MTX_DEF`, `ifqueue.ifq_mtx`, `unit2minor` do not
exist in DF), it is absent from `sys/netgraph7/Makefile` SUBDIR, and no kernel config
defines `NETGRAPH7_DEVICE`. `./build.sh` reproduces the compile failure on the guest.
Therefore the UAF cannot be triggered on any buildable kernel today; the verdict is
`build_failed` with the defect proven by source-level analysis (see VERDICT.md).

## Build (reproduces non-compilability)
```
sh build.sh        # guest, root — out-of-tree kmod build of ng_device.c
                   # → 64 compile errors, full log in build.log
```

## Run (would trigger the UAF if the module existed)
```
cc -O2 -o stalefd stalefd.c     # on the guest
sh run.sh                       # documents the intended sequence:
                                #   open /dev/ngd0 -> keep fd -> ngctl rmhook
                                #   -> read()/write() on the stale fd => UAF
```
Success criterion (if the node type ever becomes loadable): kernel panic /
INVARIANTS double-free / objcache corruption from `IF_DEQUEUE` on the freed queue or
`NG_SEND_DATA_ONLY(..., priv->hook /* freed */, ...)`.

## Fix
`fix.diff` — reference-counted `priv` (acquire/release around every cdevsw method,
`si_drv1` cleared under the lock before `destroy_dev`, free deferred to last release).
Cannot be compile-validated for the same reason (file rot) → fix_status `not_testable`.
