net80211: make sure to not start a BGSCAN if not enabled

On drivers not supporting background scanning (not having announced
IEEE80211_C_BGSCAN) we repeatedly have seen scanning issues and
BGSCAN was "on" according to, e.g., ddb show com /a.

Turns out there are multiple problems:
(a) the ioctl scanreq code can pass IEEE80211_[IOC_]SCAN_BGSCAN in
    (ifconfig wlanX scan will do so by default).  That flag ends up
    on flags in the scanning code which have no other checks, and
    we are doing a BGSCAN.
    So make sure BGSCAN is announced by the driver and enabled
    (and it's STA mode for the full check) or filter the BGSCAN out.

(b) ieee80211_bg_scan() never checked if background scanning was
    available/enabled.  Do so now.

(c) ieee80211_swscan_start_scan_locked() as a consequence of (a) would
    start the BGSCAN unconditionally.  Also check for BGSCAN to be
    available/enabled here.

Lastly, we should no longer reach ieee80211_swscan_bg_scan() without
background scanning being available/enabled, so document that fact
by placing a KASSERT.  That will also help in case future changes
will open a new hole or there are further which I have not noticed.

Sponsored by:	The FreeBSD Foundation
MFC after:	3 days
Reviewed by:	adrian
Differential Revision: https://reviews.freebsd.org/D50513
This commit is contained in:
Bjoern A. Zeeb 2025-05-24 17:01:59 +00:00
parent 54d0e1772f
commit 32af70fae8
3 changed files with 32 additions and 1 deletions

View file

@ -2598,6 +2598,18 @@ ieee80211_scanreq(struct ieee80211vap *vap, struct ieee80211_scan_req *sr)
return EINVAL;
/* cleanse flags just in case, could reject if invalid flags */
sr->sr_flags &= IEEE80211_IOC_SCAN_FLAGS;
/*
* If the driver does not support BGSCAN, or BGSCAN is disabled
* do not allow the IEEE80211_SCAN_BGSCAN flag to go through
* to avoid accidentally enabling BGSCANs.
* Also if not STA mode [see ieee80211_vap_setup()].
*/
if ((vap->iv_caps & IEEE80211_C_BGSCAN) == 0 ||
(vap->iv_flags & IEEE80211_F_BGSCAN) == 0 ||
vap->iv_opmode != IEEE80211_M_STA)
sr->sr_flags &= ~IEEE80211_IOC_SCAN_BGSCAN;
/*
* Add an implicit NOPICK if the vap is not marked UP. This
* allows applications to scan without joining a bss (or picking

View file

@ -428,6 +428,19 @@ ieee80211_bg_scan(struct ieee80211vap *vap, int flags)
// IEEE80211_UNLOCK_ASSERT(sc);
/*
* If the driver has not announced BGSCAN capabilities
* or BGSCAN is disabled do not attempt to start a bg_scan.
* IEEE80211_F_BGSCAN only gets set if IEEE80211_C_BGSCAN
* was set by the driver, so no need to check for both here.
*/
if ((vap->iv_flags & IEEE80211_F_BGSCAN) == 0) {
IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
"%s: BGSCAN not enabled; not starting bg_scan\n",
__func__);
return (0);
}
scan = ieee80211_scanner_get(vap->iv_opmode);
if (scan == NULL) {
IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,

View file

@ -201,7 +201,9 @@ ieee80211_swscan_start_scan_locked(const struct ieee80211_scanner *scan,
vap->iv_stats.is_scan_passive++;
if (flags & IEEE80211_SCAN_FLUSH)
ss->ss_ops->scan_flush(ss);
if (flags & IEEE80211_SCAN_BGSCAN)
/* Only BGSCAN if enabled and requested. */
if ((vap->iv_flags & IEEE80211_F_BGSCAN) != 0 &&
(flags & IEEE80211_SCAN_BGSCAN) != 0)
ic->ic_flags_ext |= IEEE80211_FEXT_BGSCAN;
/* Set duration for this particular scan */
@ -339,6 +341,10 @@ ieee80211_swscan_bg_scan(const struct ieee80211_scanner *scan,
// IEEE80211_UNLOCK_ASSERT(ic);
IEEE80211_LOCK(ic);
KASSERT((vap->iv_flags & IEEE80211_F_BGSCAN) != 0,
("%s: vap %p iv_flags %#010x no IEEE80211_F_BGSCAN set",
__func__, vap, vap->iv_flags));
scanning = ic->ic_flags & IEEE80211_F_SCAN;
if (!scanning) {
u_int duration;