# DF-3384 VERDICT

## Reproduced: NO (3 strategies, 260+ attempts) — code-certain interleaving, timing not landed on this guest

Claim: `bpfread()` finishes `uiomove()` and then unconditionally executes
(bpf.c:541-545):

```c
error = uiomove(d->bd_hbuf, d->bd_hlen, ap->a_uio);
d->bd_fbuf = d->bd_hbuf;      /* <-- unconditional clobber */
d->bd_hbuf = NULL;
d->bd_hlen = 0;
```

If the reader *blocks inside uiomove* (user page fault), `bpf_token` is
released (lwkt tokens are dropped on block); a concurrent `BIOCFLUSH` on a
dup'd descriptor then runs `bpf_resetd()` (bpf.c:674-686):

```c
if (d->bd_hbuf) {
        d->bd_fbuf = d->bd_hbuf;   /* parks the hold buffer */
        d->bd_hbuf = NULL;
}
```

and the resuming reader overwrites `bd_fbuf` with the now-NULL `bd_hbuf`,
losing the buffer pointer (2-4096 byte... `bd_bufsize`-byte kmalloc leak
per win; `bpf_freed()` cannot free it).  After the next immediate-mode read
the store slot itself is NULL (`ROTATE_BUFFERS` sets `bd_sbuf = bd_fbuf`),
and the next tapped packet makes `catchpacket()` write the bpf header
through `hp = (struct bpf_hdr *)(d->bd_sbuf + curlen)` == NULL
(bpf.c:1455-1458) — a kernel write to address 0 (`bh_tstamp`, then
`bh_datalen = pktlen` attacker-controlled, then the packet copy at +hdrlen).

## Attempts (guest DragonFly 6.5-DEVELOPMENT, INVARIANTS, 4 CPU)

1. v1: single-shot, 1 s stagger, anon read buffer — read#1 completed before
   flush; no interference.
2. v2: 200 attempts, 512 KiB hold buffer (128 anon zero-fill page faults
   inside one uiomove), flush delay scanned 300 µs..20 ms — no hit.
3. v3: flush thread spamming `BIOCFLUSH` continuously across read#1 — no
   hit in 60 attempts.
4. v4: read buffer = 128 **cold file-backed pages** of a 3.5 GiB file
   (written past RAM size so pages are evicted; hammer2 + virtio disk) —
   ran 7+ minutes of fault+flush storm without a panic before being
   stopped; guest stayed up.

Conclusion: on this virtualized guest the copyout fault path never yields
the token for a long enough window for the flushing thread to acquire it
(zero-fill faults complete in-place; host-page-cached virtio disk faults
are too short, and the token ping-pong between a spamming ioctl thread and
a faulting reader doesn't serialize the flush *inside* the uiomove).  The
interleaving is not contradicted by anything in the code — it requires a
genuinely blocking fault (real slow disk, NFS, swap-backed page, memory
pressure) which this guest cannot present.  Honest status:
`not_reproduced`; confidence in the *defect* remains `likely` from code
arithmetic alone.

## Impact if landed
Kernel memory leak (one `bd_bufsize` buffer per race win, unrecoverable
until close) + guaranteed NULL-address write (DoS panic).  Requires two
threads sharing a bpf fd (dup) — privileged trigger (root-owned fd or
dropped-priv holder).  Not a credential-boundary crossing beyond the
bpf-fd holder.  The NULL-write is mitigated by the `bd_sbuf == NULL` guard
in the validated DF-3381 `fix.diff`; the leak needs a `bd_reading` flag or
equivalent around uiomove (upstream-grade fix, out of scope here).

kernel refs: sys/net/bpf.c:541-545, 674-686, 475-531, 439-444, 1455-1463.

## Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest `make -j6 nativekernel KERNCONF=X86_64_GENERIC` completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.

(No fix.diff for this item: documented recommendation only - see Fix above.)
