Merge tag 'wireless-drivers-2019-12-17' of git://git.kernel.org/pub/scm/linux/kernel...
authorDavid S. Miller <davem@davemloft.net>
Tue, 17 Dec 2019 22:27:35 +0000 (14:27 -0800)
committerDavid S. Miller <davem@davemloft.net>
Tue, 17 Dec 2019 22:27:35 +0000 (14:27 -0800)
Kalle Valo says:

====================
wireless-drivers fixes for v5.5

First set of fixes for v5.5. Fixing security issues, some regressions
and few major bugs.

mwifiex

* security fix for handling country Information Elements (CVE-2019-14895)

* security fix for handling TDLS Information Elements

ath9k

* fix endian issue with ath9k_pci_owl_loader

mt76

* fix default mac address handling

iwlwifi

* fix merge damage which lead to firmware crashing during boot on some devices

* fix device initialisation regression on some devices
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/wireless/ath/ath9k/ath9k_pci_owl_loader.c
drivers/net/wireless/intel/iwlwifi/pcie/drv.c
drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
drivers/net/wireless/intel/iwlwifi/pcie/trans.c
drivers/net/wireless/marvell/mwifiex/sta_ioctl.c
drivers/net/wireless/marvell/mwifiex/tdls.c
drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c

index 956fa78..56d1a77 100644 (file)
@@ -83,7 +83,7 @@ static int ath9k_pci_fixup(struct pci_dev *pdev, const u16 *cal_data,
                        val = swahb32(val);
                }
 
-               __raw_writel(val, mem + reg);
+               iowrite32(val, mem + reg);
                usleep_range(100, 120);
        }
 
index 040cec1..b0b7eca 100644 (file)
@@ -1111,18 +1111,18 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        /* same thing for QuZ... */
        if (iwl_trans->hw_rev == CSR_HW_REV_TYPE_QUZ) {
-               if (iwl_trans->cfg == &iwl_ax101_cfg_qu_hr)
-                       iwl_trans->cfg = &iwl_ax101_cfg_quz_hr;
-               else if (iwl_trans->cfg == &iwl_ax201_cfg_qu_hr)
-                       iwl_trans->cfg = &iwl_ax201_cfg_quz_hr;
-               else if (iwl_trans->cfg == &iwl9461_2ac_cfg_qu_b0_jf_b0)
-                       iwl_trans->cfg = &iwl9461_2ac_cfg_quz_a0_jf_b0_soc;
-               else if (iwl_trans->cfg == &iwl9462_2ac_cfg_qu_b0_jf_b0)
-                       iwl_trans->cfg = &iwl9462_2ac_cfg_quz_a0_jf_b0_soc;
-               else if (iwl_trans->cfg == &iwl9560_2ac_cfg_qu_b0_jf_b0)
-                       iwl_trans->cfg = &iwl9560_2ac_cfg_quz_a0_jf_b0_soc;
-               else if (iwl_trans->cfg == &iwl9560_2ac_160_cfg_qu_b0_jf_b0)
-                       iwl_trans->cfg = &iwl9560_2ac_160_cfg_quz_a0_jf_b0_soc;
+               if (cfg == &iwl_ax101_cfg_qu_hr)
+                       cfg = &iwl_ax101_cfg_quz_hr;
+               else if (cfg == &iwl_ax201_cfg_qu_hr)
+                       cfg = &iwl_ax201_cfg_quz_hr;
+               else if (cfg == &iwl9461_2ac_cfg_qu_b0_jf_b0)
+                       cfg = &iwl9461_2ac_cfg_quz_a0_jf_b0_soc;
+               else if (cfg == &iwl9462_2ac_cfg_qu_b0_jf_b0)
+                       cfg = &iwl9462_2ac_cfg_quz_a0_jf_b0_soc;
+               else if (cfg == &iwl9560_2ac_cfg_qu_b0_jf_b0)
+                       cfg = &iwl9560_2ac_cfg_quz_a0_jf_b0_soc;
+               else if (cfg == &iwl9560_2ac_160_cfg_qu_b0_jf_b0)
+                       cfg = &iwl9560_2ac_160_cfg_quz_a0_jf_b0_soc;
        }
 
 #endif
index 0252716..0d8b2a8 100644 (file)
 #include "internal.h"
 #include "fw/dbg.h"
 
