Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 66415
b: refs/heads/master
c: d4e46a3
h: refs/heads/master
i:
  66413: 295e85c
  66411: 557b20a
  66407: deda9db
  66399: 06f34e4
v: v3
  • Loading branch information
Johannes Berg authored and David S. Miller committed Oct 10, 2007
1 parent 314b418 commit 81be5d0
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 28 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c29b9b9b0235d56e5602f61ed38702dd376aae20
refs/heads/master: d4e46a3d9869563c6210b01bb651c40cbe65da80
5 changes: 1 addition & 4 deletions trunk/net/mac80211/ieee80211_ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,8 @@ static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr,
key = NULL;
} else {
/*
* Need to free it before allocating a new one with
* with the same index or the ordering to the driver's
* set_key() callback becomes confused.
* Automatically frees any old key if present.
*/
ieee80211_key_free(key);
key = ieee80211_key_alloc(sdata, sta, alg, idx, key_len, _key);
if (!key) {
ret = -ENOMEM;
Expand Down
43 changes: 27 additions & 16 deletions trunk/net/mac80211/key.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <linux/if_ether.h>
#include <linux/etherdevice.h>
#include <linux/list.h>
#include <linux/rcupdate.h>
#include <net/mac80211.h>
#include "ieee80211_i.h"
#include "debugfs_key.h"
Expand Down Expand Up @@ -120,6 +121,7 @@ struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,
{
struct ieee80211_key *key;

BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS);
BUG_ON(alg == ALG_NONE);

key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL);
Expand Down Expand Up @@ -157,9 +159,15 @@ struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,

ieee80211_debugfs_key_add(key->local, key);

/* remove key first */
if (sta)
ieee80211_key_free(sta->key);
else
ieee80211_key_free(sdata->keys[idx]);

if (sta) {
ieee80211_debugfs_key_sta_link(key, sta);
sta->key = key;

/*
* some hardware cannot handle TKIP with QoS, so
* we indicate whether QoS could be in use.
Expand All @@ -179,21 +187,19 @@ struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,
sta_info_put(ap);
}
}

if (idx >= 0 && idx < NUM_DEFAULT_KEYS) {
if (!sdata->keys[idx])
sdata->keys[idx] = key;
else
WARN_ON(1);
} else
WARN_ON(1);
}

list_add(&key->list, &sdata->key_list);

/* enable hwaccel if appropriate */
if (netif_running(key->sdata->dev))
ieee80211_key_enable_hw_accel(key);

if (sta)
rcu_assign_pointer(sta->key, key);
else
rcu_assign_pointer(sdata->keys[idx], key);

list_add(&key->list, &sdata->key_list);

return key;
}

Expand All @@ -202,20 +208,25 @@ void ieee80211_key_free(struct ieee80211_key *key)
if (!key)
return;

ieee80211_key_disable_hw_accel(key);

if (key->sta) {
key->sta->key = NULL;
rcu_assign_pointer(key->sta->key, NULL);
} else {
if (key->sdata->default_key == key)
ieee80211_set_default_key(key->sdata, -1);
if (key->conf.keyidx >= 0 &&
key->conf.keyidx < NUM_DEFAULT_KEYS)
key->sdata->keys[key->conf.keyidx] = NULL;
rcu_assign_pointer(key->sdata->keys[key->conf.keyidx],
NULL);
else
WARN_ON(1);
}

/* wait for all key users to complete */
synchronize_rcu();

/* remove from hwaccel if appropriate */
ieee80211_key_disable_hw_accel(key);

if (key->conf.alg == ALG_CCMP)
ieee80211_aes_key_free(key->u.ccmp.tfm);
ieee80211_debugfs_key_remove(key);
Expand All @@ -235,7 +246,7 @@ void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx)
if (sdata->default_key != key) {
ieee80211_debugfs_key_remove_default(sdata);

sdata->default_key = key;
rcu_assign_pointer(sdata->default_key, key);

if (sdata->default_key)
ieee80211_debugfs_key_add_default(sdata);
Expand Down
20 changes: 17 additions & 3 deletions trunk/net/mac80211/rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/rcupdate.h>
#include <net/mac80211.h>
#include <net/ieee80211_radiotap.h>

Expand Down Expand Up @@ -311,6 +312,7 @@ ieee80211_rx_h_load_key(struct ieee80211_txrx_data *rx)
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
int keyidx;
int hdrlen;
struct ieee80211_key *stakey = NULL;

/*
* Key selection 101
Expand Down Expand Up @@ -348,8 +350,11 @@ ieee80211_rx_h_load_key(struct ieee80211_txrx_data *rx)
if (!(rx->flags & IEEE80211_TXRXD_RXRA_MATCH))
return TXRX_CONTINUE;

if (!is_multicast_ether_addr(hdr->addr1) && rx->sta && rx->sta->key) {
rx->key = rx->sta->key;
if (rx->sta)
stakey = rcu_dereference(rx->sta->key);

if (!is_multicast_ether_addr(hdr->addr1) && stakey) {
rx->key = stakey;
} else {
/*
* The device doesn't give us the IV so we won't be
Expand All @@ -374,7 +379,7 @@ ieee80211_rx_h_load_key(struct ieee80211_txrx_data *rx)
*/
keyidx = rx->skb->data[hdrlen + 3] >> 6;

rx->key = rx->sdata->keys[keyidx];
rx->key = rcu_dereference(rx->sdata->keys[keyidx]);

/*
* RSNA-protected unicast frames should always be sent with
Expand Down Expand Up @@ -1364,6 +1369,12 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
skb_pull(skb, radiotap_len);
}

/*
* key references are protected using RCU and this requires that
* we are in a read-site RCU section during receive processing
*/
rcu_read_lock();

hdr = (struct ieee80211_hdr *) skb->data;
memset(&rx, 0, sizeof(rx));
rx.skb = skb;
Expand Down Expand Up @@ -1404,6 +1415,7 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
ieee80211_invoke_rx_handlers(local, local->rx_handlers, &rx,
rx.sta);
sta_info_put(sta);
rcu_read_unlock();
return;
}

