]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
mac80211: Fix possible sband related NULL pointer de-reference
authorMohammed Shafi Shajakhan <mohammed@qti.qualcomm.com>
Thu, 27 Apr 2017 07:15:38 +0000 (12:45 +0530)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 28 Apr 2017 10:28:44 +0000 (12:28 +0200)
Existing API 'ieee80211_get_sdata_band' returns default 2 GHz band even
if the channel context configuration is NULL. This crashes for chipsets
which support 5 Ghz alone when it tries to access members of 'sband'.
Channel context configuration can be NULL in multivif case and when
channel switch is in progress (or) when it fails. Fix this by replacing
the API 'ieee80211_get_sdata_band' with  'ieee80211_get_sband' which
returns a NULL pointer for sband when the channel configuration is NULL.

An example scenario is as below:

In multivif mode (AP + STA) with drivers like ath10k, when we do a
channel switch in the AP vif (which has a number of clients connected)
and a STA vif which is connected to some other AP, when the channel
switch in AP vif fails, while the STA vifs tries to connect to the
other AP, there is a window where the channel context is NULL/invalid
and this results in a crash  while the clients connected to the AP vif
tries to reconnect and this race is very similar to the one investigated
by Michal in https://patchwork.kernel.org/patch/3788161/ and this does
happens with hardware that supports 5Ghz alone after long hours of
testing with continuous channel switch on the AP vif

ieee80211 phy0: channel context reservation cannot be finalized because
some interfaces aren't switching
wlan0: failed to finalize CSA, disconnecting
wlan0-1: deauthenticating from 8c:fd:f0:01:54:9c by local choice
(Reason: 3=DEAUTH_LEAVING)

WARNING: CPU: 1 PID: 19032 at net/mac80211/ieee80211_i.h:1013 sta_info_alloc+0x374/0x3fc [mac80211]
[<bf77272c>] (sta_info_alloc [mac80211])
[<bf78776c>] (ieee80211_add_station [mac80211]))
[<bf73cc50>] (nl80211_new_station [cfg80211])

Unable to handle kernel NULL pointer dereference at virtual
address 00000014
pgd = d5f4c000
Internal error: Oops: 17 [#1] PREEMPT SMP ARM
PC is at sta_info_alloc+0x380/0x3fc [mac80211]
LR is at sta_info_alloc+0x37c/0x3fc [mac80211]
[<bf772738>] (sta_info_alloc [mac80211])
[<bf78776c>] (ieee80211_add_station [mac80211])
[<bf73cc50>] (nl80211_new_station [cfg80211]))

Cc: Michal Kazior <michal.kazior@tieto.com>
Signed-off-by: Mohammed Shafi Shajakhan <mohammed@qti.qualcomm.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/cfg.c
net/mac80211/ibss.c
net/mac80211/ieee80211_i.h
net/mac80211/mesh.c
net/mac80211/mesh_plink.c
net/mac80211/mlme.c
net/mac80211/rate.c
net/mac80211/sta_info.c
net/mac80211/tdls.c
net/mac80211/tx.c
net/mac80211/util.c

index e4a370b42a9330b3087887906dbb20d5cbb96de8..6c2e6060cd549e3c4c39e78cc20ca9302472c4ac 100644 (file)
@@ -660,10 +660,11 @@ void sta_set_rate_info_tx(struct sta_info *sta,
                int shift = ieee80211_vif_get_shift(&sta->sdata->vif);
                u16 brate;
 
-               sband = sta->local->hw.wiphy->bands[
-                               ieee80211_get_sdata_band(sta->sdata)];
-               brate = sband->bitrates[rate->idx].bitrate;
-               rinfo->legacy = DIV_ROUND_UP(brate, 1 << shift);
+               sband = ieee80211_get_sband(sta->sdata);
+               if (sband) {
+                       brate = sband->bitrates[rate->idx].bitrate;
+                       rinfo->legacy = DIV_ROUND_UP(brate, 1 << shift);
+               }
        }
        if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
                rinfo->bw = RATE_INFO_BW_40;