-static int iwl_pcie_gen2_force_power_gating(struct iwl_trans *trans)
-{
-       iwl_set_bits_prph(trans, HPM_HIPM_GEN_CFG,
-                         HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE);
-       udelay(20);
-       iwl_set_bits_prph(trans, HPM_HIPM_GEN_CFG,
-                         HPM_HIPM_GEN_CFG_CR_PG_EN |
-                         HPM_HIPM_GEN_CFG_CR_SLP_EN);
-       udelay(20);
-       iwl_clear_bits_prph(trans, HPM_HIPM_GEN_CFG,
-                           HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE);
-
-       iwl_trans_sw_reset(trans);
-       iwl_clear_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
-
-       return 0;
-}
-
 /*
  * Start up NIC's basic functionality after it has been reset
  * (e.g. after platform boot, or shutdown via iwl_pcie_apm_stop())
@@ -110,13 +92,6 @@ int iwl_pcie_gen2_apm_init(struct iwl_trans *trans)
 
        iwl_pcie_apm_config(trans);
 
-       if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000 &&
-           trans->cfg->integrated) {
-               ret = iwl_pcie_gen2_force_power_gating(trans);
-               if (ret)
-                       return ret;
-       }
-
        ret = iwl_finish_nic_init(trans, trans->trans_cfg);
        if (ret)
                return ret;
index af9bc6b..a067713 100644 (file)
@@ -1783,6 +1783,29 @@ static int iwl_trans_pcie_clear_persistence_bit(struct iwl_trans *trans)
        return 0;
 }
 
+static int iwl_pcie_gen2_force_power_gating(struct iwl_trans *trans)
+{
+       int ret;
+
+       ret = iwl_finish_nic_init(trans, trans->trans_cfg);
+       if (ret < 0)
+               return ret;
+
+       iwl_set_bits_prph(trans, HPM_HIPM_GEN_CFG,
+                         HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE);
+       udelay(20);
+       iwl_set_bits_prph(trans, HPM_HIPM_GEN_CFG,
+                         HPM_HIPM_GEN_CFG_CR_PG_EN |
+                         HPM_HIPM_GEN_CFG_CR_SLP_EN);
+       udelay(20);
+       iwl_clear_bits_prph(trans, HPM_HIPM_GEN_CFG,
+                           HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE);
+
+       iwl_trans_pcie_sw_reset(trans);
+
+       return 0;
+}
+
 static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -1802,6 +1825,13 @@ static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans)
 
        iwl_trans_pcie_sw_reset(trans);
 
+       if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000 &&
+           trans->cfg->integrated) {
+               err = iwl_pcie_gen2_force_power_gating(trans);
+               if (err)
+                       return err;
+       }
+
        err = iwl_pcie_apm_init(trans);
        if (err)
                return err;
index 74e5056..6dd835f 100644 (file)
@@ -229,6 +229,14 @@ 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)) {
+               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,8 +280,9 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
        priv->scan_block = false;
 
        if (bss) {
-               if (adapter->region_code == 0x00)
-                       mwifiex_process_country_ie(priv, bss);
+               if (adapter->region_code == 0x00 &&
+                   mwifiex_process_country_ie(priv, bss))
+                       return -EINVAL;
 
                /* Allocate and fill new bss descriptor */
                bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor),
index 0931304..7caf1d2 100644 (file)
@@ -953,59 +953,117 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
 
                switch (*pos) {
                case WLAN_EID_SUPP_RATES:
+                       if (pos[1] > 32)
+                               return;
                        sta_ptr->tdls_cap.rates_len = pos[1];
                        for (i = 0; i < pos[1]; i++)
                                sta_ptr->tdls_cap.rates[i] = pos[i + 2];
                        break;
 
                case WLAN_EID_EXT_SUPP_RATES:
+                       if (pos[1] > 32)
+                               return;
                        basic = sta_ptr->tdls_cap.rates_len;
+                       if (pos[1] > 32 - basic)
+                               return;
                        for (i = 0; i < pos[1]; i++)
                                sta_ptr->tdls_cap.rates[basic + i] = pos[i + 2];
                        sta_ptr->tdls_cap.rates_len += pos[1];
                        break;
                case WLAN_EID_HT_CAPABILITY:
-                       memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos,
+                       if (pos > end - sizeof(struct ieee80211_ht_cap) - 2)
+                               return;
+                       if (pos[1] != sizeof(struct ieee80211_ht_cap))
+                               return;
+                       /* copy the ie's value into ht_capb*/
+                       memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos + 2,
                               sizeof(struct ieee80211_ht_cap));
                        sta_ptr->is_11n_enabled = 1;
                        break;
                case WLAN_EID_HT_OPERATION:
