aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/tx.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/tx.c')
-rw-r--r--net/mac80211/tx.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 0820f127da2b..b29dc70b2f01 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -17,6 +17,7 @@
17#include <linux/skbuff.h> 17#include <linux/skbuff.h>
18#include <linux/etherdevice.h> 18#include <linux/etherdevice.h>
19#include <linux/bitmap.h> 19#include <linux/bitmap.h>
20#include <linux/rcupdate.h>
20#include <net/net_namespace.h> 21#include <net/net_namespace.h>
21#include <net/ieee80211_radiotap.h> 22#include <net/ieee80211_radiotap.h>
22#include <net/cfg80211.h> 23#include <net/cfg80211.h>
@@ -427,14 +428,16 @@ ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx)
427static ieee80211_txrx_result 428static ieee80211_txrx_result
428ieee80211_tx_h_select_key(struct ieee80211_txrx_data *tx) 429ieee80211_tx_h_select_key(struct ieee80211_txrx_data *tx)
429{ 430{
431 struct ieee80211_key *key;
432
430 tx->u.tx.control->key_idx = HW_KEY_IDX_INVALID; 433 tx->u.tx.control->key_idx = HW_KEY_IDX_INVALID;
431 434
432 if (unlikely(tx->u.tx.control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)) 435 if (unlikely(tx->u.tx.control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
433 tx->key = NULL; 436 tx->key = NULL;
434 else if (tx->sta && tx->sta->key) 437 else if (tx->sta && (key = rcu_dereference(tx->sta->key)))
435 tx->key = tx->sta->key; 438 tx->key = key;
436 else if (tx->sdata->default_key) 439 else if ((key = rcu_dereference(tx->sdata->default_key)))
437 tx->key = tx->sdata->default_key; 440 tx->key = key;
438 else if (tx->sdata->drop_unencrypted && 441 else if (tx->sdata->drop_unencrypted &&
439 !(tx->sdata->eapol && ieee80211_is_eapol(tx->skb))) { 442 !(tx->sdata->eapol && ieee80211_is_eapol(tx->skb))) {
440 I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted); 443 I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted);
@@ -1112,6 +1115,12 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb,
1112 return 0; 1115 return 0;
1113 } 1116 }
1114 1117
1118 /*
1119 * key references are protected using RCU and this requires that
1120 * we are in a read-site RCU section during receive processing
1121 */
1122 rcu_read_lock();
1123
1115 sta = tx.sta; 1124 sta = tx.sta;
1116 tx.u.tx.mgmt_interface = mgmt; 1125 tx.u.tx.mgmt_interface = mgmt;
1117 tx.u.tx.mode = local->hw.conf.mode; 1126 tx.u.tx.mode = local->hw.conf.mode;
@@ -1139,6 +1148,7 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb,
1139 1148
1140 if (unlikely(res == TXRX_QUEUED)) { 1149 if (unlikely(res == TXRX_QUEUED)) {
1141 I802_DEBUG_INC(local->tx_handlers_queued); 1150 I802_DEBUG_INC(local->tx_handlers_queued);
1151 rcu_read_unlock();
1142 return 0; 1152 return 0;
1143 } 1153 }
1144 1154
@@ -1196,6 +1206,7 @@ retry:
1196 store->last_frag_rate_ctrl_probe = 1206 store->last_frag_rate_ctrl_probe =
1197 !!(tx.flags & IEEE80211_TXRXD_TXPROBE_LAST_FRAG); 1207 !!(tx.flags & IEEE80211_TXRXD_TXPROBE_LAST_FRAG);
1198 } 1208 }
1209 rcu_read_unlock();
1199 return 0; 1210 return 0;
1200 1211
1201 drop: 1212 drop:
@@ -1205,6 +1216,7 @@ retry:
1205 if (tx.u.tx.extra_frag[i]) 1216 if (tx.u.tx.extra_frag[i])
1206 dev_kfree_skb(tx.u.tx.extra_frag[i]); 1217 dev_kfree_skb(tx.u.tx.extra_frag[i]);
1207 kfree(tx.u.tx.extra_frag); 1218 kfree(tx.u.tx.extra_frag);
1219 rcu_read_unlock();
1208 return 0; 1220 return 0;
1209} 1221}
1210 1222