Skip to content

Commit

Permalink
mac80211: fix key replacing, hw accel
Browse files Browse the repository at this point in the history
Even though I thought about it a lot and had also tested it, some
of my recent changes in the key code broke replacing keys, making
the kernel oops because a key is removed from a list while not on
it.

This patch fixes that using the list as an indication whether or
not the key is on it (an empty list means it's not on any list.)

Also, this patch fixes hw accel enabling, the check for not doing
hw accel when the interface is down was lost and is restored by
this.

Additionally, move adding the key to the list into the function
__ieee80211_key_replace() for more consistency.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Johannes Berg authored and John W. Linville committed Feb 29, 2008
1 parent db4d116 commit e486182
Showing 1 changed file with 20 additions and 7 deletions.
27 changes: 20 additions & 7 deletions net/mac80211/key.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
key->conf.keyidx = idx;
key->conf.keylen = key_len;
memcpy(key->conf.key, key_data, key_len);
INIT_LIST_HEAD(&key->list);

if (alg == ALG_CCMP) {
/*
Expand Down Expand Up @@ -189,14 +190,20 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
ieee80211_set_default_key(sdata, -1);

rcu_assign_pointer(sdata->keys[idx], new);
if (new)
list_add(&new->list, &sdata->key_list);

if (defkey && new)
ieee80211_set_default_key(sdata, new->conf.keyidx);
}

if (key) {
ieee80211_key_mark_hw_accel_off(key);
list_del(&key->list);
/*
* We'll use an empty list to indicate that the key
* has already been removed.
*/
list_del_init(&key->list);
}
}

Expand Down Expand Up @@ -251,12 +258,13 @@ void ieee80211_key_link(struct ieee80211_key *key,

__ieee80211_key_replace(sdata, sta, old_key, key);

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

synchronize_rcu();
if (old_key) {
synchronize_rcu();
ieee80211_key_free(old_key);
}

ieee80211_key_free(old_key);
ieee80211_key_enable_hw_accel(key);
if (netif_running(sdata->dev))
ieee80211_key_enable_hw_accel(key);
}

void ieee80211_key_free(struct ieee80211_key *key)
Expand All @@ -274,8 +282,13 @@ void ieee80211_key_free(struct ieee80211_key *key)
* Because other code may have key reference (RCU protected)
* right now, we then wait for a grace period before freeing
* it.
* An empty list indicates it was never added to the key list
* or has been removed already. It may, however, still be in
* hardware for acceleration.
*/
__ieee80211_key_replace(key->sdata, key->sta, key, NULL);
if (!list_empty(&key->list))
__ieee80211_key_replace(key->sdata, key->sta,
key, NULL);

synchronize_rcu();

Expand Down

0 comments on commit e486182

Please sign in to comment.