diff options
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 b758350919ff..0ae23c60968c 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; |