@@ -1253,10 +1254,11 @@ static int sta_apply_parameters(struct ieee80211_local *local,
        int ret = 0;
        struct ieee80211_supported_band *sband;
        struct ieee80211_sub_if_data *sdata = sta->sdata;
-       enum nl80211_band band = ieee80211_get_sdata_band(sdata);
        u32 mask, set;
 
-       sband = local->hw.wiphy->bands[band];
+       sband = ieee80211_get_sband(sdata);
+       if (!sband)
+               return -EINVAL;
 
        mask = params->sta_flags_mask;
        set = params->sta_flags_set;
@@ -1389,7 +1391,7 @@ static int sta_apply_parameters(struct ieee80211_local *local,
                ieee80211_parse_bitrates(&sdata->vif.bss_conf.chandef,
                                         sband, params->supported_rates,
                                         params->supported_rates_len,
-                                        &sta->sta.supp_rates[band]);
+                                        &sta->sta.supp_rates[sband->band]);
        }
 
        if (params->ht_capa)
@@ -1405,8 +1407,8 @@ static int sta_apply_parameters(struct ieee80211_local *local,
                /* returned value is only needed for rc update, but the
                 * rc isn't initialized here yet, so ignore it
                 */
-               __ieee80211_vht_handle_opmode(sdata, sta,
-                                             params->opmode_notif, band);
+               __ieee80211_vht_handle_opmode(sdata, sta, params->opmode_notif,
+                                             sband->band);
        }
 
        if (params->support_p2p_ps >= 0)
@@ -2044,13 +2046,15 @@ static int ieee80211_change_bss(struct wiphy *wiphy,
                                struct bss_parameters *params)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-       enum nl80211_band band;
+       struct ieee80211_supported_band *sband;
        u32 changed = 0;
 
        if (!sdata_dereference(sdata->u.ap.beacon, sdata))
                return -ENOENT;
 
