=== FIXED KERNEL (fix.diff applied in guest scratch /usr/src, built via === make nativekernel KERNCONF=X86_64_GENERIC, 6.1 min, installed, rebooted) uname -v: DragonFly 6.5-DEVELOPMENT #1: Tue Oct 20 11:55:22 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC sysctl vm.max_vkernel_vmspaces: 64 <- new tunable present sysctl vm.vkernel_enable: 0 -> 1 === [A] unpriv create loop hits the cap cleanly === (command: /tmp/vmsp_grow 100000 1000 -u [run_root; binary self-drops to uid 65534]) # uid=65534 count=100000 sample_every=1000 base_id=0x10000000 # ITER WIRE KVM_FREE FREE_COUNT ELAPSED_MS 0 142648 8791374426112 849671 0 FAILED iter=64 rc=-1 errno=59 (Too many references: can't splice) 1 142648 8791374426112 849671 1 GROW_EXIT=2 wire_after=142706 -> allocation stops at 64 live vmspaces with a CLEAN error return (ETOOMANYREFS); wire count stays at baseline; no runaway. === [B] cap arithmetic: destroy frees a slot === (command: /tmp/vmsp_cap as unpriv uid 1001) uid=1001 create #65 -> rc=-1 errno=59 (Too many references: can't splice) [cap hit] destroy(id=0x20000000) -> rc=0 errno=0 create after destroy -> rc=0 errno=0 (OK) [want 0: slot freed] === [C] legitimate usage unchanged: root raises the cap === vm.max_vkernel_vmspaces: 64 -> 100000 (command: /tmp/vmsp_grow 5000 1000 -u) # uid=65534 count=5000 sample_every=1000 base_id=0x10000000 # ITER WIRE KVM_FREE FREE_COUNT ELAPSED_MS 0 142762 8791374426112 849816 0 1000 144565 8791363940352 847825 97 2000 147155 8791355551744 845234 161 3000 149789 8791345065984 842600 209 4000 151589 8791334580224 840800 266 5000 154331 8791324094464 838058 313 # DONE created=5000 uid=65534 elapsed=313ms -- exiting, vkernel_exit must now reclaim all of it GROW_EXIT=0 vm.max_vkernel_vmspaces: 100000 -> 64 wire=144196 -> with the operator-set cap, an unpriv process creates 5000 vmspaces successfully; everything reclaimed at exit (wire back ~baseline). === [D] cap is per-process: two concurrent fillers === (command: /tmp/vmsp_cap & /tmp/vmsp_cap & wait) uid=0 create #65 -> rc=-1 errno=59 (Too many references: can't splice) [cap hit] destroy(id=0x20000000) -> rc=0 errno=0 create after destroy -> rc=0 errno=0 (OK) [want 0: slot freed] uid=0 create #65 -> rc=-1 errno=59 (Too many references: can't splice) [cap hit] destroy(id=0x20000000) -> rc=0 errno=0 create after destroy -> rc=0 errno=0 (OK) [want 0: slot freed] -> each process has its own limit; no cross-process interference. === restore === sysctl vm.vkernel_enable: 1 -> 0 (then: vm.sh reset with-src -- guest returned to clean snapshot kernel)