DF-3968 / trigger.c
/* * DF-3968 trigger sketch — rt2661_scan_end NULL-vap deref race * ============================================================ * rt2661.c:2839-2848: * rt2661_scan_end(struct ieee80211com *ic) * { * struct rt2661_softc *sc = ic->ic_softc; * struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); // may be NULL * * rt2661_enable_tsf_sync(sc); * rt2661_set_bssid(sc, vap->iv_bss->ni_bssid); // NULL deref * * rt2661.c:2743-2750 (rt2661_enable_tsf_sync): * struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); // may be NULL * ... * if (vap->iv_opmode != IEEE80211_M_STA) { // NULL deref * * The call site races vap destruction: * sys/netproto/802_11/wlan/ieee80211_scan_sw.c:781-797 (scan_end): * IEEE80211_UNLOCK(ic); * ic->ic_scan_end(ic); <-- driver called UNLOCKED * IEEE80211_LOCK(ic); * /* XXX scan state can change! Re-validate scan state! * / * while ieee80211_vap_delete -> ieee80211_scan_vdetach * (ieee80211_scan.c:140-155) removes the vap from ic_vaps under the lock. * If the only vap is destroyed inside that window, TAILQ_FIRST returns NULL * and the driver dereferences it: Fatal trap 12 (NULL+offsetof(iv_bss)). * * On-hardware trigger (needs a Ralink NIC; guest has none): * # while true; do * # ifconfig wlan0 create wlandev ral0 wlanmode sta * # (wpa_supplicant associates; background scan active) * # ifconfig wlan0 destroy & # race last-vap delete vs scan end * # done * Window is the unlocked driver call; repeat until hit (typically seconds). */ #include <stdio.h> int main(void) { printf("hardware-gated: see header comment for the on-target recipe\n"); return 0; } |