# DF-5718 — kernel `strcpy` invoked on overlapping regions by the netgraph text parser

## What this is

Evidence pack for the pass-2 audit of `sys/libkern/strcpy.c` (batch with
`sys/libkern/skpc.c`, `sys/libkern/strcat.c`). The unbounded-copy primitive
itself is a correct implementation of the C contract; the actionable hazard
found in the consumer census is that the **netgraph ASCII message parser
calls `strcpy()` with overlapping source and destination**, which is
undefined behavior under the `restrict` contract both prototypes declare
(`sys/sys/libkern.h:131`), and works today only because the in-tree
`sys/libkern/strcpy.c:40` is a forward byte loop.

Overlapping call sites (all verified by reading and by the rig):

* `sys/netgraph/netgraph/ng_parse.c:1572` — `strcpy(p, p + 1)` (dst = src-1)
* `sys/netgraph/netgraph/ng_parse.c:1621` — `strcpy(p, v)` (v > p)
* `sys/netgraph7/netgraph/ng_parse.c:1764` — same
* `sys/netgraph7/netgraph/ng_parse.c:1813` — same

Severity: **Info** (hardening / latent). Netgraph control messages that
reach this parser are gated behind `caps_priv_check(SYSCAP_RESTRICTEDROOT)`
on DFly (`sys/netgraph/socket/ng_socket.c:171-175`), so there is no
unprivileged-reachable bug in the shipped kernel.

## How to reproduce (on the DragonFly guest)

```
# copy overlap_rig.c wrestrict_shim.c build.sh run.sh to /tmp/DF-5718/ on the guest
sh build.sh     # builds rig_intree rig_libc rig_block rig_fixed
sh run.sh
```

## Expected decisive output

```
INTREE: parse correct with verbatim byte-forward strcpy: YES
INTREE: overlapping strcpy invocations (restrict violations at ng_parse.c:1572/1621): 5
LIBC  : divergence vs in-tree strcpy: none            <- negative control (DFly libc is byte-forward too)
BLOCK : child killed by SIGSEGV ... => equivalent to a kernel heap OOB write
RESULT : overlap/past-NUL reliance CONFIRMED - the in-tree byte-forward strcpy is load-bearing
FIXED  : memmove treatment output identical to in-tree semantics: YES
```

## Rig modes

| binary | strcpy used | proves |
|---|---|---|
| `rig_intree` | verbatim `sys/libkern/strcpy.c:36-42` loop, instrumented | the shipped algorithm calls strcpy on overlapping regions (5x in one parse) and is correct with the byte-forward implementation |
| `rig_libc`   | libc / gcc builtin (`-O2`, no `-fno-builtin`) | swap-scenario control; DFly's libc strcpy is also byte-forward -> no divergence on this platform |
| `rig_block`  | model of a vectorized block-store strcpy (16-byte block loads/stores, final partial block stored whole) | a legal-in-practice optimized strcpy writes past the NUL and past the exact-size `cbuf` allocation (`kmalloc(strlen(s + start))`, no `+1`, ng_parse.c:1559) -> SIGSEGV on a guard page = OOB write |
| `rig_fixed`  | the two overlap sites switched to `memmove` (= `fix.diff`) | fix preserves the parser's byte-exact semantics |

## Files

* `overlap_rig.c` — the rig (parser body is the verbatim kernel algorithm; deviations marked `DEV:`)
* `wrestrict_shim.c` — the two call sites in isolation; gcc 8.3 `-Wrestrict` does **not** diagnose them (compiler does not catch this)
* `build.sh`, `run.sh` — exact commands
* `build.log`, `run.log` — full untrimmed guest output
* `env.txt` — guest uname / cc version
* `fix.diff` — git-apply-able fix (netgraph + netgraph7)
* `VERDICT.md`, `manifest.json`, `verdict.json`
