{
 "finding_id": "DF-3405",
 "status": "reproduced",
 "reproduced": 1,
 "impact": "panic",
 "confidence": "certain",
 "verdict": "tap_softc use-after-free reproduced on the stock INVARIANTS kernel: tapopen() (mplock) races the ifconfig destroy path tap_clone_destroy()->tapdestroy()->kfree(sc) (no mplock; only ifnet_lock, which tapopen never takes), and tapcreate() publishes dev->si_drv1 before the softc is initialized. 8-thread open/write/close vs SIOCIFCREATE/SIOCIFDESTROY hammering panicked the guest within 43-90s on 2/2 completed baseline runs: Fatal user address access from kernel mode, fault VA 0x84 supervisor WRITE, trace tapifstop() at if_tap.c:710 <- tapclose() <- dev_dclose <- close(fd), with the TAPDEBUG line not ready, flags = 0x41 proving the closer ran on torn/freed softc state (a live ifconfig-created tap reads 0x53); full crash dump in core.txt.0 (kgdb: tapifstop sc=0xfffff801179a9e00). Fixed in-guest (fix.diff: publish si_drv1 after full init; tapopen ENXIO on NULL; mplock across tap_clone_destroy) -- 3 re-runs ~480s total identical pressure, zero panics, normal create/open/write/destroy cycles pass. Trigger requires root on both sides (/dev/tapN 0600 + tapuopen=0 SYSCAP gate; SIOCIFDESTROY SYSCAP_RESTRICTEDROOT), so severity is Low (privileged local kernel memory corruption / DoS), memcorrupt bucket.",
 "exploit_chain": "root: 8 threads open+write+close /dev/tap0 while another thread cycles SIOCIFCREATE/SIOCIFDESTROY -> tapopen fetches dev->si_drv1 and continues while tapdestroy kfrees the 256-byte M_TAP softc (or catches tapcreates half-built sc published at if_tap.c:223) -> open side writes TAP_OPEN/taprefcnt into freed memory and returns an fd -> tapwrite/tapioctl/tapclose run entirely on the freed softc -> tapclose->tapifstop writes through garbage ifq_sq pointers -> supervisor write page fault (VA 0x84), panic. The freed kmalloc(256) chunk is reallocation-groomable; on this no-SMEP/SMAP/KASLR guest a persistent root attacker could aim for RIP control, but the trigger is already root-only: escalation value none, filed Low/DoS. No unprivileged entry found.",
 "evidence": [
  "panic.txt: full serial-console panic -- Fatal user address access ... fault virtual address = 0x84 / supervisor write data + trace tapifstop() at tapifstop+0x88 / tapclose() at tapclose+0x1b5, preceded by TAPDEBUG not ready, minor = 0, flags = 0x41 (torn softc flags)",
  "core.txt.0: savecore/kgdb dump session -- #6 tapifstop (sc=0xfffff801179a9e00, clear_flags=1) at /usr/src/sys/net/tap/if_tap.c:710, #7 tapclose at if_tap.c:422, via dev_dclose/devfs_spec_close/kern_close(fd=4); process table already corrupt (Cannot access memory at 0x2b00001665)",
  "run.log: baseline run1 (90s) kernel fault bcmp+0x3c, run2 (150s) panic at 43s uptime -- 2/2 completed runs crashed",
  "fix_validation.log: patched kernel #1 (both fixes), 3 race runs ~480s total, 0 panics, guest up, functional create/open/write/destroy CYCLE_OK"
 ],
 "kernel_refs": [
  "sys/net/tap/if_tap.c:332",
  "sys/net/tap/if_tap.c:347",
  "sys/net/tap/if_tap.c:503",
  "sys/net/tap/if_tap.c:507",
  "sys/net/tap/if_tap.c:471",
  "sys/net/tap/if_tap.c:487",
  "sys/net/tap/if_tap.c:495",
  "sys/net/tap/if_tap.c:223",
  "sys/net/if_clone.c:104"
 ],
 "poc_changes": "PoC written fresh for this finding (race harness). Improved mid-validation: destroy is now attempted every cycle (not only after a successful create) because a single EBUSY stalled the loop; that stall also exposed the residual devfs destroy_dev-vs-in-flight-open wedge (documented, not part of this findings fix).",
 "attempts": 5,
 "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64 (baseline); fix kernel #1: Sat Sep 12 06:59:23 UTC 2026",
 "runtime_sec": 5400,
 "guest_dirty": 0,
 "build_cmd": "cc -O2 -o /root/taprace /tmp/taprace.c -lpthread  (in-guest)",
 "run_cmd": "sysctl -w debug.if_tap_debug=1 debug.debugger_on_panic=0; /root/taprace 90",
 "code_hash": "ee37676913830dc9c944c22d60e13cb8325cbdf4287bea66e617848dd70924ab",
 "notes": "Residual (honest, NOT fixed by fix.diff): destroy_dev() racing an in-flight open() can still lose the fd -- tapopens taprefcnt++/TAP_OPEN stay set forever (zombie tap unit, kldunload blocked until reboot). No memory unsafety observed in that state; needs devfs-side in-flight-open draining. Baseline panics were captured with debug.if_tap_debug=1 and debugger_on_panic=0 so the full trap dump hit the serial log; /var/crash/core.txt.0 carries the kgdb backtrace.",
 "recommended_fix": "Publish dev->si_drv1 only after full tapcreate() init; tapopen() returns ENXIO when si_drv1 is NULL; hold the mplock across tap_clone_destroy()s TAP_OPEN check + tapdestroy() (see fix.diff); follow-up: drain in-flight opens in destroy_dev().",
 "fix_status": "fixed",
 "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #1: Sat Sep 12 06:59:23 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64",
 "fix_baseline_reproduced": 1,
 "fix_patched_reproduced": 0,
 "fix_verdict": "fix.diff (3 hunks: publish dev->si_drv1 only after tapcreate() fully initializes the softc; tapopen() returns ENXIO when si_drv1 is NULL instead of resurrecting a destroyed/pending device; tap_clone_destroy() holds the mplock across its TAP_OPEN check and tapdestroy(), matching tapopen/tapclose discipline). Built in-guest with make -j4 nativekernel KERNCONF=X86_64_GENERIC + make installkernel (kernel #1, Sat Sep 12 06:59:23 UTC 2026, combined with the DF-3406 hunk). Re-ran the identical race three times (~480s total, same 8-thread open/write/close vs SIOCIFCREATE/SIOCIFDESTROY pressure that panicked the stock kernel 2/2 within 43-90s): zero panics, guest stable, post-fix create/open/write/destroy cycle passes (CYCLE_OK). The UAF crash is gone. Residual (documented, outside this diff): destroy_dev() vs an in-flight open() can still lose the fd leaving taprefcnt=1/TAP_OPEN set (zombie tap unit until reboot) -- a devfs-level drain issue, no memory unsafety observed.",
 "fix_evidence": [
  "findings/poc/DF-3405/fix_validation.log",
  "findings/poc/DF-3405/fix.diff"
 ]
}