aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/rx.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r--net/mac80211/rx.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 4fb8c7026f11..91b7886bf797 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -13,6 +13,7 @@
13#include <linux/skbuff.h> 13#include <linux/skbuff.h>
14#include <linux/netdevice.h> 14#include <linux/netdevice.h>
15#include <linux/etherdevice.h> 15#include <linux/etherdevice.h>
16#include <linux/rcupdate.h>
16#include <net/mac80211.h> 17#include <net/mac80211.h>
17#include <net/ieee80211_radiotap.h> 18#include <net/ieee80211_radiotap.h>
18 19
@@ -311,6 +312,7 @@ ieee80211_rx_h_load_key(struct ieee80211_txrx_data *rx)
311 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; 312 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
312 int keyidx; 313 int keyidx;
313 int hdrlen; 314 int hdrlen;
315 struct ieee80211_key *stakey = NULL;
314 316
315 /* 317 /*
316 * Key selection 101 318 * Key selection 101
@@ -348,8 +350,11 @@ ieee80211_rx_h_load_key(struct ieee80211_txrx_data *rx)
348 if (!(rx->flags & IEEE80211_TXRXD_RXRA_MATCH)) 350 if (!(rx->flags & IEEE80211_TXRXD_RXRA_MATCH))
349 return TXRX_CONTINUE; 351 return TXRX_CONTINUE;
350 352
351 if (!is_multicast_ether_addr(hdr->addr1) && rx->sta && rx->sta->key) { 353 if (rx->sta)
352 rx->key = rx->sta->key; 354 stakey = rcu_dereference(rx->sta->key);
355
356 if (!is_multicast_ether_addr(hdr->addr1) && stakey) {
357 rx->key = stakey;
353 } else { 358 } else {
354 /* 359 /*
355 * The device doesn't give us the IV so we won't be 360 * The device doesn't give us the IV so we won't be
@@ -374,7 +379,7 @@ ieee80211_rx_h_load_key(struct ieee80211_txrx_data *rx)
374 */ 379 */
375 keyidx = rx->skb->data[hdrlen + 3] >> 6; 380 keyidx = rx->skb->data[hdrlen + 3] >> 6;
376 381
377 rx->key = rx->sdata->keys[keyidx]; 382 rx->key = rcu_dereference(rx->sdata->keys[keyidx]);
378 383
379 /* 384 /*
380 * RSNA-protected unicast frames should always be sent with 385 * RSNA-protected unicast frames should always be sent with
@@ -1364,6 +1369,12 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
1364 skb_pull(skb, radiotap_len); 1369 skb_pull(skb, radiotap_len);
1365 } 1370 }
1366 1371
1372 /*
1373 * key references are protected using RCU and this requires that
1374 * we are in a read-site RCU section during receive processing
1375 */
1376 rcu_read_lock();
1377
1367 hdr = (struct ieee80211_hdr *) skb->data; 1378 hdr = (struct ieee80211_hdr *) skb->data;
1368 memset(&rx, 0, sizeof(rx)); 1379 memset(&rx, 0, sizeof(rx));
1369 rx.skb = skb; 1380 rx.skb = skb;
@@ -1404,6 +1415,7 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
1404 ieee80211_invoke_rx_handlers(local, local->rx_handlers, &rx, 1415 ieee80211_invoke_rx_handlers(local, local->rx_handlers, &rx,
1405 rx.sta); 1416 rx.sta);
1406 sta_info_put(sta); 1417 sta_info_put(sta);
1418 rcu_read_unlock();
1407 return; 1419 return;
1408 } 1420 }
1409 1421
@@ -1465,6 +1477,8 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
1465 read_unlock(&local->sub_if_lock); 1477 read_unlock(&local->sub_if_lock);
1466 1478
1467 end: 1479 end:
1480 rcu_read_unlock();
1481
1468 if (sta) 1482 if (sta)
1469 sta_info_put(sta); 1483 sta_info_put(sta);
1470} 1484}