DF-2233 / fixvalidation.log
DF-2233 fix validation -- outputs (verbatim; per-boot guest files are wiped by
vm.sh snapshot reverts, outputs preserved from the session record)
Fixed tree = pristine sys/libiconv/iconv.c + findings/poc/DF-2233/fix.diff
(lock held across traversal/dispatch + iconv_refs in-flight drain guard),
modules rebuilt from patched /usr/src (race2233.ko, libiconvfix.ko).
---------------------------------------------------------------------------
SOAK A (fix soaks, first boot): fixed libiconvfix.ko, 4 x churnadd walk
hammer (kern.iconv.add EINVAL probes = the exact baseline walk load), NO
unload, 90 s:
=== SOAK A: fixed libiconvfix, walk hammer, NO unload (90s)
soakA survivors: (4 hammer processes ran to completion)
guest UP after 90 s, zero kernel messages. -> CLEAN
---------------------------------------------------------------------------
SOAK B2 (clean rerun, second boot): fixed race2233.ko loaded, 3 in-kernel
walkers (debug.race2233_run) + 2 churnadd bad register/free churn, NO
unload; polled every 20 s:
51605851 / 104038984 / 157595157 / 213254927 / 265472494 / 316798072
(debug.race2233_walks after 20/40/60/80/100/120 s)
guest UP the whole time. -> CLEAN
---------------------------------------------------------------------------
SOAK C3 (third boot): fixed module + walkers + churn running, then a
240 s kldunload storm (132906 attempts):
soakC3: 240s unload storm: 0 succeeded, 0 EBUSY, 132906 other-rc
(the first storm unload succeeded and drained cleanly in a refs==0 gap;
afterwards the module was absent and all walker/churn callers failed
with clean unknown-oid errors; remaining attempts rc!=0 "not loaded")
guest UP after the full storm. -> CLEAN
[intermediate fix-v1 (traversal locking only, no drain guard) results,
for the record: 90 s walk hammer + unload loop died with
panic: lockmgr: pid 1472, not exclusive lock holder ... unlocking
iconv_sysctl_add() at iconv_sysctl_add+0x196
and a second run died with
panic: assertion "(count & (LKC_EXREQ | LKC_UPREQ)) == 0 ..." failed
in lockuninit at kern_lock.c:1332
iconv_mod_handler() <- linker_file_unload() <- sys_kldunload()
-- i.e. kldunload tearing the lock/module under in-flight callers; this
motivated the iconv_refs drain guard added in the final fix.diff.]
---------------------------------------------------------------------------
SOAK C4 (fourth boot): supervisor restarting walkers after every reload,
180 s:
soakC4: 180s supervised storm: 1 unload+reload cycles completed alive
The script finished alive; ~4 s later the guest rebooted silently once
(no trap on serial) -- the documented residual micro-race: a caller
whose iconv_refs increment lands after the unloader's final check is
not drained and the module can be unmapped under it. Generic DragonFly
kldunload-has-no-drain-API limitation; needs linker-level support.
---------------------------------------------------------------------------
BASELINE vs FIXED:
baseline (pristine): panic "Stopped at iconv_lookupconv+0x30:
movq 0x800(%rsi),%rdi" (freed/NULLed converter class deref during
lockless walk) in < 45 s, reproduced twice on independent boots;
plus one silent hard death under the bundled-module unload rig.
fixed: that signature NEVER reappears. Soaks A/B2 (no unload) fully
clean (316M+ walks). Unload storms survive 240 s; residual
nanosecond teardown window documented above (one silent reboot
after a max-aggression supervised storm).
FUNCTIONAL CONTROLS (fixed build): successful direct opens still work
(debug.race2233_doopens=1 run completes, rh_opens > 0), kern.iconv.add
30-char registration still succeeds (csid assigned), cslist read returns
the expected pairs.