-                       memcpy(&sta_ptr->tdls_cap.ht_oper, pos,
+                       if (pos > end -
+                           sizeof(struct ieee80211_ht_operation) - 2)
+                               return;
+                       if (pos[1] != sizeof(struct ieee80211_ht_operation))
+                               return;
+                       /* copy the ie's value into ht_oper*/
+                       memcpy(&sta_ptr->tdls_cap.ht_oper, pos + 2,
                               sizeof(struct ieee80211_ht_operation));
                        break;
                case WLAN_EID_BSS_COEX_2040:
+                       if (pos > end - 3)
+                               return;
+                       if (pos[1] != 1)
+                               return;
                        sta_ptr->tdls_cap.coex_2040 = pos[2];
                        break;
                case WLAN_EID_EXT_CAPABILITY:
+                       if (pos > end - sizeof(struct ieee_types_header))
+                               return;
+                       if (pos[1] < sizeof(struct ieee_types_header))
+                               return;
+                       if (pos[1] > 8)
+                               return;
                        memcpy((u8 *)&sta_ptr->tdls_cap.extcap, pos,
                               sizeof(struct ieee_types_header) +
                               min_t(u8, pos[1], 8));
                        break;
                case WLAN_EID_RSN:
+                       if (pos > end - sizeof(struct ieee_types_header))
+                               return;
+                       if (pos[1] < sizeof(struct ieee_types_header))
+                               return;
+                       if (pos[1] > IEEE_MAX_IE_SIZE -
+                           sizeof(struct ieee_types_header))
+                               return;
                        memcpy((u8 *)&sta_ptr->tdls_cap.rsn_ie, pos,
                               sizeof(struct ieee_types_header) +
                               min_t(u8, pos[1], IEEE_MAX_IE_SIZE -
                                     sizeof(struct ieee_types_header)));
                        break;
                case WLAN_EID_QOS_CAPA:
+                       if (pos > end - 3)
+                               return;
+                       if (pos[1] != 1)
+                               return;
                        sta_ptr->tdls_cap.qos_info = pos[2];
                        break;
                case WLAN_EID_VHT_OPERATION:
-                       if (priv->adapter->is_hw_11ac_capable)
-                               memcpy(&sta_ptr->tdls_cap.vhtoper, pos,
+                       if (priv->adapter->is_hw_11ac_capable) {
+                               if (pos > end -
+                                   sizeof(struct ieee80211_vht_operation) - 2)
+                                       return;
+                               if (pos[1] !=
+                                   sizeof(struct ieee80211_vht_operation))
+                                       return;
+                               /* copy the ie's value into vhtoper*/
+                               memcpy(&sta_ptr->tdls_cap.vhtoper, pos + 2,
                                       sizeof(struct ieee80211_vht_operation));
+                       }
                        break;
                case WLAN_EID_VHT_CAPABILITY:
                        if (priv->adapter->is_hw_11ac_capable) {
-                               memcpy((u8 *)&sta_ptr->tdls_cap.vhtcap, pos,
+                               if (pos > end -
+                                   sizeof(struct ieee80211_vht_cap) - 2)
+                                       return;
+                               if (pos[1] != sizeof(struct ieee80211_vht_cap))
+                                       return;
+                               /* copy the ie's value into vhtcap*/
+                               memcpy((u8 *)&sta_ptr->tdls_cap.vhtcap, pos + 2,
                                       sizeof(struct ieee80211_vht_cap));
                                sta_ptr->is_11ac_enabled = 1;
                        }
                        break;
                case WLAN_EID_AID:
-                       if (priv->adapter->is_hw_11ac_capable)
+                       if (priv->adapter->is_hw_11ac_capable) {
+                               if (pos > end - 4)
+                                       return;
+                               if (pos[1] != 2)
+                                       return;
                                sta_ptr->tdls_cap.aid =
                                        get_unaligned_le16((pos + 2));
+                       }
+                       break;
                default:
                        break;
                }
index a03e2d0..d140552 100644 (file)
@@ -342,8 +342,11 @@ int mt76x0_eeprom_init(struct mt76x02_dev *dev)
        dev_info(dev->mt76.dev, "EEPROM ver:%02hhx fae:%02hhx\n",
                 version, fae);
 
-       mt76x02_mac_setaddr(dev, dev->mt76.eeprom.data + MT_EE_MAC_ADDR);
+       memcpy(dev->mt76.macaddr, (u8 *)dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
+              ETH_ALEN);
        mt76_eeprom_override(&dev->mt76);
+       mt76x02_mac_setaddr(dev, dev->mt76.macaddr);
+
        mt76x0_set_chip_cap(dev);
        mt76x0_set_freq_offset(dev);
        mt76x0_set_temp_offset(dev);