# DF-0601 — VERDICT: NOT REPRODUCED (latent: file is dead, orphaned, non-compiling code)

## Verdict

**NOT REPRODUCED — latent hardening item.** The race condition described in the
finding is **statically correct** (every source-level claim verified below), but
the file `sys/netgraph7/ng_source.c` is **dead, orphaned, and non-compiling
code** that cannot be reached on any currently-buildable DragonFlyBSD kernel
configuration. There is no triggerable primitive, no panic, no leak — the bug
is a latent defect that would only become live if a maintainer re-animates the
file (fixes the compile typo, adds it to `conf/files`, adds a `NETGRAPH7_SOURCE`
option, enables `NETGRAPH7` in a kernel config). The finding is correctly filed
as **Info severity**.

## Why it cannot reproduce — exhaustive dead-code proof

The finding's own caveat (lines 17-37 of the finding markdown) is fully
confirmed by source tracing:

### (1) `ng_source.c` is NOT in the build system

```
$ grep -rn ng_source sys/conf/
(empty — no match in any conf/ file)
$ grep -n "netgraph7" sys/conf/files | grep source
(empty — every other ng7 node IS listed, ng_source is conspicuously absent)
$ grep -n "NETGRAPH7_SOURCE" sys/conf/options
(empty — there is no such option; all ~50 other ng7 node types have one)
```

Even if a maintainer added `options NETGRAPH7_SOURCE` to a kernel config, the
build would not compile the file because `conf/files` has no
`netgraph7/ng_source.c` entry.

### (2) The file has a hard compile error at line 743

Inside `ng_source_intr` (ng_source.c:726), the only local in scope at line 743
is `ifsq` (declared at lines 740-741 via `ifq_get_subq_default`). Line 743
references the **undeclared** identifier `ifq`:

```c
739:	if (sc->output_ifp != NULL) {
740:		struct ifaltq_subqueue *ifsq =
741:		    ifq_get_subq_default(&sc->output_ifp->if_snd);
742:
743:		packets = ifq->ifq_maxlen - ifq->ifq_len;   /* BUG: ifq undeclared */
744:	} else
```

This is a guaranteed `error: 'ifq' undeclared` compile failure. The file
cannot be compiled as-is.

### (3) The default kernel does not enable NETGRAPH7 at all

```
$ grep -in netgraph sys/config/X86_64_GENERIC
(empty)
```

The default `X86_64_GENERIC` kernel has no `options NETGRAPH7` line, so
`netgraph7/netgraph/ng_base.c` (the framework dispatcher, listed as
`optional netgraph7`) is not compiled into the kernel. The guest confirms:
`nm /boot/kernel/kernel | grep netgraph7` returns nothing, and
`kldload netgraph7` fails with "No such file or directory".

### (4) No ng_source module exists on the guest

```
guest$ ls /boot/kernel/ | grep source    (empty)
guest$ find sys/ -name "*ng_source*"     → only sys/netgraph7/ng_source.{c,h}
```

Neither old netgraph (`sys/netgraph/`) nor netgraph7 has a loadable/compiled
ng_source on this guest.

## Static analysis — all 4 source claims verified (the bug IS real if re-animated)

Despite being dead code, the race-condition observation is **correct**:

### Claim 1: Constructor lacks NG_NODE_FORCE_WRITER ✅

`ng_source_constructor` (ng_source.c:269-284) sets `sc->snd_queue.ifq_maxlen`
and calls `ng_callout_init`, but **never calls `NG_NODE_FORCE_WRITER(node)`**.
Compare sibling nodes that correctly force writer serialization:

| Node | Constructor line | Has FORCE_WRITER? |
|------|-----------------|-------------------|
| `ng_nat.c` | 304 | ✅ yes |
| `ng_bridge.c` | 329 | ✅ yes |
| `ng_pred1.c` | 196 | ✅ yes |
| `ng_deflate.c` | 183 | ✅ yes |
| `ng_mppc.c` | 211 | ✅ yes |
| `ng_hci_main.c` | 151 | ✅ yes |
| **`ng_source.c`** | **284** | **❌ NO** |

