diff options
author | John W. Linville <linville@tuxdriver.com> | 2012-03-16 13:45:25 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-03-16 13:45:25 -0400 |
commit | 01a282980937f9ca55a3cb06b9c6ff1cc49ea396 (patch) | |
tree | 07a043edc861e245a7a9764751af0898a1f1199a /net/mac80211/wpa.c | |
parent | d5ddb4a59ed43b4c569b4efa8b508d50ef140cc6 (diff) | |
parent | 377526578f2c343ea281a918b18ece1fca65005c (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Conflicts:
drivers/net/wireless/ath/ath9k/hw.c
Diffstat (limited to 'net/mac80211/wpa.c')
-rw-r--r-- | net/mac80211/wpa.c | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index b758350919f..0ae23c60968 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -138,6 +138,10 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) if (skb->len < hdrlen + MICHAEL_MIC_LEN) return RX_DROP_UNUSABLE; + if (skb_linearize(rx->skb)) + return RX_DROP_UNUSABLE; + hdr = (void *)skb->data; + data = skb->data + hdrlen; data_len = skb->len - hdrlen - MICHAEL_MIC_LEN; key = &rx->key->conf.key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY]; @@ -253,6 +257,11 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) if (!rx->sta || skb->len - hdrlen < 12) return RX_DROP_UNUSABLE; + /* it may be possible to optimize this a bit more */ + if (skb_linearize(rx->skb)) + return RX_DROP_UNUSABLE; + hdr = (void *)skb->data; + /* * Let TKIP code verify IV, but skip decryption. * In the case where hardware checks the IV as well, @@ -484,6 +493,14 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) if (!rx->sta || data_len < 0) return RX_DROP_UNUSABLE; + if (status->flag & RX_FLAG_DECRYPTED) { + if (!pskb_may_pull(rx->skb, hdrlen + CCMP_HDR_LEN)) + return RX_DROP_UNUSABLE; + } else { + if (skb_linearize(rx->skb)) + return RX_DROP_UNUSABLE; + } + ccmp_hdr2pn(pn, skb->data + hdrlen); queue = rx->security_idx; @@ -509,7 +526,8 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) memcpy(key->u.ccmp.rx_pn[queue], pn, CCMP_PN_LEN); /* Remove CCMP header and MIC */ - skb_trim(skb, skb->len - CCMP_MIC_LEN); + if (pskb_trim(skb, skb->len - CCMP_MIC_LEN)) + return RX_DROP_UNUSABLE; memmove(skb->data + CCMP_HDR_LEN, skb->data, hdrlen); skb_pull(skb, CCMP_HDR_LEN); @@ -609,6 +627,8 @@ ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx) if (!ieee80211_is_mgmt(hdr->frame_control)) return RX_CONTINUE; + /* management frames are already linear */ + if (skb->len < 24 + sizeof(*mmie)) return RX_DROP_UNUSABLE; |