{
 "finding_id": "DF-3380",
 "status": "reproduced",
 "reproduced": 1,
 "impact": "panic",
 "confidence": "certain",
 "verdict": "Deterministic kernel panic on INVARIANTS kernels ~5s after any successful pfsync syncdev configuration: pfsyncioctl(SIOCSETPFSYNC) arms sc_bulkfail_tmo (if_pfsync.c:1168) with handler pfsync_bulkfail, which executes in the per-CPU softclock_handler thread (kern_timeout.c:491) holding no lwkt tokens and immediately trips ASSERT_LWKT_TOKEN_HELD(&pf_token) (if_pfsync.c:1621). Reproduced on the stock INVARIANTS guest (kernel #0) with a 60-line SIOCSETPFSYNC trigger and syncdev=lo0: panic: assertion LWKT_TOKEN_HELD_ANY(&pf_token) failed in pfsync_bulkfail at if_pfsync.c:1621, guest dead in DDB. Same family: pfsync_timeout->pfsync_sendout assert (1673), pfsync_bulk_update entry assert (1552), and clone_destroy uses non-draining callout_stop (203-206) before kfree(sc) (222). Privileged (SIOCSETPFSYNC is caps-gated) => local root-config DoS of debug/INVARIANTS kernels; on production kernels the handlers run unserialized against pf_token holders instead (benign only while the sync engine stays dead per DF-3379). Fix validated: nativekernel rebuild with fix.diff (token acquire/release in the three callout handlers + callout_drain in destroy) -> same trigger, callout fires and completes (dmesg shows its CARP demotion side-effect), no panic, guest stays up.",
 "exploit_chain": "root: kldload pf; ifconfig pfsync0 create; SIOCSETPFSYNC(syncdev=lo0) -> sc_bulkfail_tmo armed 5*hz -> softclock thread fires pfsync_bulkfail without pf_token -> KKASSERT panic (INVARIANTS kernels; GENERIC in this tree ships options INVARIANTS). No memory-corruption primitive: post-assert code paths no-op on pfsyncif==NULL (DF-3379).",
 "evidence": [
  "panic.txt: panic: assertion LWKT_TOKEN_HELD_ANY(&pf_token) failed in pfsync_bulkfail at /usr/src/sys/net/pf/if_pfsync.c:1621 with softclock_handler backtrace, cpuid=2, ~5s after trigger printed callout armed",
  "run.baseline.log (=run.log): full baseline session incl. timestamps and the ENOBUFS negative variants (tap0/vtnet0 fail earlier at in_addmulti, if_pfsync.c:1143-1148)",
  "run.fixed.log (=fix_run.log): patched kernel #1 same trigger -> SURVIVED_CALLOUT + dmesg pfsync0 demoted group carp to 1 proving the handler ran to completion under the acquired token",
  "boot_panic_full.log: serial console capture of the panic boot",
  "fix.diff: callout_drain in clone_destroy + lwkt_gettoken/reltoken in pfsync_timeout/pfsync_bulk_update/pfsync_bulkfail replacing the asserts",
  "build.log/build.log.final/fix_build.log: if_pfsync.o compiled into the in-guest nativekernel build, install completed 2026-09-11 21:30:40Z, kernel #1 21:24:50Z booted for validation"
 ],
 "kernel_refs": [
  "sys/net/pf/if_pfsync.c:1621",
  "sys/net/pf/if_pfsync.c:1164-1170",
  "sys/net/pf/if_pfsync.c:1514-1522",
  "sys/net/pf/if_pfsync.c:1552",
  "sys/net/pf/if_pfsync.c:1673",
  "sys/net/pf/if_pfsync.c:203-206",
  "sys/net/pf/if_pfsync.c:222",
  "sys/kern/kern_timeout.c:491"
 ],
 "poc_changes": "No PoC seed existed (new finding). Trigger written from scratch: direct SIOCSETPFSYNC ioctl (base ifconfig has no pfsync support at all in DF); syncdev had to be lo0 because tap0/vtnet0 make pfsync_in_addmulti fail (ENOBUFS) before the callout is armed.",
 "attempts": 4,
 "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64 (baseline panic) / #1: Fri Sep 11 21:24:50 UTC 2026 (fix validation)",
 "runtime_sec": 1800,
 "guest_dirty": 0,
 "build_cmd": "cc -o /root/trigger_df3380 /root/trigger_df3380.c",
 "run_cmd": "kldload pf; ifconfig pfsync0 create; /root/trigger_df3380 lo0; sleep 10 (panic ~5s after callout armed)",
 "code_hash": "ca6c41ab659632b18809c90b48acb93f0f458c3ee26076c896db37d7fa12b717",
 "notes": "Guest reset with-src performed after validation. ifconfig pfsync0 destroy returns EINVAL with membership held (unrelated). The panic fires on CPU2s softclock thread while the ioctl ran on another CPU - callouts armed from SIOCSETPFSYNC fire on arbitrary CPUs, consistent with the DF-3299 wrong-CPU/callout-context family. 4 attempts = tap0 (ENOBUFS pre-arm), vtnet0 (ENOBUFS pre-arm), lo0 (panic), lo0-on-patched-kernel (survives).",
 "recommended_fix": "Acquire pf_token in the pfsync callout handlers (pfsync_timeout/pfsync_bulk_update/pfsync_bulkfail) instead of asserting it, and use callout_drain() in pfsync_clone_destroy (see fix.diff).",
 "fix_status": "fixed",
 "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #1: Fri Sep 11 21:24:50 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64",
 "fix_baseline_reproduced": 1,
 "fix_patched_reproduced": 0,
 "fix_verdict": "Baseline stock kernel #0: deterministic panic at if_pfsync.c:1621 (guest dead in DDB). Patched kernel #1 (fix.diff applied in-guest, make nativekernel + installkernel + reboot): identical trigger arms the callout, pfsync_bulkfail executes fully (dmesg demote side-effect visible), no panic, guest stays up across the 12s window. Panic gone; fix validated.",
 "fix_evidence": "run.baseline.log vs run.fixed.log; build.log.final (if_pfsync.o in build, install completed); dmesg line pfsync0 demoted group carp to 1 on patched run proves handler execution rather than silent skip"
}