]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blobdiff - net/mac80211/wpa.c
mac80211: linearize SKBs as needed for crypto
[mirror_ubuntu-zesty-kernel.git] / net / mac80211 / wpa.c
index b758350919ff4641e69127a220f3c450fb07fcc9..0ae23c60968c0a9e82b214042ee5b01c4f27bb7d 100644 (file)
@@ -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;