iwlwifi: mvm: correct rate_idx bounds-check
[cascardo/linux.git] / drivers / net / wireless / intel / iwlwifi / mvm / tx.c
index 1051777..ef4bdfc 100644 (file)
@@ -346,7 +346,7 @@ void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd *tx_cmd,
 
        rate_idx = info->control.rates[0].idx;
        /* if the rate isn't a well known legacy rate, take the lowest one */
-       if (rate_idx < 0 || rate_idx > IWL_RATE_COUNT_LEGACY)
+       if (rate_idx < 0 || rate_idx >= IWL_RATE_COUNT_LEGACY)
                rate_idx = rate_lowest_index(
                                &mvm->nvm_data->bands[info->band], sta);
 
@@ -490,16 +490,34 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
 static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm,
                                      struct ieee80211_tx_info *info, __le16 fc)
 {
-       if (iwl_mvm_is_dqa_supported(mvm)) {
-               if (info->control.vif->type == NL80211_IFTYPE_AP &&
-                   ieee80211_is_probe_resp(fc))
+       if (!iwl_mvm_is_dqa_supported(mvm))
+               return info->hw_queue;
+
+       switch (info->control.vif->type) {
+       case NL80211_IFTYPE_AP:
+               /*
+                * handle legacy hostapd as well, where station may be added
+                * only after assoc.
+                */
+               if (ieee80211_is_probe_resp(fc) || ieee80211_is_auth(fc))
                        return IWL_MVM_DQA_AP_PROBE_RESP_QUEUE;
-               else if (ieee80211_is_mgmt(fc) &&
-                        info->control.vif->type == NL80211_IFTYPE_P2P_DEVICE)
+               if (info->hw_queue == info->control.vif->cab_queue)
+                       return info->hw_queue;
+
+               WARN_ON_ONCE(1);
+               return IWL_MVM_DQA_AP_PROBE_RESP_QUEUE;
+       case NL80211_IFTYPE_P2P_DEVICE:
+               if (ieee80211_is_mgmt(fc))
                        return IWL_MVM_DQA_P2P_DEVICE_QUEUE;
-       }
+               if (info->hw_queue == info->control.vif->cab_queue)
+                       return info->hw_queue;
 
-       return info->hw_queue;
+               WARN_ON_ONCE(1);
+               return IWL_MVM_DQA_P2P_DEVICE_QUEUE;
+       default:
+               WARN_ONCE(1, "Not a ctrl vif, no available queue\n");
+               return -1;
+       }
 }
 
 int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
@@ -560,6 +578,9 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
                        sta_id = mvmvif->bcast_sta.sta_id;
                        queue = iwl_mvm_get_ctrl_vif_queue(mvm, &info,
                                                           hdr->frame_control);
+                       if (queue < 0)
+                               return -1;
+
                } else if (info.control.vif->type == NL80211_IFTYPE_STATION &&
                           is_multicast_ether_addr(hdr->addr1)) {
                        u8 ap_sta_id = ACCESS_ONCE(mvmvif->ap_sta_id);