⬢ DragonFlyBSD Kernel Audit
DF-2233 / fixvalidation.log
← back to finding ↓ download raw
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.