aboutsummaryrefslogtreecommitdiff
path: root/net/ieee80211
diff options
context:
space:
mode:
authorJames Ketrenos <jketreno@linux.intel.com>2005-09-21 11:53:43 -0500
committerJeff Garzik <jgarzik@pobox.com>2005-09-21 23:01:52 -0400
commit20d64713ae71c0b0aa06084acbef2244021baaca (patch)
treef9af562b0bc70f7f75d0195aacf155fd3ec6628a /net/ieee80211
parent4ca5253d573d7b3785dbb2f123f948fdca6ee235 (diff)
[PATCH] ieee80211: Fixed a kernel oops on module unload
tree 367069f24fc38b4aa910e86ff40094d2078d8aa7 parent a33a1982012e9070736e3717231714dc9892303b author James Ketrenos <jketreno@linux.intel.com> 1124430800 -0500 committer James Ketrenos <jketreno@linux.intel.com> 1127310571 -0500 Fixed a kernel oops on module unload by adding spin lock protection to ieee80211's crypt handlers (thanks to Zhu Yi) Modified scan result logic to report WPA and RSN IEs if set (vs.being based on wpa_enabled) Added ieee80211_device as the first parameter to the crypt init() method. TKIP modified to use that structure for determining whether to countermeasures are active. Signed-off-by: James Ketrenos <jketreno@linux.intel.com> Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
Diffstat (limited to 'net/ieee80211')
-rw-r--r--net/ieee80211/ieee80211_crypt.c9
-rw-r--r--net/ieee80211/ieee80211_crypt_ccmp.c2
-rw-r--r--net/ieee80211/ieee80211_crypt_tkip.c31
-rw-r--r--net/ieee80211/ieee80211_crypt_wep.c2
-rw-r--r--net/ieee80211/ieee80211_rx.c11
-rw-r--r--net/ieee80211/ieee80211_tx.c14
-rw-r--r--net/ieee80211/ieee80211_wx.c6
7 files changed, 38 insertions, 37 deletions
diff --git a/net/ieee80211/ieee80211_crypt.c b/net/ieee80211/ieee80211_crypt.c
index dc835f68edd..0c366299db0 100644
--- a/net/ieee80211/ieee80211_crypt.c
+++ b/net/ieee80211/ieee80211_crypt.c
@@ -41,7 +41,9 @@ void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, int force)
{
struct list_head *ptr, *n;
struct ieee80211_crypt_data *entry;
+ unsigned long flags;
+ spin_lock_irqsave(&ieee->lock, flags);
for (ptr = ieee->crypt_deinit_list.next, n = ptr->next;
ptr != &ieee->crypt_deinit_list; ptr = n, n = ptr->next) {
entry = list_entry(ptr, struct ieee80211_crypt_data, list);
@@ -57,14 +59,13 @@ void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, int force)
}
kfree(entry);
}
+ spin_unlock_irqrestore(&ieee->lock, flags);
}
void ieee80211_crypt_deinit_handler(unsigned long data)
{
struct ieee80211_device *ieee = (struct ieee80211_device *)data;
- unsigned long flags;
- spin_lock_irqsave(&ieee->lock, flags);
ieee80211_crypt_deinit_entries(ieee, 0);
if (!list_empty(&ieee->crypt_deinit_list)) {
printk(KERN_DEBUG "%s: entries remaining in delayed crypt "
@@ -72,7 +73,6 @@ void ieee80211_crypt_deinit_handler(unsigned long data)
ieee->crypt_deinit_timer.expires = jiffies + HZ;
add_timer(&ieee->crypt_deinit_timer);
}
- spin_unlock_irqrestore(&ieee->lock, flags);
}
@@ -182,7 +182,8 @@ struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name)
return NULL;
}
-static void *ieee80211_crypt_null_init(int keyidx)
+static void *ieee80211_crypt_null_init(struct ieee80211_device *ieee,
+ int keyidx)
{
return (void *)1;
}
diff --git a/net/ieee80211/ieee80211_crypt_ccmp.c b/net/ieee80211/ieee80211_crypt_ccmp.c
index 7b6290885e7..1e6644b133d 100644
--- a/net/ieee80211/ieee80211_crypt_ccmp.c
+++ b/net/ieee80211/ieee80211_crypt_ccmp.c
@@ -74,7 +74,7 @@ static void ieee80211_ccmp_aes_encrypt(struct crypto_tfm *tfm,
crypto_cipher_encrypt(tfm, &dst, &src, AES_BLOCK_LEN);
}
-static void *ieee80211_ccmp_init(int key_idx)
+static void *ieee80211_ccmp_init(struct ieee80211_device *ieee, int key_idx)
{
struct ieee80211_ccmp_data *priv;
diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c
index dca380e5745..0c495f07e71 100644
--- a/net/ieee80211/ieee80211_crypt_tkip.c
+++ b/net/ieee80211/ieee80211_crypt_tkip.c
@@ -59,9 +59,11 @@ struct ieee80211_tkip_data {
/* scratch buffers for virt_to_page() (crypto API) */
u8 rx_hdr[16], tx_hdr[16];
+
+ struct ieee80211_device *ieee;
};
-static void *ieee80211_tkip_init(int key_idx)
+static void *ieee80211_tkip_init(struct ieee80211_device *ieee, int key_idx)
{
struct ieee80211_tkip_data *priv;
@@ -69,6 +71,9 @@ static void *ieee80211_tkip_init(int key_idx)
if (priv == NULL)
goto fail;
memset(priv, 0, sizeof(*priv));
+
+ priv->ieee = ieee;
+
priv->key_idx = key_idx;
priv->tfm_arc4 = crypto_alloc_tfm("arc4", 0);
@@ -264,11 +269,21 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
u32 crc;
struct scatterlist sg;
+ hdr = (struct ieee80211_hdr *)skb->data;
+
+ if (tkey->ieee->tkip_countermeasures) {
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
+ "TX packet to " MAC_FMT "\n",
+ tkey->ieee->dev->name, MAC_ARG(hdr->addr1));
+ }
+ return -1;
+ }
+
if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 4 ||
skb->len < hdr_len)
return -1;
- hdr = (struct ieee80211_hdr *)skb->data;
if (!tkey->tx_phase1_done) {
tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2,
tkey->tx_iv32);
@@ -325,10 +340,20 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
struct scatterlist sg;
int plen;
+ hdr = (struct ieee80211_hdr *)skb->data;
+
+ if (tkey->ieee->tkip_countermeasures) {
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
+ "received packet from " MAC_FMT "\n",
+ tkey->ieee->dev->name, MAC_ARG(hdr->addr2));
+ }
+ return -1;
+ }
+
if (skb->len < hdr_len + 8 + 4)
return -1;
- hdr = (struct ieee80211_hdr *)skb->data;
pos = skb->data + hdr_len;
keyidx = pos[3];
if (!(keyidx & (1 << 5))) {
diff --git a/net/ieee80211/ieee80211_crypt_wep.c b/net/ieee80211/ieee80211_crypt_wep.c
index ebe16155e79..63e783fa517 100644
--- a/net/ieee80211/ieee80211_crypt_wep.c
+++ b/net/ieee80211/ieee80211_crypt_wep.c
@@ -37,7 +37,7 @@ struct prism2_wep_data {
struct crypto_tfm *tfm;
};
-static void *prism2_wep_init(int keyidx)
+static void *prism2_wep_init(struct ieee80211_device *ieee, int keyidx)
{
struct prism2_wep_data *priv;
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index e0337c8fcde..9a125d45289 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -280,17 +280,6 @@ ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb,
hdr = (struct ieee80211_hdr *)skb->data;
hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
-#ifdef CONFIG_IEEE80211_CRYPT_TKIP
- if (ieee->tkip_countermeasures && strcmp(crypt->ops->name, "TKIP") == 0) {
- if (net_ratelimit()) {
- printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
- "received packet from " MAC_FMT "\n",
- ieee->dev->name, MAC_ARG(hdr->addr2));
- }
- return -1;
- }
-#endif
-
atomic_inc(&crypt->refcnt);
res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
atomic_dec(&crypt->refcnt);
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index 1a09448016e..435ef5a73d7 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -157,20 +157,6 @@ static inline int ieee80211_encrypt_fragment(struct ieee80211_device *ieee,
struct ieee80211_crypt_data *crypt = ieee->crypt[ieee->tx_keyidx];
int res;
-#ifdef CONFIG_IEEE80211_CRYPT_TKIP
- struct ieee80211_hdr *header;
-
- if (ieee->tkip_countermeasures &&
- crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
- header = (struct ieee80211_hdr *)frag->data;
- if (net_ratelimit()) {
- printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
- "TX packet to " MAC_FMT "\n",
- ieee->dev->name, MAC_ARG(header->addr1));
- }
- return -1;
- }
-#endif
/* To encrypt, frame format is:
* IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index 04f0897b065..fc4e1377aba 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -182,7 +182,7 @@ static inline char *ipw2100_translate_scan(struct ieee80211_device *ieee,
if (iwe.u.data.length)
start = iwe_stream_add_point(start, stop, &iwe, custom);
- if (ieee->wpa_enabled && network->wpa_ie_len) {
+ if (network->wpa_ie_len) {
char buf[MAX_WPA_IE_LEN * 2 + 30];
u8 *p = buf;
@@ -197,7 +197,7 @@ static inline char *ipw2100_translate_scan(struct ieee80211_device *ieee,
start = iwe_stream_add_point(start, stop, &iwe, buf);
}
- if (ieee->wpa_enabled && network->rsn_ie_len) {
+ if (network->rsn_ie_len) {
char buf[MAX_WPA_IE_LEN * 2 + 30];
u8 *p = buf;
@@ -351,7 +351,7 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
}
if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
- new_crypt->priv = new_crypt->ops->init(key);
+ new_crypt->priv = new_crypt->ops->init(ieee, key);
if (!new_crypt->ops || !new_crypt->priv) {
kfree(new_crypt);