aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/key.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/key.c')
-rw-r--r--net/mac80211/key.c43
1 files changed, 27 insertions, 16 deletions
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 178f00cf61b9..19e77f626d84 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -12,6 +12,7 @@
12#include <linux/if_ether.h> 12#include <linux/if_ether.h>
13#include <linux/etherdevice.h> 13#include <linux/etherdevice.h>
14#include <linux/list.h> 14#include <linux/list.h>
15#include <linux/rcupdate.h>
15#include <net/mac80211.h> 16#include <net/mac80211.h>
16#include "ieee80211_i.h" 17#include "ieee80211_i.h"
17#include "debugfs_key.h" 18#include "debugfs_key.h"
@@ -120,6 +121,7 @@ struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,
120{ 121{
121 struct ieee80211_key *key; 122 struct ieee80211_key *key;
122 123
124 BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS);
123 BUG_ON(alg == ALG_NONE); 125 BUG_ON(alg == ALG_NONE);
124 126
125 key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL); 127 key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL);
@@ -157,9 +159,15 @@ struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,
157 159
158 ieee80211_debugfs_key_add(key->local, key); 160 ieee80211_debugfs_key_add(key->local, key);
159 161
162 /* remove key first */
163 if (sta)
164 ieee80211_key_free(sta->key);
165 else
166 ieee80211_key_free(sdata->keys[idx]);
167
160 if (sta) { 168 if (sta) {
161 ieee80211_debugfs_key_sta_link(key, sta); 169 ieee80211_debugfs_key_sta_link(key, sta);
162 sta->key = key; 170
163 /* 171 /*
164 * some hardware cannot handle TKIP with QoS, so 172 * some hardware cannot handle TKIP with QoS, so
165 * we indicate whether QoS could be in use. 173 * we indicate whether QoS could be in use.
@@ -179,21 +187,19 @@ struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,
179 sta_info_put(ap); 187 sta_info_put(ap);
180 } 188 }
181 } 189 }
182
183 if (idx >= 0 && idx < NUM_DEFAULT_KEYS) {
184 if (!sdata->keys[idx])
185 sdata->keys[idx] = key;
186 else
187 WARN_ON(1);
188 } else
189 WARN_ON(1);
190 } 190 }
191 191
192 list_add(&key->list, &sdata->key_list); 192 /* enable hwaccel if appropriate */
193
194 if (netif_running(key->sdata->dev)) 193 if (netif_running(key->sdata->dev))
195 ieee80211_key_enable_hw_accel(key); 194 ieee80211_key_enable_hw_accel(key);
196 195
196 if (sta)
197 rcu_assign_pointer(sta->key, key);
198 else
199 rcu_assign_pointer(sdata->keys[idx], key);
200
201 list_add(&key->list, &sdata->key_list);
202
197 return key; 203 return key;
198} 204}
199 205
@@ -202,20 +208,25 @@ void ieee80211_key_free(struct ieee80211_key *key)
202 if (!key) 208 if (!key)
203 return; 209 return;
204 210
205 ieee80211_key_disable_hw_accel(key);
206
207 if (key->sta) { 211 if (key->sta) {
208 key->sta->key = NULL; 212 rcu_assign_pointer(key->sta->key, NULL);
209 } else { 213 } else {
210 if (key->sdata->default_key == key) 214 if (key->sdata->default_key == key)
211 ieee80211_set_default_key(key->sdata, -1); 215 ieee80211_set_default_key(key->sdata, -1);
212 if (key->conf.keyidx >= 0 && 216 if (key->conf.keyidx >= 0 &&
213 key->conf.keyidx < NUM_DEFAULT_KEYS) 217 key->conf.keyidx < NUM_DEFAULT_KEYS)
214 key->sdata->keys[key->conf.keyidx] = NULL; 218 rcu_assign_pointer(key->sdata->keys[key->conf.keyidx],
219 NULL);
215 else 220 else
216 WARN_ON(1); 221 WARN_ON(1);
217 } 222 }
218 223
224 /* wait for all key users to complete */
225 synchronize_rcu();
226
227 /* remove from hwaccel if appropriate */
228 ieee80211_key_disable_hw_accel(key);
229
219 if (key->conf.alg == ALG_CCMP) 230 if (key->conf.alg == ALG_CCMP)
220 ieee80211_aes_key_free(key->u.ccmp.tfm); 231 ieee80211_aes_key_free(key->u.ccmp.tfm);
221 ieee80211_debugfs_key_remove(key); 232 ieee80211_debugfs_key_remove(key);
@@ -235,7 +246,7 @@ void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx)
235 if (sdata->default_key != key) { 246 if (sdata->default_key != key) {
236 ieee80211_debugfs_key_remove_default(sdata); 247 ieee80211_debugfs_key_remove_default(sdata);
237 248
238 sdata->default_key = key; 249 rcu_assign_pointer(sdata->default_key, key);
239 250
240 if (sdata->default_key) 251 if (sdata->default_key)
241 ieee80211_debugfs_key_add_default(sdata); 252 ieee80211_debugfs_key_add_default(sdata);