DF-3903 / verdict.json
{ "finding_id": "DF-3903", "status": "inconclusive", "reproduced": 0, "impact": "none", "confidence": "certain", "verdict": "Mechanism PROVEN on the guest kernel on the FIRST attempt by a deterministic replica of if_sk.cs exact callout/serializer protocol; sk-specific runtime hardware-gated (no SysKonnect NIC on the audit guest) -> inconclusive per family convention. sk_tick/sk_yukon_tick (sys/dev/netif/sk/if_sk.c:2032/:2081) are the callbacks of a PLAIN (non-MPSAFE) callout (callout_init at :1311 -> callback executes under the Giant MP lock, kern_timeout.c:583) and do a BLOCKING lwkt_serialize_enter(ifp->if_serializer) at :2041/:2087 with self re-arm at :2067/:2089 (sk_yukon_tick unconditional, 1 Hz from sk_init :2766); sk_stop() tears the callout down with the synchronous callout_stop() at :2782 while holding that same serializer (ASSERT_SERIALIZED :2778; callers: sk_ioctl :992, sk_init :2606 via SIOCSIFMTU :977 / SIOCSIFFLAGS :989 / sk_ifmedia_upd :937, sk_watchdog :1758, sk_detach :1540); DragonFly callout_stop synchronously waits for an INPROG callback (kern_timeout.c:1091 -> :859-932, ssleep costp at :920). A tick dequeued and parked on the serializer therefore deadlocks against the stopper (AB-BA) - and since the serializer is the one card-global lock shared by BOTH ports of a dual-port card (ether_ifattach :1281), both interfaces wedge. Kernel-module replica on the guest: with the sk-shaped handler parked, callout_stop NEVER returned - stopper observed D0/wchan costp (pid 2051), softclock 1 observed B1/wchan slize holding the Giant MP lock (non-MPSAFE callout, aggravation shared with dc DF-3850), serial console shows fired=2 ran=1 then the terminal marker line, and the wedge survived a clean shutdown attempt (vm.sh down had to SIGKILL QEMU). 7th member of the DF-3715/3738/3760/3776/3806/3850 family, now live-proven 8 times with zero false triggers. Fix-shape validation on a fresh guest with the exact fix.diff protocol (lwkt_serialize_try + 1-tick retry): callout_stop returned with pending=0 under both interleave shapes, including cross-CPU contention (fired=312 ran=5 retry=307, 0 parks) - deadlock eliminated.", "exploit_chain": "", "evidence": "findings/poc/DF-3903/VERDICT.md; run.log (D0 costp stopper + B1 slize softclock 1); console_markers.txt (fired=2 ran=1 + terminal marker line from dfbsd-qemu/boot.log); build_shared.log (modules built clean under -Werror); fix_validation.log (fixed shape: callout_stop RETURNED, pending=0, 312 fires/307 retries/0 parks); env.txt (guest uname); fix.diff (try-enter + 1-tick retry for sk_tick and sk_yukon_tick)", "kernel_refs": [ "sys/dev/netif/sk/if_sk.c:1311", "sys/dev/netif/sk/if_sk.c:2041", "sys/dev/netif/sk/if_sk.c:2067", "sys/dev/netif/sk/if_sk.c:2087", "sys/dev/netif/sk/if_sk.c:2089", "sys/dev/netif/sk/if_sk.c:2778", "sys/dev/netif/sk/if_sk.c:2782", "sys/dev/netif/sk/if_sk.c:977", "sys/dev/netif/sk/if_sk.c:2606", "sys/kern/kern_timeout.c:583", "sys/kern/kern_timeout.c:920", "sys/kern/kern_timeout.c:1091", "sys/kern/lwkt_serialize.c:105" ], "poc_changes": "No seed PoC. Authored sk_callout_replica.ko / sk_callout_replica_fixed.ko (out-of-tree kmodules replicating the if_sk.c callout protocol, including the plain/non-MPSAFE callout_init at :1311) because the guest has no sk hardware; the deadlock is in the generic protocol sk uses, so the replica exercises the identical kernel paths.", "attempts": 1, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64", "runtime_sec": 1800, "guest_dirty": 0, "build_cmd": "cd /root/kmod && make (KMOD=sk_callout_replica SRCS=sk_callout_replica.c; then sk_callout_replica_fixed)", "run_cmd": "vm.sh run_root kldload /root/kmod/sk_callout_replica.ko; sysctl kern.skreplica_arm=1; sleep 1; (sysctl kern.skreplica_stop=1 >/dev/null 2>&1 &) then ps from a second session", "code_hash": "39d596712049bb2acfff13a9021c8ac6e792e8cdfd1b543c79f02c2028cf7094", "notes": "sk(4) instance of the DF-3715/3738/3760/3776/3806/3850 AB-BA callout family. Aggravations: (1) sk_tick_timer is non-MPSAFE (parked softclock holds the Giant MP lock - the wedge defeated the guests clean shutdown); (2) the serializer is card-global, so a single ports stop wedges BOTH ports of a dual-port SK-98xx. Triggers: ifconfig skX down/up, MTU change while running, media change, watchdog reinit, detach/kldunload, suspend/resume, shutdown. RX-length (DF-3604 family) checked and NOT present: sk_rxeof bounds total_len at :1859 and the jumbo pool sizes match exactly (SK_JLEN-SK_JUMBO_FRAMELEN == ETHER_ALIGN). Guest reset to with-src snapshot after verification.", "recommended_fix": "Make sk_tick()/sk_yukon_tick() non-blocking: lwkt_serialize_try() with a 1-tick callout_reset retry (validated live at protocol level).", "fix_status": "inconclusive", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff authored against the read-only sys/ tree: sk_tick and sk_yukon_tick use lwkt_serialize_try + 1-tick retry. Validated at protocol level on the guest with sk_callout_replica_fixed.ko (callout_stop returns, pending==0, 312 fires / 307 retries / 0 parks while the serializer was held 3s from another CPU). Driver-level validation impossible on this guest (no sk NIC).", "fix_evidence": "findings/poc/DF-3903/fix.diff; findings/poc/DF-3903/fix_validation.log" } |