### Claim 2: rcvdata uses unlocked _IF_ENQUEUE ✅

`ng_source_rcvdata` (ng_source.c:545-570) mutates shared state with no lock:

```c
565:		_IF_ENQUEUE(&sc->snd_queue, m);      /* unlocked macro */
566:		sc->queueOctets += m->m_pkthdr.len;  /* plain racy assignment */
567:		sc->last_packet = m;                 /* plain racy assignment */
```

`_IF_ENQUEUE` is the **unlocked** variant — it does
`if (ifq->ifq_tail == NULL) ifq->ifq_head = m; else ifq->ifq_tail->m_nextpkt = m;
ifq->ifq_tail = m;` with no atomicity.

### Claim 3: Framework dispatches data as readers without FORCE_WRITER ✅

The netgraph7 dispatch (ng_base.c:1993-1999) checks `NGF_FORCE_WRITER`:

```c
1993:	if (((item->el_flags & NGQF_RW) == NGQF_WRITER) ||
1994:	    (node->nd_flags & NGF_FORCE_WRITER) ||
1995:	    (hook && (hook->hk_flags & HK_FORCE_WRITER))) {
1996:		ng_acquire_write(node);       /* exclusive: lwkt_gettoken */
1997:	} else {
1998:		ng_acquire_read(node);        /* shared: lwkt_gettoken_shared */
1999:	}
```

Data items are created as readers by default (ng_base.c:2994:
`item->el_flags |= NGQF_READER`). Without `NG_NODE_FORCE_WRITER`, ng_source's
rcvdata runs under `ng_acquire_read` → `lwkt_gettoken_shared`
(ng_base.c:1845), which **permits concurrent execution across CPUs**.

### Claim 4: _IF_ENQUEUE is non-atomic → race on snd_queue linkage ✅

Two concurrent rcvdata invocations can both read `ifq_tail==NULL` (losing one
packet's linkage) or both write `->m_nextpkt` of the same tail (corrupt chain).
The same `snd_queue` is later dequeued by `ng_source_send`/`ng_source_intr`
via `_IF_DEQUEUE` (lines 671, 789), so a corrupted chain yields panic or
double-free.

## Classification

This is Phase 4 case **(d): genuinely not reachable on this kernel** — and
stronger: not reachable on ANY buildable kernel because the file is not in the
build system and has a pre-existing compile error. This is a valid **latent
defect / hardening item** (Info severity), exactly as the finding is filed.

## Exploit chain

**none** — this is a latent race condition in dead code. There is no
triggerable primitive, so no escalation chain is possible. This is the valid
hard-blocker case: "The vulnerable code path is dead/unreachable at runtime on
this guest AND no harness can exercise it" (a race in a netgraph dispatch
handler cannot be isolated to a unit-test harness; it requires the full
netgraph framework + multi-CPU packet fan-in).

## PoC changes

**none** — no PoC can be built (the finding's README correctly states this).
No source files were added or modified. Only `fix.diff`, `VERDICT.md`,
`build.sh`, `run.sh`, `env.txt`, and `manifest.json` were added to the evidence
pack.

## Fix

`fix.diff` adds `NG_NODE_FORCE_WRITER(node)` to the constructor — the minimal,
targeted hardening fix matching every sibling netgraph7 node. This is a
**defense-in-depth** measure for dead code; it cannot be build-validated
because the file is not in `conf/files` and has the pre-existing `ifq` typo at
line 743.

`fix_status: not_testable` — the file is dead code (not in the build system,
has a compile error, NETGRAPH7 not in GENERIC), so building a single-fix kernel
and re-running a PoC is impossible. The diff passes `git apply --check`
(rc=0) and matches the finding's recommended fix exactly.

Before this fix has any effect, a maintainer must also:
1. Fix the `ifq`→`ifsq` typo at ng_source.c:743.
2. Add `netgraph7/ng_source.c  optional netgraph7_source` to `sys/conf/files`.
3. Add `NETGRAPH7_SOURCE  opt_netgraph.h` to `sys/conf/options`.
4. Enable `options NETGRAPH7` + `options NETGRAPH7_SOURCE` in a kernel config.