Expand Down Expand Up @@ -1465,6 +1477,8 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
read_unlock(&local->sub_if_lock);

end:
rcu_read_unlock();

if (sta)
sta_info_put(sta);
}
Expand Down
20 changes: 16 additions & 4 deletions trunk/net/mac80211/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <linux/skbuff.h>
#include <linux/etherdevice.h>
#include <linux/bitmap.h>
#include <linux/rcupdate.h>
#include <net/net_namespace.h>
#include <net/ieee80211_radiotap.h>
#include <net/cfg80211.h>
Expand Down Expand Up @@ -427,14 +428,16 @@ ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx)
static ieee80211_txrx_result
ieee80211_tx_h_select_key(struct ieee80211_txrx_data *tx)
{
struct ieee80211_key *key;

tx->u.tx.control->key_idx = HW_KEY_IDX_INVALID;

if (unlikely(tx->u.tx.control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
tx->key = NULL;
else if (tx->sta && tx->sta->key)
tx->key = tx->sta->key;
else if (tx->sdata->default_key)
tx->key = tx->sdata->default_key;
else if (tx->sta && (key = rcu_dereference(tx->sta->key)))
tx->key = key;
else if ((key = rcu_dereference(tx->sdata->default_key)))
tx->key = key;
else if (tx->sdata->drop_unencrypted &&
!(tx->sdata->eapol && ieee80211_is_eapol(tx->skb))) {
I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted);
Expand Down Expand Up @@ -1112,6 +1115,12 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb,
return 0;
}

/*
* key references are protected using RCU and this requires that
* we are in a read-site RCU section during receive processing
*/
rcu_read_lock();

sta = tx.sta;
tx.u.tx.mgmt_interface = mgmt;
tx.u.tx.mode = local->hw.conf.mode;
Expand Down Expand Up @@ -1139,6 +1148,7 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb,

if (unlikely(res == TXRX_QUEUED)) {
I802_DEBUG_INC(local->tx_handlers_queued);
rcu_read_unlock();
return 0;
}

Expand Down Expand Up @@ -1196,6 +1206,7 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb,
store->last_frag_rate_ctrl_probe =
!!(tx.flags & IEEE80211_TXRXD_TXPROBE_LAST_FRAG);
}
rcu_read_unlock();
return 0;

drop:
Expand All @@ -1205,6 +1216,7 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb,
if (tx.u.tx.extra_frag[i])
dev_kfree_skb(tx.u.tx.extra_frag[i]);
kfree(tx.u.tx.extra_frag);
rcu_read_unlock();
return 0;
}

Expand Down

0 comments on commit 81be5d0

Please sign in to comment.