DF-3310 / verdict.json
{ "finding_id": "DF-3310", "status": "not_reproduced", "reproduced": 0, "impact": "none", "confidence": "certain", "verdict": "Code defect certain by source proof: wg_socket_init() (if_wg.c:974) re-runs lockinit() on the live sc_socket.so_lock while wg_send() (if_wg.c:1145) may hold it shared (lockinit zeroes lk_count -> ghost shared holder -> permanent exclusive starvation of wg_socket_set_cookie/wg_socket_uninit), and closes/installs the UDP sockets (if_wg.c:976-982) without taking so_lock at all. Dynamic campaign: ~8900 successful port changes raced against sustained encrypted ping -f traffic across async-UDP and sosend_async=0 (sync) configs with live so_lock-EXCLUSIVE probes (SIOCSWG cookie, timeout-guarded) - no wedge, panic, or probe timeout observed; sub-1%-duty-cycle overlap window not hit within budget. Realistic ceiling if hit: permanent wg ioctl/destroy wedge (local DoS) or INVARIANTS panic; trigger itself requires a privileged SIOCSWG, so no unpriv->root path.", "exploit_chain": "", "evidence": [ "findings/poc/DF-3310/VERDICT.md (code proof: if_wg.c:974 vs kern_lock.c:1300 lockinit semantics)", "findings/poc/DF-3310/run.log/.2/.3 (3 campaigns: 8000 async / 600+probes / 300 sync+probes, all clean)", "findings/poc/DF-3310/fix.diff (init so_lock once at clone_create; EXCLUSIVE around close/swap)" ], "kernel_refs": [ "sys/net/wg/if_wg.c:974", "sys/net/wg/if_wg.c:976", "sys/net/wg/if_wg.c:1145", "sys/net/wg/if_wg.c:1063", "sys/net/wg/if_wg.c:2557", "sys/kern/kern_lock.c:1300" ], "poc_changes": "No wg(8) on guest: wrote wgtool.c (SIOCSWG/SIOCGWG ioctl driver, struct layout copied byte-exact from sys/net/wg/if_wg.h; includes embedded X25519 that turned out buggy and was bypassed by using RFC 7748 6.1 fixed keypairs - kernel does all DH). raceB2.sh adds a live so_lock-EXCLUSIVE detector (SIOCSWG cookie under timeout(1)) that the seed sketch lacked.", "attempts": 3, "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": "cc -O2 -o wgtool wgtool.c", "run_cmd": "sh setupB.sh; ping -f 10.7.0.2 & sysctl net.inet.udp.sosend_async=0; sh raceB2.sh 300 0", "code_hash": "c467f9e3214df90b66aee38a9441141e0beb846f4461375604d03bec58671742", "notes": "Known findings DF-0315..DF-0319 (pass 1) all remain unfixed in sys/net/wg/if_wg.c as of this pass-2 audit. Guest left clean (vm.sh reset with-src after campaign).", "recommended_fix": "Initialize sc_socket.so_lock once in wg_clone_create(); in wg_socket_init() take it LK_EXCLUSIVE around closing old sockets and installing new pointers; never re-lockinit a live lock (see fix.diff).", "fix_status": "not_testable", "fix_kernel_uname": "", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "Race never manifested dynamically in budget, so no baseline/patched A/B was possible; fix is by-inspection correctness (single lockinit lifetime + exclusive serialization matches wg_socket_uninits existing protocol).", "fix_evidence": "findings/poc/DF-3310/fix.diff" } |