aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2015-03-10 16:24:34 -0400
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2015-03-19 08:53:35 -0400
commitdcbc17ad7c7525ed04a45a94cfc5640d5cccf480 (patch)
tree67169f46e3369c3d91667a132a0c4fffb2e19702
parent9c8928f5176766bec79f272bd47b7124e11cccbd (diff)
iwlwifi: mvm: protect rate scaling against non-mvm IBSS stations
When the driver callback returns that it's out of space for new stations, the mac80211 IBSS code still keeps the station so it doesn't try to add it over and over again. Since the rate scaling algorithm is separate in mac80211, it also invokes the rate scaling algorithm for such stations. It doesn't know that our rate scaling algorithm is tightly integrated with the MVM code and relies on those data structures, and it cannot as the abstraction doesn't allow for it. This leads to crashes when the rate scaling algorithm tries to use uninitialized data, notably the mvmsta->vif pointer. Protect against this in the rate scaling algorithm. We cannot get good rates with such peers anyway since the firmware cannot do anything with them. This should fix https://bugzilla.kernel.org/show_bug.cgi?id=93461 CC: <stable@vger.kernel.org> Reported-by: Richard Taylor <rjt-kernel@thegrindstone.me.uk> Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/rs.c24
1 files changed, 22 insertions, 2 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c
index efa9688a4cf1..078f24cf4af3 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.c
@@ -1278,6 +1278,9 @@ static void rs_mac80211_tx_status(void *mvm_r,
1278 struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); 1278 struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
1279 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 1279 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1280 1280
1281 if (!iwl_mvm_sta_from_mac80211(sta)->vif)
1282 return;
1283
1281 if (!ieee80211_is_data(hdr->frame_control) || 1284 if (!ieee80211_is_data(hdr->frame_control) ||
1282 info->flags & IEEE80211_TX_CTL_NO_ACK) 1285 info->flags & IEEE80211_TX_CTL_NO_ACK)
1283 return; 1286 return;
@@ -2511,6 +2514,14 @@ static void rs_get_rate(void *mvm_r, struct ieee80211_sta *sta, void *mvm_sta,
2511 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 2514 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
2512 struct iwl_lq_sta *lq_sta = mvm_sta; 2515 struct iwl_lq_sta *lq_sta = mvm_sta;
2513 2516
2517 if (sta && !iwl_mvm_sta_from_mac80211(sta)->vif) {
2518 /* if vif isn't initialized mvm doesn't know about
2519 * this station, so don't do anything with the it
2520 */
2521 sta = NULL;
2522 mvm_sta = NULL;
2523 }
2524
2514 /* TODO: handle rate_idx_mask and rate_idx_mcs_mask */ 2525 /* TODO: handle rate_idx_mask and rate_idx_mcs_mask */
2515 2526
2516 /* Treat uninitialized rate scaling data same as non-existing. */ 2527 /* Treat uninitialized rate scaling data same as non-existing. */
@@ -2827,6 +2838,9 @@ static void rs_rate_update(void *mvm_r,
2827 (struct iwl_op_mode *)mvm_r; 2838 (struct iwl_op_mode *)mvm_r;
2828 struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); 2839 struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
2829 2840
2841 if (!iwl_mvm_sta_from_mac80211(sta)->vif)
2842 return;
2843
2830 /* Stop any ongoing aggregations as rs starts off assuming no agg */ 2844 /* Stop any ongoing aggregations as rs starts off assuming no agg */
2831 for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) 2845 for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++)
2832 ieee80211_stop_tx_ba_session(sta, tid); 2846 ieee80211_stop_tx_ba_session(sta, tid);
@@ -3587,9 +3601,15 @@ static ssize_t iwl_dbgfs_ss_force_write(struct iwl_lq_sta *lq_sta, char *buf,
3587 3601
3588MVM_DEBUGFS_READ_WRITE_FILE_OPS(ss_force, 32); 3602MVM_DEBUGFS_READ_WRITE_FILE_OPS(ss_force, 32);
3589 3603
3590static void rs_add_debugfs(void *mvm, void *mvm_sta, struct dentry *dir) 3604static void rs_add_debugfs(void *mvm, void *priv_sta, struct dentry *dir)
3591{ 3605{
3592 struct iwl_lq_sta *lq_sta = mvm_sta; 3606 struct iwl_lq_sta *lq_sta = priv_sta;
3607 struct iwl_mvm_sta *mvmsta;
3608
3609 mvmsta = container_of(lq_sta, struct iwl_mvm_sta, lq_sta);
3610
3611 if (!mvmsta->vif)
3612 return;
3593 3613
3594 debugfs_create_file("rate_scale_table", S_IRUSR | S_IWUSR, dir, 3614 debugfs_create_file("rate_scale_table", S_IRUSR | S_IWUSR, dir,
3595 lq_sta, &rs_sta_dbgfs_scale_table_ops); 3615 lq_sta, &rs_sta_dbgfs_scale_table_ops);