{
 "finding_id": "DF-3314",
 "status": "reproduced",
 "reproduced": 1,
 "impact": "panic",
 "confidence": "certain",
 "verdict": "Use-after-free of the ieee80211vap when the last node reference outlives vap destruction: ieee80211_node_table_reset() (node.c:1977) unlinks a vaps nodes without clearing ni_associd or performing vap-dependent cleanup, the vap memory is then freed by ic_vap_delete, and the eventual final ieee80211_free_node() dereferences ni->ni_vap in three places (_ieee80211_free_node:1786 AID_CLR bit-clear write through a pointer read from the freed vap; node_free:1117 ratectl deinit; node_cleanup:1041-1082). Reproduced deterministically on the stock INVARIANTS guest with a software-radio KLD emulating an async driver whose tx completions arrive after ifconfig destroy: Fatal trap 9 ... Stopped at _ieee80211_free_node+0x2d: andl %esi,(%r8,%rax,4) -- exactly the AID_CLR write, with the base pointer read from marker-sprayed (0xb0) freed vap memory. A one-line associd-only fix moved the trap to node_free+0x18 (ratectl deref), proving the broader free-path deref family; the validated fix.diff (NODE_VAPGONE flag + full cleanup at table_reset while the vap is alive) makes the byte-identical PoC pass cleanly (RELEASE_RC=0, guest up, no traps). Primitive beyond the panic: a clear-one-bit-of-one-32bit-word write at a small attacker-influenced offset through an attacker-groomable base pointer (freed 2640-byte vap block is reclaimable); uid=0 escalation from a clear-only write was assessed and not achieved this run. Precondition (vap destroy/reset racing outstanding tx completions -- routine admin under load on async-driver hardware) keeps severity at Medium.",
 "exploit_chain": "STA vap associated (associd set at sta.c:1683) + driver-held node ref in flight -> ifconfig destroy: table_reset drops table ref, node survives unlinked with ni_associd intact, vap kfreed -> late tx-complete -> ieee80211_free_node -> _ieee80211_free_node reads iv_aid_bitmap from freed vap -> bit-clear write through stale/reclaimed pointer -> fatal trap (or silent corruption of whatever occupies the stale bitmap target). Grooming the freed vap block yields a constrained arbitrary bit-clear write; full uid=0 chain not developed (clear-only primitive).",
 "evidence": [
  "panic.txt: Fatal trap 9 ... Stopped at _ieee80211_free_node+0x2d: andl %esi,(%r8,%rax,4) (baseline run 1, with 0xb0 spray of the freed vap block)",
  "panic.2.txt: same trap/IP reproduced from a fresh vm.sh reset with-src (deterministic spray variant)",
  "run.log: full command sequence incl. the negative-evidence rates-IE run (discard beacon frame, bad scan->rates len 200) and the fw3.sta/spray/release transcript (associd 0xc001, ni_vap freed address)",
  "patched_run.txt: fix-v2 kernel, exact PoC, RELEASE_RC=0, associd 0x0 at every late completion, guest up",
  "fix.diff: NODE_VAPGONE fix (node.c + node.h), applied in-guest only",
  "fw3.c: software-radio KLD (beacon injector, AUTH/ASSOC injector, async-driver ref parking, exact-reclaim spray)"
 ],
 "kernel_refs": [
  "sys/netproto/802_11/wlan/ieee80211_node.c:1786-1790",
  "sys/netproto/802_11/wlan/ieee80211_node.c:1112-1122",
  "sys/netproto/802_11/wlan/ieee80211_node.c:1033-1110",
  "sys/netproto/802_11/wlan/ieee80211_node.c:1909-1938",
  "sys/netproto/802_11/wlan/ieee80211_node.c:1977-2012",
  "sys/netproto/802_11/wlan/ieee80211_sta.c:1683"
 ],
 "poc_changes": "Seed concept (from pass-2 analysis) was a remote rates-IE overflow via init_neighbor; live testing killed it (parse_beacon VERIFY_ELEMENT guard) and the effort pivoted to the vap-lifetime UAF, which static pass-2 analysis had flagged from the codes own hazard comment. fw3.c written from scratch on the DF-3282/3312 harness pattern; the associd state is set directly on the bss node (substitutes for a full MLME dance with a fake AP; the AUTH/ASSOC injector was also built and used to prove over-the-air associability on hostap). An associd-only fix was tried first and failed (trap moved to node_free+0x18), driving the NODE_VAPGONE v2 fix.",
 "attempts": 8,
 "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": 4800,
 "guest_dirty": 0,
 "build_cmd": "sh findings/poc/DF-3314/build.sh  (guest: cd /root/fw3 && make SYSDIR=/usr/src/sys)",
 "run_cmd": "kldload /root/fw3/fw3.ko && ifconfig wlan create wlandev fw3_0 wlanmode sta ssid fw3sta mode 11g channel 1 up && sysctl kern.fw3_sta=1 && ifconfig wlan0 destroy && sysctl kern.fw3_spray=1 && sysctl kern.fw3_release=1  # expect: Fatal trap 9 at _ieee80211_free_node+0x2d",
 "code_hash": "fff74051fc332fc88310acdbbf0be690efd77af1989a048a9160d1c855938576",
 "notes": "Negative result recorded: the remote rates-IE overflow candidate (node.c:1559 -> setup_rates, would upgrade DF-0581) is unreachable -- ieee80211_parse_beacons IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE) (input.c:667) is checked by every caller (adhoc.c:697, mesh.c:1904, tdma.c:336; hostap.c:2061, sta.c:1666 VERIFY directly); proven live (discard beacon frame, bad scan->rates len 200). Guest reset clean after validation (stock kernel #0 confirmed by uname).",
 "recommended_fix": "At vap detach, run all vap-dependent node cleanup while ni_vap is still valid (ic_node_cleanup + ratectl deinit in ieee80211_node_table_reset) and mark nodes IEEE80211_NODE_VAPGONE so node_free() skips those calls; clear ni_associd in node_reclaims unlink branch (fix.diff).",
 "fix_status": "fixed",
 "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #1: Thu Sep 10 15:53:57 UTC 2026   root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64",
 "fix_baseline_reproduced": 1,
 "fix_patched_reproduced": 0,
 "fix_verdict": "fix.diff v2 applied in guest /usr/src, make nativekernel + installkernel + reboot (#1 15:53:57); byte-identical PoC re-run: RELEASE_RC=0, associd cleared at detach (0x0 in release log), guest up, dmesg trap-free, module unloads. Baseline on stock #0 traps at _ieee80211_free_node+0x2d. v1 associd-only fix insufficient (trap moved to node_free+0x18 ratectl deref) -- documented in VERDICT.md.",
 "fix_evidence": "findings/poc/DF-3314/patched_run.txt; findings/poc/DF-3314/panic.txt; findings/poc/DF-3314/VERDICT.md (fix narrative incl. v1 failure)"
}