# DF-3405 — tap(4) softc use-after-free: clone-destroy/create vs open

tap_softc lifetime is protected only on some paths: tapopen/tapclose
hold the mplock, but the ifconfig destroy path
(SIOCIFDESTROY -> if_clone_destroy -> tap_clone_destroy -> tapdestroy
-> kfree) takes no mplock, and tapcreate publishes dev->si_drv1
before the softc is initialized. An open() racing create/destroy
operates on a freed or half-built tap_softc.

## Reproduce (guest, as root)

    cc -O2 -o taprace taprace.c -lpthread
    sysctl -w debug.if_tap_debug=1
    sysctl -w debug.debugger_on_panic=0   # so the panic text hits serial
    ./taprace 90

8 threads open/write/close /dev/tap0 in a tight loop while the main
thread cycles SIOCIFCREATE/SIOCIFDESTROY on tap0.

**Expected (stock kernel #0):** kernel panic within ~90 s
(`tapclose -> tapifstop` writing through the freed softc — fault VA
0x84, `supervisor write`), crash dump in /var/crash. Baseline hit
2/2 runs (43 s and ≤90 s).

**Expected (kernel with fix.diff):** no panic; guest stays up.

## Fix

See `fix.diff` (publish si_drv1 late; ENXIO on NULL; mplock in
tap_clone_destroy). Validated in-guest: see `fix_validation.log`.
