DF-0031 / fix_run.log
=== DF-0031 PoC + regression test on PATCHED single-fix kernel #1 ===
Kernel: DragonFly 6.5-DEVELOPMENT #1: Sun Jul 12 22:43:48 UTC 2026
BuildID[sha1]=949f92eeaf07bb84d765a22c915e4d89a3e795b5
sha256(/boot/kernel/kernel)=635a182de371ae97cf645669811dbd8d3cdf57f46f3580570edd2d2cf385a0db
Fix applied: pipe_create() now sets pipe->open_count = 2 BEFORE the two pipespace() calls
(sys/kern/sys_pipe.c:434), removing the late assignment at the old :445.
=> on a partial pipespace() failure, kern_pipe's double-pipeclose() cleanup
decrements 2->1->0 and the second call (old==1) frees/caches the pipe,
instead of underflowing 0->0xFFFFFFFF->0xFFFFFFFE and leaking.
--- Regression test: 5000 pipe write/read round-trips ---
OK: 5000 pipe write/read round-trips passed (no functional regression)
--- PoC on patched kernel (timeout 25s) ---
[*] holding 32526 pipe fds to build kernel_map pressure
[*] opened=0 failures(likely underflow-leak path)=1000000
[*] check `vmstat -z` / pipe zone and kernel_map free space for cumulative KVA/struct leak
RUN_EXIT=0
(Same EMFILE behavior as baseline: the 1M failures are falloc() EMFILE at sys_pipe.c:292-297
from exhausting kern.maxfilesperproc=32528, NOT the unreachable 2nd-pipespace ENOMEM path.
No panic, no crash. kvm_free stable at ~8.79 TB before and after.)
--- Guest status: up, healthy (uptime 53 secs) ---
=== Fix validation verdict: not_testable (bug path unreachable on default config) ===
The leak precondition (kernel_map exhaustion -> 2nd pipespace ENOMEM) cannot be triggered by
an unprivileged user: kern.maxfilesperproc=32528 / kern.maxfiles=130112 cap system-wide pipes
at ~65K (~4 GB KVA) vs vm.kvm_size=8.8 TB. So there is no observable bad behavior on EITHER
the unpatched or patched kernel to contrast. The fix is validated by:
(1) git apply --check passes;
(2) make -j6 nativekernel rc=0 (no errors/warnings);
(3) kernel boots (#1, new BuildID);
(4) 5000-pipe regression test passes (no functional regression);
(5) source inspection confirms the error path now decrements cleanly (2->1->0, 2nd frees).