# DF-3382 VERDICT

## Reproduced: YES (first attempt)

Guest: DragonFly dfbsd 6.5-DEVELOPMENT #0 (X86_64_GENERIC, INVARIANTS).

Exact sequence (`run.log`):

1. `ifconfig tun0 create` (if_tun is compiled in; bpfattach DLT_NULL,
   if_tun.c:239).
2. open `/dev/bpf1`, `BIOCSETIF("tun0")` → `bpf_allocbufs()` allocates two
   4096-byte buffers (bpf.c:1475-1476).
3. `ifconfig tun0 destroy` → `bpfdetach()` → `bpf_detachd()`: `bd_bif=NULL`,
   buffers retained (bpf.c:320-326).
4. `BIOCSBLEN(0x80000)` → accepted (`bd_bif==NULL`, bpf.c:795-805) →
   `bd_bufsize=524288`.  Program printed
   `[+] BIOCSBLEN -> 524288 (buffers still 4096!)`.
5. `BIOCSETIF("lo0")` → `bd_sbuf != NULL` → allocation skipped (bpf.c:1128).
6. 512 loopback UDP packets of 1400 'A' bytes: every `catchpacket()` appends
   at `bd_sbuf+curlen`; rotation only when `curlen+totlen > 512KiB`, so the
   write stream runs ~731 KiB through a 4096-byte allocation.

Result: the process itself completed ("survived", exit 0) but the kernel
died moments later with a general protection fault in
`cache_nlookup_maybe_shared+0x100` while dereferencing a corrupted namecache
link (`panic.txt` from the serial console).  That is heap corruption
consuming unrelated kernel subsystems — a stronger demonstration than a
direct panic: ~727 KiB of controlled 0x41 data was written past the victim
allocation.

## Primitive characterization

* **What:** effectively unbounded linear heap overflow (up to
  `bd_bufsize` = 512 KiB per store-buffer cycle) with fully controlled
  content (packet bytes) and start offset (`curlen` advances by captured
  packet sizes).
* **Survivability:** unlike DF-3381 the copy length is *legitimate* per
  packet; the kernel kept running for seconds after corrupting ~727 KiB of
  adjacent memory — a corrupt-and-continue primitive, strictly more
  exploitable than DF-3381's fixed-4GiB copy.
* **Privilege gate:** reaching step 3 requires destroying an interface
  (root).  Steps 4-6 require only the open bpf descriptor, so like DF-3381
  the ioctls and traffic can come from a privilege-dropped fd holder; the
  *destroy* itself needs root, making the practical model
  root-configured / unprivileged-triggered.
* **uid0 route:** not completed.  A credible chain would spray kmalloc(4096)
  victim objects (e.g. file-table entries, kqueue structures) around the
  store buffer, overflow with forged objects, and resume execution — the
  guest has no SMAP/SMEP/KASLR — but the trigger needs a root-orchestrated
  interface destroy, so a real-world privilege boundary is only crossed in
  the dropped-daemon-holding-fd scenario.  Documented as the ceiling; not
  pursued to a uid0 shell within this run (time budget spent on fix
  validation, which is mandatory).

## Fix validation
`fix.diff` (shared with DF-3381): `BIOCSETBLEN` now also rejects when
`d->bd_sbuf != NULL`.  On the patched kernel the PoC fails cleanly at
step 4 (`BIOCSBLEN: Invalid argument`, `run.patched.log`), guest survives,
and the identical sequence cannot desynchronize `bd_bufsize` from the
allocated buffers.  `fix_baseline_reproduced=1`, `fix_patched_reproduced=0`.

kernel refs: sys/net/bpf.c:794-806 (BIOCSBLEN guard), 1128-1134 (setif
alloc guard), 320-326 (bpf_detachd keeps buffers), 1580-1583 (bpfdetach
loop), 1418-1463 (catchpacket appends).

## 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.