-       band = ieee80211_get_sdata_band(sdata);
+       sband = ieee80211_get_sband(sdata);
+       if (!sband)
+               return -EINVAL;
 
        if (params->use_cts_prot >= 0) {
                sdata->vif.bss_conf.use_cts_prot = params->use_cts_prot;
@@ -2063,7 +2067,7 @@ static int ieee80211_change_bss(struct wiphy *wiphy,
        }
 
        if (!sdata->vif.bss_conf.use_short_slot &&
-           band == NL80211_BAND_5GHZ) {
+           sband->band == NL80211_BAND_5GHZ) {
                sdata->vif.bss_conf.use_short_slot = true;
                changed |= BSS_CHANGED_ERP_SLOT;
        }
@@ -2076,7 +2080,7 @@ static int ieee80211_change_bss(struct wiphy *wiphy,
 
        if (params->basic_rates) {
                ieee80211_parse_bitrates(&sdata->vif.bss_conf.chandef,
-                                        wiphy->bands[band],
+                                        wiphy->bands[sband->band],
                                         params->basic_rates,
                                         params->basic_rates_len,
                                         &sdata->vif.bss_conf.basic_rates);
index 9d0f6100942b00e81b836955fadb9e8a67e3d4b8..6db09fa18269f3a12032345afa5af0fa336a8c50 100644 (file)
@@ -992,7 +992,7 @@ static void ieee80211_update_sta_info(struct ieee80211_sub_if_data *sdata,
        enum nl80211_band band = rx_status->band;
        enum nl80211_bss_scan_width scan_width;
        struct ieee80211_local *local = sdata->local;
-       struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
+       struct ieee80211_supported_band *sband;
        bool rates_updated = false;
        u32 supp_rates = 0;
 
@@ -1002,6 +1002,10 @@ static void ieee80211_update_sta_info(struct ieee80211_sub_if_data *sdata,
        if (!ether_addr_equal(mgmt->bssid, sdata->u.ibss.bssid))
                return;
 
+       sband = local->hw.wiphy->bands[band];
+       if (WARN_ON(!sband))
+               return;
+
        rcu_read_lock();
        sta = sta_info_get(sdata, mgmt->sa);
 
index 47d709afea25e84d7ea5ac0f0a4d485b8a74e68e..2a5730573aa3ec7b13c0250992fca4988625b255 100644 (file)
@@ -1001,21 +1001,6 @@ sdata_assert_lock(struct ieee80211_sub_if_data *sdata)
        lockdep_assert_held(&sdata->wdev.mtx);
 }
 
-static inline enum nl80211_band
-ieee80211_get_sdata_band(struct ieee80211_sub_if_data *sdata)
-{
-       enum nl80211_band band = NL80211_BAND_2GHZ;
-       struct ieee80211_chanctx_conf *chanctx_conf;
-
-       rcu_read_lock();
-       chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
-       if (!WARN_ON(!chanctx_conf))
-               band = chanctx_conf->def.chan->band;
-       rcu_read_unlock();
-
-       return band;
-}
-
 static inline int
 ieee80211_chandef_get_shift(struct cfg80211_chan_def *chandef)
 {
@@ -1421,6 +1406,27 @@ IEEE80211_WDEV_TO_SUB_IF(struct wireless_dev *wdev)
        return container_of(wdev, struct ieee80211_sub_if_data, wdev);
 }
 
+static inline struct ieee80211_supported_band *
+ieee80211_get_sband(struct ieee80211_sub_if_data *sdata)
+{
+       struct ieee80211_local *local = sdata->local;
+       struct ieee80211_chanctx_conf *chanctx_conf;
+       enum nl80211_band band;
+
+       rcu_read_lock();
+       chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+
+       if (WARN_ON(!chanctx_conf)) {
+               rcu_read_unlock();
+               return NULL;
+       }
+
+       band = chanctx_conf->def.chan->band;
+       rcu_read_unlock();
+
+       return local->hw.wiphy->bands[band];
+}
+
 /* this struct represents 802.11n's RA/TID combination */
 struct ieee80211_ra_tid {
        u8 ra[ETH_ALEN];
index 281d834c7548658edfae10eef517e6daa07ad9be..737e1f082b0ddd55e03b30bf215a5fbb68943143 100644 (file)
@@ -63,6 +63,7 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
        u32 basic_rates = 0;
        struct cfg80211_chan_def sta_chan_def;
+       struct ieee80211_supported_band *sband;
 
        /*
         * As support for each feature is added, check for matching
@@ -83,7 +84,11 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
             (ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth)))
                return false;
 
-       ieee80211_sta_get_rates(sdata, ie, ieee80211_get_sdata_band(sdata),
+       sband = ieee80211_get_sband(sdata);
+       if (!sband)
+               return false;
+
+       ieee80211_sta_get_rates(sdata, ie, sband->band,
                                &basic_rates);
 
        if (sdata->vif.bss_conf.basic_rates != basic_rates)
@@ -399,12 +404,13 @@ static int mesh_add_ds_params_ie(struct ieee80211_sub_if_data *sdata,
 int mesh_add_ht_cap_ie(struct ieee80211_sub_if_data *sdata,
                       struct sk_buff *skb)
 {
-       struct ieee80211_local *local = sdata->local;
-       enum nl80211_band band = ieee80211_get_sdata_band(sdata);
        struct ieee80211_supported_band *sband;
        u8 *pos;
 
-       sband = local->hw.wiphy->bands[band];
+       sband = ieee80211_get_sband(sdata);
+       if (!sband)
+               return -EINVAL;
+
        if (!sband->ht_cap.ht_supported ||
            sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
            sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 ||
@@ -462,12 +468,13 @@ int mesh_add_ht_oper_ie(struct ieee80211_sub_if_data *sdata,
 int mesh_add_vht_cap_ie(struct ieee80211_sub_if_data *sdata,
                        struct sk_buff *skb)
 {
-       struct ieee80211_local *local = sdata->local;
-       enum nl80211_band band = ieee80211_get_sdata_band(sdata);
        struct ieee80211_supported_band *sband;
        u8 *pos;
 
-       sband = local->hw.wiphy->bands[band];
+       sband = ieee80211_get_sband(sdata);
+       if (!sband)
+               return -EINVAL;
+
        if (!sband->vht_cap.vht_supported ||
            sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
            sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 ||
@@ -916,12 +923,16 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
        struct cfg80211_csa_settings params;
        struct ieee80211_csa_ie csa_ie;
        struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
-       enum nl80211_band band = ieee80211_get_sdata_band(sdata);
+       struct ieee80211_supported_band *sband;
        int err;
        u32 sta_flags;
 
        sdata_assert_lock(sdata);
 
+       sband = ieee80211_get_sband(sdata);
+       if (!sband)
+               return false;
+
        sta_flags = IEEE80211_STA_DISABLE_VHT;
        switch (sdata->vif.bss_conf.chandef.width) {
        case NL80211_CHAN_WIDTH_20_NOHT:
@@ -935,7 +946,7 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
 
        memset(&params, 0, sizeof(params));
        memset(&csa_ie, 0, sizeof(csa_ie));
-       err = ieee80211_parse_ch_switch_ie(sdata, elems, band,
+       err = ieee80211_parse_ch_switch_ie(sdata, elems, sband->band,
                                           sta_flags, sdata->vif.addr,
                                           &csa_ie);
        if (err < 0)
index 953d71e784a9ab71cb8494478e39eaf3b9464211..1131cd504a15ef5fa507c37c8a5464aac173321f 100644 (file)
@@ -95,19 +95,23 @@ static inline void mesh_plink_fsm_restart(struct sta_info *sta)
 static u32 mesh_set_short_slot_time(struct ieee80211_sub_if_data *sdata)
 {
        struct ieee80211_local *local = sdata->local;
-       enum nl80211_band band = ieee80211_get_sdata_band(sdata);
-       struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
+       struct ieee80211_supported_band *sband;
        struct sta_info *sta;
        u32 erp_rates = 0, changed = 0;
        int i;
        bool short_slot = false;
 
-       if (band == NL80211_BAND_5GHZ) {
+       sband = ieee80211_get_sband(sdata);
+       if (!sband)
+               return changed;
+
+       if (sband->band == NL80211_BAND_5GHZ) {
                /* (IEEE 802.11-2012 19.4.5) */
                short_slot = true;
                goto out;
-       } else if (band != NL80211_BAND_2GHZ)
+       } else if (sband->band != NL80211_BAND_2GHZ) {
                goto out;
+       }
 
        for (i = 0; i < sband->n_bitrates; i++)
                if (sband->bitrates[i].flags & IEEE80211_RATE_ERP_G)
@@ -123,7 +127,7 @@ static u32 mesh_set_short_slot_time(struct ieee80211_sub_if_data *sdata)
                        continue;
 
                short_slot = false;
-               if (erp_rates & sta->sta.supp_rates[band])
+               if (erp_rates & sta->sta.supp_rates[sband->band])
                        short_slot = true;
                 else
                        break;
@@ -249,7 +253,15 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
        mgmt->u.action.u.self_prot.action_code = action;
 
        if (action != WLAN_SP_MESH_PEERING_CLOSE) {
-               enum nl80211_band band = ieee80211_get_sdata_band(sdata);
+               struct ieee80211_supported_band *sband;
+               enum nl80211_band band;
+
+               sband = ieee80211_get_sband(sdata);
+               if (!sband) {
+                       err = -EINVAL;
+                       goto free;
+               }
+               band = sband->band;
 
                /* capability info */
                pos = skb_put(skb, 2);
@@ -395,13 +407,16 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata,
                               struct ieee802_11_elems *elems, bool insert)
 {
        struct ieee80211_local *local = sdata->local;
-       enum nl80211_band band = ieee80211_get_sdata_band(sdata);
        struct ieee80211_supported_band *sband;
        u32 rates, basic_rates = 0, changed = 0;
        enum ieee80211_sta_rx_bandwidth bw = sta->sta.bandwidth;
 
-       sband = local->hw.wiphy->bands[band];
-       rates = ieee80211_sta_get_rates(sdata, elems, band, &basic_rates);
+       sband = ieee80211_get_sband(sdata);
+       if (!sband)
+               return;
+
+       rates = ieee80211_sta_get_rates(sdata, elems, sband->band,
+                                       &basic_rates);
 
        spin_lock_bh(&sta->mesh->plink_lock);
        sta->rx_stats.last_rx = jiffies;
@@ -412,9 +427,9 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata,
                goto out;
        sta->mesh->processed_beacon = true;
 
-       if (sta->sta.supp_rates[band] != rates)
+       if (sta->sta.supp_rates[sband->band] != rates)
                changed |= IEEE80211_RC_SUPP_RATES_CHANGED;
-       sta->sta.supp_rates[band] = rates;
+       sta->sta.supp_rates[sband->band] = rates;
 
        if (ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
                                              elems->ht_cap_elem, sta))
index 24d69bcf71ad50d0e45b15ba18da3ad99b226bfb..45d80fe61c5fd84007fb3dfd001de6ccec23ec86 100644 (file)
@@ -1855,11 +1855,16 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
                                           u16 capab, bool erp_valid, u8 erp)
 {
        struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
+       struct ieee80211_supported_band *sband;
        u32 changed = 0;
        bool use_protection;
        bool use_short_preamble;
        bool use_short_slot;
 
+       sband = ieee80211_get_sband(sdata);
+       if (!sband)
+               return changed;
+
        if (erp_valid) {
                use_protection = (erp & WLAN_ERP_USE_PROTECTION) != 0;
                use_short_preamble = (erp & WLAN_ERP_BARKER_PREAMBLE) == 0;
@@ -1869,7 +1874,7 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
        }
 
        use_short_slot = !!(capab & WLAN_CAPABILITY_SHORT_SLOT_TIME);
-       if (ieee80211_get_sdata_band(sdata) == NL80211_BAND_5GHZ)
+       if (sband->band == NL80211_BAND_5GHZ)
                use_short_slot = true;
 
        if (use_protection != bss_conf->use_cts_prot) {
@@ -3004,7 +3009,12 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
                goto out;
        }
 
-       sband = local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)];
+       sband = ieee80211_get_sband(sdata);
+       if (!sband) {
+               mutex_unlock(&sdata->local->sta_mtx);
+               ret = false;
+               goto out;
+       }
 
        /* Set up internal HT/VHT capabilities */
        if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_HT))
