DF-0585 / fix_run.log
=== DF-0585 FIX-VALIDATION — patched #1 kernel + patched if_tap.ko ===
BUILD
-----
Source patch applied to /usr/src/sys/net/tap/if_tap.c (patch -p1, Hunk #1 succeeded at 741, rc=0):
742: case TAPSIFINFO:
743: tapp = (struct tapinfo *)data;
744: if (ifp->if_type != tapp->type) {
745: ifnet_deserialize_all(ifp); <-- added: release serializer
746: return (EPROTOTYPE);
747: }
Build: cd /usr/src && make -j6 nativekernel KERNCONF=X86_64_GENERIC (warm obj)
=> === NK_DONE rc=0 === (Thu Jul 2 16:50:15 UTC 2026)
Full nativekernel output: see fix_build.log (~35k lines, no errors)
INSTALLED ARTIFACTS
-------------------
/boot/kernel/kernel = kernel.stripped (15,705,800 B, Jul 2 16:50) #1
/boot/kernel/kernel.debug = kernel.debug (119,340,592 B, Jul 2 16:50)
/boot/kernel/if_tap.ko = PATCHED module (263,008 B, Jul 2 16:50)
sha256: bfe90971b5139929f255114c712a85b5621b41550dc55782fa14c00a46d92e02
/boot/kernel/if_tap.ko.orig = BASELINE module (262,320 B, Jun 29 14:24)
sha256: 8e1a6da38502efe3cc7db2e6bb07555d555312bb02c4d5d44436b68791c65393
IMPORTANT NUANCE: in X86_64_GENERIC, tap(4) is a KLD MODULE, not a static
kernel device. The bug (and the fix) live in if_tap.ko, NOT in the kernel
binary. The first fix-validation attempt rebuilt the kernel but left the old
Jun-29 if_tap.ko on disk; kldload if_tap then loaded the UNPATCHED module and
the wedge reproduced even on the #1 kernel. The correct validation installs
BOTH the rebuilt kernel AND the rebuilt if_tap.ko. The fix is a one-line change
in the module; the kernel rebuild is incidental (version bump only).
PATCHED KERNEL
--------------
kern.version: DragonFly 6.5-DEVELOPMENT #1: Thu Jul 2 16:46:56 UTC 2026
loaded if_tap.ko sha256: bfe90971b5139929f255114c712a85b5621b41550dc55782fa14c00a46d92e02 (== patched)
RUN 1 (decisive)
----------------
Trigger ./leak_tap_lock /dev/tap on #1 + patched module:
[*] opened /dev/tap (fd=3)
[*] cloned interface: tap0
[*] TAPSIFINFO returned -1: errno=41 (Protocol wrong type for socket) [EPROTOTYPE=41]
[*] tapioctl() early-returned at if_tap.c:745 (now WITH ifnet_deserialize_all at 745)
[*] parent dropped its fd; child 851 will perform the final close()
[+] child pid 851 EXITED after close() (status=0x0)
[+] -> tapclose() completed; serializer released
[+] -> DF-0585 NOT reproduced: no wedge (FIXED kernel)
TRIGGER_RC=1
Kernel-side state after trigger (vs baseline D1/slize):
956 S1 nanslp leak_tap_lock <- parent sleeping in its 3s probe
958 Z - leak_tap_lock <- child EXITED (zombie), NOT wedged
Independent `ifconfig tap0` (timed):
ifconfig rc=1 elapsed=0s <- returned immediately ("interface tap0
does not exist" because the completing
close() properly tore down the clone)
RUN 2 (determinism)
-------------------
ifconfig tap0 rc=1 (returned immediately); no D-state leak_tap_lock procs.
RUN 3 (determinism)
-------------------
ifconfig tap0 rc=1 (returned immediately); no D-state leak_tap_lock procs.
BEFORE / AFTER CONTRAST
-----------------------
BASELINE (#0 + orig if_tap.ko) PATCHED (#1 + new if_tap.ko)
child state after 3s D1 wchan=slize (WEDGED) Z (EXITED)
ifconfig tap0 hangs >120s in D-sleep (slize) returns 0s, rc=1
interface permanently orphaned serializer cleanly torn down
==> FIX VALIDATED: the orphaned serializer is released on the TAPSIFINFO
type-mismatch error path; tapclose() completes; the interface is no
longer wedged. Behavior on every other path is unchanged.