OSDN Git Service

mwifiex: fix unbalanced locking in mwifiex_process_country_ie()
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / drivers / net / wireless / mwifiex / sta_ioctl.c
index a6c8a4f..a1c376c 100644 (file)
@@ -229,6 +229,15 @@ static int mwifiex_process_country_ie(struct mwifiex_private *priv,
                            "11D: skip setting domain info in FW\n");
                return 0;
        }
+
+       if (country_ie_len >
+           (IEEE80211_COUNTRY_STRING_LEN + MWIFIEX_MAX_TRIPLET_802_11D)) {
+               rcu_read_unlock();
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "11D: country_ie_len overflow!, deauth AP\n");
+               return -EINVAL;
+       }
+
        memcpy(priv->adapter->country_code, &country_ie[2], 2);
 
        domain_info->country_code[0] = country_ie[2];
@@ -272,7 +281,8 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
        priv->scan_block = false;
 
        if (bss) {
-               mwifiex_process_country_ie(priv, bss);
+               if (mwifiex_process_country_ie(priv, bss))
+                       return -EINVAL;
 
                /* Allocate and fill new bss descriptor */
                bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor),
@@ -313,6 +323,7 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
                        mwifiex_dbg(adapter, ERROR,
                                    "Attempt to reconnect on csa closed chan(%d)\n",
                                    bss_desc->channel);
+                       ret = -1;
                        goto done;
                }
 
@@ -665,6 +676,9 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv,
        txp_cfg = (struct host_cmd_ds_txpwr_cfg *) buf;
        txp_cfg->action = cpu_to_le16(HostCmd_ACT_GEN_SET);
        if (!power_cfg->is_power_auto) {
+               u16 dbm_min = power_cfg->is_power_fixed ?
+                             dbm : priv->min_tx_power_level;
+
                txp_cfg->mode = cpu_to_le32(1);
                pg_tlv = (struct mwifiex_types_power_group *)
                         (buf + sizeof(struct host_cmd_ds_txpwr_cfg));
@@ -679,7 +693,7 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv,
                pg->last_rate_code = 0x03;
                pg->modulation_class = MOD_CLASS_HR_DSSS;
                pg->power_step = 0;
-               pg->power_min = (s8) dbm;
+               pg->power_min = (s8) dbm_min;
                pg->power_max = (s8) dbm;
                pg++;
                /* Power group for modulation class OFDM */
@@ -687,7 +701,7 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv,
                pg->last_rate_code = 0x07;
                pg->modulation_class = MOD_CLASS_OFDM;
                pg->power_step = 0;
-               pg->power_min = (s8) dbm;
+               pg->power_min = (s8) dbm_min;
                pg->power_max = (s8) dbm;
                pg++;
                /* Power group for modulation class HTBW20 */
@@ -695,7 +709,7 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv,
                pg->last_rate_code = 0x20;
                pg->modulation_class = MOD_CLASS_HT;
                pg->power_step = 0;
-               pg->power_min = (s8) dbm;
+               pg->power_min = (s8) dbm_min;
                pg->power_max = (s8) dbm;
                pg->ht_bandwidth = HT_BW_20;
                pg++;
@@ -704,7 +718,7 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv,
                pg->last_rate_code = 0x20;
                pg->modulation_class = MOD_CLASS_HT;
                pg->power_step = 0;
-               pg->power_min = (s8) dbm;
+               pg->power_min = (s8) dbm_min;
                pg->power_max = (s8) dbm;
                pg->ht_bandwidth = HT_BW_40;
        }
@@ -1097,8 +1111,6 @@ int mwifiex_set_encode(struct mwifiex_private *priv, struct key_params *kp,
                        encrypt_key.is_rx_seq_valid = true;
                }
        } else {
-               if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP)
-                       return 0;
                encrypt_key.key_disable = true;
                if (mac_addr)
                        memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN);
@@ -1306,7 +1318,7 @@ mwifiex_set_gen_ie_helper(struct mwifiex_private *priv, u8 *ie_data_ptr,
        pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr;
        /* Test to see if it is a WPA IE, if not, then it is a gen IE */
        if (((pvendor_ie->element_id == WLAN_EID_VENDOR_SPECIFIC) &&
-            (!memcmp(pvendor_ie->oui, wpa_oui, sizeof(wpa_oui)))) ||
+            (!memcmp(&pvendor_ie->oui, wpa_oui, sizeof(wpa_oui)))) ||
            (pvendor_ie->element_id == WLAN_EID_RSN)) {
 
                /* IE is a WPA/WPA2 IE so call set_wpa function */
@@ -1331,7 +1343,7 @@ mwifiex_set_gen_ie_helper(struct mwifiex_private *priv, u8 *ie_data_ptr,
                 */
                pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr;
                if ((pvendor_ie->element_id == WLAN_EID_VENDOR_SPECIFIC) &&
-                   (!memcmp(pvendor_ie->oui, wps_oui, sizeof(wps_oui)))) {
+                   (!memcmp(&pvendor_ie->oui, wps_oui, sizeof(wps_oui)))) {
                        priv->wps.session_enable = true;
                        mwifiex_dbg(priv->adapter, INFO,
                                    "info: WPS Session Enabled.\n");