index b387c07b8b479a99d0c5181f4d4e34abd6cb195d..ea1f4315c521be976c822918d7d821cffd3cc0e9 100644 (file)
@@ -926,7 +926,9 @@ int rate_control_set_rates(struct ieee80211_hw *hw,
        struct ieee80211_sta_rates *old;
        struct ieee80211_supported_band *sband;
 
-       sband = hw->wiphy->bands[ieee80211_get_sdata_band(sta->sdata)];
+       sband = ieee80211_get_sband(sta->sdata);
+       if (!sband)
+               return -EINVAL;
        rate_control_apply_mask_ratetbl(sta, sband, rates);
        /*
         * mac80211 guarantees that this function will not be called
index 464566c662c55710381fd0e5c9bbe27bb1f05ab5..7cdf7a835bb01e8fade3b9d9bb6efaa19158f72b 100644 (file)
@@ -395,10 +395,15 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
        sta->sta.smps_mode = IEEE80211_SMPS_OFF;
        if (sdata->vif.type == NL80211_IFTYPE_AP ||
            sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
-               struct ieee80211_supported_band *sband =
-                       hw->wiphy->bands[ieee80211_get_sdata_band(sdata)];
-               u8 smps = (sband->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >>
-                               IEEE80211_HT_CAP_SM_PS_SHIFT;
+               struct ieee80211_supported_band *sband;
+               u8 smps;
+
+               sband = ieee80211_get_sband(sdata);
+               if (!sband)
+                       goto free_txq;
+
+               smps = (sband->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >>
+                       IEEE80211_HT_CAP_SM_PS_SHIFT;
                /*
                 * Assume that hostapd advertises our caps in the beacon and
                 * this is the known_smps_mode for a station that just assciated
index afca7d103684bbc8c953ae13bb0345934d8f5f35..f20dcf1b1830a2412ed96ebcc9ce3be65ef5d7e8 100644 (file)
@@ -47,8 +47,7 @@ static void ieee80211_tdls_add_ext_capab(struct ieee80211_sub_if_data *sdata,
                           NL80211_FEATURE_TDLS_CHANNEL_SWITCH;
        bool wider_band = ieee80211_hw_check(&local->hw, TDLS_WIDER_BW) &&
                          !ifmgd->tdls_wider_bw_prohibited;
-       enum nl80211_band band = ieee80211_get_sdata_band(sdata);
-       struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
+       struct ieee80211_supported_band *sband = ieee80211_get_sband(sdata);
        bool vht = sband && sband->vht_cap.vht_supported;
        u8 *pos = (void *)skb_put(skb, 10);
 
@@ -180,11 +179,14 @@ static void ieee80211_tdls_add_bss_coex_ie(struct sk_buff *skb)
 static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata,
                                        u16 status_code)
 {
+       struct ieee80211_supported_band *sband;
+
        /* The capability will be 0 when sending a failure code */
        if (status_code != 0)
                return 0;
 
-       if (ieee80211_get_sdata_band(sdata) == NL80211_BAND_2GHZ) {
+       sband = ieee80211_get_sband(sdata);
+       if (sband && sband->band == NL80211_BAND_2GHZ) {
                return WLAN_CAPABILITY_SHORT_SLOT_TIME |
                       WLAN_CAPABILITY_SHORT_PREAMBLE;
        }
@@ -358,17 +360,20 @@ ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata,
                                   u8 action_code, bool initiator,
                                   const u8 *extra_ies, size_t extra_ies_len)
 {
-       enum nl80211_band band = ieee80211_get_sdata_band(sdata);
-       struct ieee80211_local *local = sdata->local;
        struct ieee80211_supported_band *sband;
+       struct ieee80211_local *local = sdata->local;
        struct ieee80211_sta_ht_cap ht_cap;
        struct ieee80211_sta_vht_cap vht_cap;
        struct sta_info *sta = NULL;
        size_t offset = 0, noffset;
        u8 *pos;
 
-       ieee80211_add_srates_ie(sdata, skb, false, band);
-       ieee80211_add_ext_srates_ie(sdata, skb, false, band);
+       sband = ieee80211_get_sband(sdata);
+       if (!sband)
+               return;
+
+       ieee80211_add_srates_ie(sdata, skb, false, sband->band);
+       ieee80211_add_ext_srates_ie(sdata, skb, false, sband->band);
        ieee80211_tdls_add_supp_channels(sdata, skb);
 
        /* add any custom IEs that go before Extended Capabilities */
@@ -439,7 +444,6 @@ ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata,
         * the same on all bands. The specification limits the setup to a
         * single HT-cap, so use the current band for now.
         */
-       sband = local->hw.wiphy->bands[band];
        memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap));
 
        if ((action_code == WLAN_TDLS_SETUP_REQUEST ||
@@ -545,9 +549,13 @@ ieee80211_tdls_add_setup_cfm_ies(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        size_t offset = 0, noffset;
        struct sta_info *sta, *ap_sta;
-       enum nl80211_band band = ieee80211_get_sdata_band(sdata);
+       struct ieee80211_supported_band *sband;
        u8 *pos;
 
+       sband = ieee80211_get_sband(sdata);
+       if (!sband)
+               return;
+
        mutex_lock(&local->sta_mtx);
 
        sta = sta_info_get(sdata, peer);
@@ -612,7 +620,8 @@ ieee80211_tdls_add_setup_cfm_ies(struct ieee80211_sub_if_data *sdata,
        ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator);
 
        /* only include VHT-operation if not on the 2.4GHz band */
-       if (band != NL80211_BAND_2GHZ && sta->sta.vht_cap.vht_supported) {
+       if (sband->band != NL80211_BAND_2GHZ &&
+           sta->sta.vht_cap.vht_supported) {
                /*
                 * if both peers support WIDER_BW, we can expand the chandef to
                 * a wider compatible one, up to 80MHz
index f27719eeeed795f8ee7d54c20519d695d352a584..04b22f8982fe42b41364d8d7feee0d5bd036c64a 100644 (file)
@@ -4297,7 +4297,10 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
                return bcn;
 
        shift = ieee80211_vif_get_shift(vif);
-       sband = hw->wiphy->bands[ieee80211_get_sdata_band(vif_to_sdata(vif))];
+       sband = ieee80211_get_sband(vif_to_sdata(vif));
+       if (!sband)
+               return bcn;
+
        ieee80211_tx_monitor(hw_to_local(hw), copy, sband, 1, shift, false);
 
        return bcn;
index 83342b73e9aadd5d8256e75df0cee633fd26b0e2..4a5414481b78edb90e50136dbf4f661a65effc39 100644 (file)
@@ -1590,14 +1590,14 @@ u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata,
        size_t num_rates;
        u32 supp_rates, rate_flags;
        int i, j, shift;
+
        sband = sdata->local->hw.wiphy->bands[band];
+       if (WARN_ON(!sband))
+               return 1;
 
        rate_flags = ieee80211_chandef_rate_flags(&sdata->vif.bss_conf.chandef);
        shift = ieee80211_vif_get_shift(&sdata->vif);
 
-       if (WARN_ON(!sband))
-               return 1;
-
        num_rates = sband->n_bitrates;
        supp_rates = 0;
        for (i = 0; i < elems->supp_rates_len +