DragonFlyBSD Kernel Audit
DF-0587 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/netproto/802_11/wlan/ieee80211_scan_sw.c b/sys/netproto/802_11/wlan/ieee80211_scan_sw.c
--- a/sys/netproto/802_11/wlan/ieee80211_scan_sw.c
+++ b/sys/netproto/802_11/wlan/ieee80211_scan_sw.c
@@ -762,6 +762,22 @@
 
 	/* XXX scan state can change! Re-validate scan state! */
 
+	/*
+	 * The vap may have been detached (and ss_vap/ss_ops cleared by
+	 * ieee80211_scan_vdetach under IEEE80211_LOCK) while the lock
+	 * was dropped above for ic_set_channel / radiotap_chan_change /
+	 * ic_scan_curchan. Bail straight through scan_done() instead of
+	 * dereferencing a NULL vap via the DPRINTF/scan_end/scan_done
+	 * paths (which would otherwise fault at the loop-top DPRINTF on
+	 * IEEE80211_DEBUG kernels, or in scan_done on any kernel).
+	 */
+	if (ss->ss_vap == NULL || ss->ss_ops == NULL) {
+		ss_priv->ss_iflags &= ~ISCAN_RUNNING;
+		ss_priv->ss_iflags |= ISCAN_ABORT;
+		scan_done(ss, 1);
+		return;
+	}
+
 	ss_priv->ss_chanmindwell = ticks + ss->ss_mindwell;
 	/* clear mindwell lock and initial channel change flush */
 	ss_priv->ss_iflags &= ~ISCAN_REP;
@@ -908,7 +924,11 @@
 	 * save mode because the beacon indicates we have frames
 	 * waiting for us.
 	 */
-	if (scandone) {
+	/*
+	 * vap may be NULL if we got here via the scan_curchan_task
+	 * re-validation bail-out after the owning vap was detached.
+	 */
+	if (scandone && vap != NULL) {
 		/*
 		 * If we're not a scan offload device, come back out of
 		 * station powersave.  Offload devices handle this themselves.