⬢ DragonFlyBSD Kernel Audit
DF-4064 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-4064",
  "status": "inconclusive",
  "reproduced": 0,
  "impact": "none",
  "confidence": "certain",
  "verdict": "Mechanism PROVEN on the guest kernel by deterministic replica of if_fxp.cs exact callout/serializer protocol; fxp-specific runtime hardware/timing-gated (inconclusive per family convention, same standard as em(4) DF-3715 and emx(4) DF-3738). fxp_stat_timer is a NON-MPSAFE callout (plain callout_init, if_fxp.c:399 - unlike em/emx, its callback also runs under the MP lock, kern_timeout.c:575-580); fxp_tick (if_fxp.c:1441-1555) BLOCKS in lwkt_serialize_enter at :1449 and self re-arms INSIDE the serializer at :1552; fxp_stop tears it down with callout_stop at :1577 while holding the serializer (:1568; callers: fxp_detach :738, fxp_shutdown :787, fxp_suspend :805, fxp_init :1651 -> every ifconfig up + watchdog, SIOCSIFFLAGS down :2078). DragonFly callout_stop synchronously waits for an in-progress callback (kern_timeout.c:1091 -> sync=1, ssleep costp :920) while lwkt_serialize_enter blocks (tsleep slize, lwkt_serialize.c:234). Replica on the guest: the fxp_stop-shaped stopper wedges permanently (ps: 231052 D0 costp sysctl + softclock 5 B5 slize), console ends at the pre-callout_stop marker. Driver-level attempt on REAL emulated fxp0 (QEMU i82557b via temp launcher vm_fxp.sh, vm.sh untouched; fxp0+miibus0 attached, tick proven firing via the rx_idle->mc_setup->watchdog device timeout chain) could not reach the park window across four adversarial campaigns (~10 min) - structural on this kernel: the timer is always armed from the fxp netisr CPU, whose softclock only runs when the ifnet queue is drained (serializer free), and no path sleeps holding the serializer before callout_stop (fxp_stop stop-first ordering). Fix validated at protocol level on the same guest: try-enter + 1-tick retry shape = the same stop completes cleanly, pending=0, module unloads.",
  "exploit_chain": "",
  "evidence": "findings/poc/DF-4064/VERDICT.md; run.log (replica transcript: fxr: handler BLOCKED ... entering callout_stop then silence + ps 231052 D0 costp sysctl / softclock 5 B5 slize); run.patched.log (fxrf: callout_stop RETURNED cleanly, pending=0 + FIXED_SHAPE_OK); boot-fxp-full.log (real fxp0 attach on i82557b + race campaigns); build.log / build.fixed.log (-Werror clean)",
  "kernel_refs": [
    "sys/dev/netif/fxp/if_fxp.c:399",
    "sys/dev/netif/fxp/if_fxp.c:1449",
    "sys/dev/netif/fxp/if_fxp.c:1552",
    "sys/dev/netif/fxp/if_fxp.c:1577",
    "sys/kern/kern_timeout.c:920",
    "sys/kern/kern_timeout.c:1091",
    "sys/kern/lwkt_serialize.c:234"
  ],
  "poc_changes": "No seed PoC. Authored fxp_callout_replica.ko (out-of-tree kmodule replicating the fxp callout protocol; adapted from DF-3738s emx replica with fxp line citations and the fxp-specific NON-MPSAFE callout_init fidelity) plus fxp_callout_replica_fixed.c (fix.diff protocol). Driver-level campaigns fxp_race*.sh authored for the real i82557b fxp0; the resulting structural negative (same-CPU callout wheel closes the ifconfig window) is documented in VERDICT.md.",
  "attempts": 4,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul  2 06:02:54 UTC 2026 x86_64",
  "runtime_sec": 2100,
  "guest_dirty": 0,
  "build_cmd": "guest: cd /root/fxpkmod && make; cd /root/fxpkmod_fixed && make",
  "run_cmd": "vm_fxp.sh (real fxp0 campaigns) + kldload fxp_callout_replica.ko; sysctl kern.fxr.arm=1; sysctl kern.fxr.stop_blk=1  # wedge; then vm.sh reset with-src; kldload fxp_callout_replica_fixed.ko; sysctl kern.fxrf.arm=1; sysctl kern.fxrf.stop_blk=1",
  "code_hash": "08fba236d3236c11815a9e1339b9322e59e9d5fe8e2e95cd468c27397970c45f",
  "notes": "Triggers on real fxp hardware from ordinary privileged operations (ifconfig up/down, detach, suspend/resume, watchdog reinit) IF the tick parks - any change arming the callout off-CPU or sleeping while serializer-held re-opens the deadlock; impact is permanent system degradation (two wedged threads + CPU-wide callout starvation + MP-lock holder). Family precedent: DF-3715 (em), DF-3738 (emx).",
  "recommended_fix": "Make fxp_tick() non-blocking: lwkt_serialize_try() with a 1-tick callout_reset retry (emx_txgc_timer pattern).",
  "fix_status": "fixed",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "Protocol-level validation on the guest: baseline (current fxp_tick shape) = permanent AB-BA wedge (stopper D0 costp, softclock 5 B5 slize); patched shape (exact fix.diff protocol: try + 1-tick retry + re-arm under serializer) = the same fxp_stop-shaped callout_stop completes, pending=0, module unloads cleanly. Full driver-kernel rebuild validation not possible in-module without rebuilding the in-kernel fxp driver.",
  "fix_evidence": "findings/poc/DF-4064/fix.diff; run.patched.log fxrf: callout_stop RETURNED cleanly, pending=0 + FIXED_SHAPE_OK"
}