| From 3d71c3f1f50cf309bd20659422af549bc784bfff Mon Sep 17 00:00:00 2001 |
| From: Luca Coelho <luciano.coelho@intel.com> |
| Date: Sat, 13 Oct 2018 09:46:08 +0300 |
| Subject: iwlwifi: mvm: check return value of rs_rate_from_ucode_rate() |
| |
| From: Luca Coelho <luciano.coelho@intel.com> |
| |
| commit 3d71c3f1f50cf309bd20659422af549bc784bfff upstream. |
| |
| The rs_rate_from_ucode_rate() function may return -EINVAL if the rate |
| is invalid, but none of the callsites check for the error, potentially |
| making us access arrays with index IWL_RATE_INVALID, which is larger |
| than the arrays, causing an out-of-bounds access. This will trigger |
| KASAN warnings, such as the one reported in the bugzilla issue |
| mentioned below. |
| |
| This fixes https://bugzilla.kernel.org/show_bug.cgi?id=200659 |
| |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Luca Coelho <luciano.coelho@intel.com> |
| Signed-off-by: Kalle Valo <kvalo@codeaurora.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/net/wireless/intel/iwlwifi/mvm/rs.c | 24 +++++++++++++++++++----- |
| 1 file changed, 19 insertions(+), 5 deletions(-) |
| |
| --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c |
| +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c |
| @@ -1207,7 +1207,11 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm |
| !(info->flags & IEEE80211_TX_STAT_AMPDU)) |
| return; |
| |
| - rs_rate_from_ucode_rate(tx_resp_hwrate, info->band, &tx_resp_rate); |
| + if (rs_rate_from_ucode_rate(tx_resp_hwrate, info->band, |
| + &tx_resp_rate)) { |
| + WARN_ON_ONCE(1); |
| + return; |
| + } |
| |
| #ifdef CONFIG_MAC80211_DEBUGFS |
| /* Disable last tx check if we are debugging with fixed rate but |
| @@ -1263,7 +1267,10 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm |
| */ |
| table = &lq_sta->lq; |
| lq_hwrate = le32_to_cpu(table->rs_table[0]); |
| - rs_rate_from_ucode_rate(lq_hwrate, info->band, &lq_rate); |
| + if (rs_rate_from_ucode_rate(lq_hwrate, info->band, &lq_rate)) { |
| + WARN_ON_ONCE(1); |
| + return; |
| + } |
| |
| /* Here we actually compare this rate to the latest LQ command */ |
| if (!rs_rate_equal(&tx_resp_rate, &lq_rate, allow_ant_mismatch)) { |
| @@ -1365,8 +1372,12 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm |
| /* Collect data for each rate used during failed TX attempts */ |
| for (i = 0; i <= retries; ++i) { |
| lq_hwrate = le32_to_cpu(table->rs_table[i]); |
| - rs_rate_from_ucode_rate(lq_hwrate, info->band, |
| - &lq_rate); |
| + if (rs_rate_from_ucode_rate(lq_hwrate, info->band, |
| + &lq_rate)) { |
| + WARN_ON_ONCE(1); |
| + return; |
| + } |
| + |
| /* |
| * Only collect stats if retried rate is in the same RS |
| * table as active/search. |
| @@ -3261,7 +3272,10 @@ static void rs_build_rates_table_from_fi |
| for (i = 0; i < num_rates; i++) |
| lq_cmd->rs_table[i] = ucode_rate_le32; |
| |
| - rs_rate_from_ucode_rate(ucode_rate, band, &rate); |
| + if (rs_rate_from_ucode_rate(ucode_rate, band, &rate)) { |
| + WARN_ON_ONCE(1); |
| + return; |
| + } |
| |
| if (is_mimo(&rate)) |
| lq_cmd->mimo_delim = num_rates - 1; |