DF-4760 / fix_run.log
# DF-4760 fix validation. Final fix = fix.diff (v2) in this pack:
# MOD_UNLOAD asks a live daemon to leave ONCE (single daemonrq_return),
# waits a bounded 5*hz ticks, and returns EBUSY with NOTHING torn down
# if the daemon device is still open; free_vinum()'s old per-tick
# queue+sleep loop is replaced by a single queued request + bounded wait.
# Module rebuilt standalone from patched /usr/src (BUILD_RC=0), installed
# to /boot/kernel/vinum.ko, loaded. Guest: DF 6.5-DEVELOPMENT #0 stock kernel.
==== A) malicious holder (root process holds /dev/vinum/controld, no daemon) ====
$ vmstat -m | grep -i devbuf
devbuf 219 224K 0 390M 236
$ /tmp/hold_daemon 20 &
[holder] opened /dev/vinum/controld fd=3 (VF_DAEMONOPEN set); holding for 20s
$ T0=$(date +%s); kldunload vinum; RC=$?; T1=$(date +%s)
kldunload: can't unload file: Device busy
$ echo RC=$RC elapsed=$((T1-T0))s
RC=1 elapsed=10s <-- BOUNDED (baseline: wedged for the full 300 s hold
and only released by the holder's close)
$ kldstat | grep -i vinum
8 0 0xffffffff82600000 10000 vinum.ko <-- module intact, nothing torn down
$ vmstat -m | grep -i devbuf
devbuf 232 246K 0 390M 289
<-- +~10 allocations total (ONE daemonrq_return node +
noise). BASELINE leaked +14,600 nodes (~350 KB) for
a 300 s hold, permanently (devbuf 5.10K -> 19.7K).
$ sleep 20; kldunload vinum; echo RC2=$?
RC2=0 <-- after the holder closes, clean unload
kldstat | grep -i vinum || echo gone --> module gone cleanly
==== B) legitimate vinum daemon alive (started by `vinum create`) ====
$ ps -axww | grep '[v]inum daemon'
912 ?? D0s 0:00.01 vinum: vinum daemon (vinum)
$ T0=$(date +%s); kldunload vinum; RC=$?; T1=$(date +%s)
$ echo RC=$RC elapsed=$((T1-T0))s
RC=0 elapsed=0s <-- asked once, daemon exited + closed, unload proceeded
$ kldstat | grep -i vinum || echo gone
module gone cleanly (daemon asked once, left)
$ ps -axww | grep '[v]inum daemon' || echo "daemon exited"
daemon exited
$ dmesg | tail -1
vinum: unloaded
$ vmstat -m | grep -i devbuf
devbuf 223 231K 0 390M 263 <-- no leak
==== BASELINE (stock module) for comparison (runs 1-4, same guest image) ====
# run-2 (40 s hold): kldunload caught at t=8 in state D2 wchan "vstop"
# (the free_vinum tsleep loop); devbuf +1,850 daemonq nodes; unload only
# completed when the holder closed.
# run-4 (300 s hold): "vinum: unloaded" logged exactly 300 s after holder
# open; devbuf 5.10K -> 19.7K allocations (+14,600 leaked struct daemonq,
# ~350 KB, never freed even after unload); while stuck, kldstat and
# vmstat -m blocked system-wide (kldunload holds the kernel linker lock).