macsec: allocate sg and iv on the heap
authorSabrina Dubroca <sd@queasysnail.net>
Tue, 14 Jun 2016 13:25:15 +0000 (15:25 +0200)
committerDavid S. Miller <davem@davemloft.net>
Wed, 15 Jun 2016 21:47:46 +0000 (14:47 -0700)
For the crypto callbacks to work properly, we cannot have sg and iv on
the stack.  Use kmalloc instead, with a single allocation for
aead_request + scatterlist + iv.

Fixes: c09440f7dcb3 ("macsec: introduce IEEE 802.1AE driver")
Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/macsec.c

index e80736f6acd7726e77768c21e2c3eb6b1744336f..189ea3e8e8a040e8f28583b3db005677c1c573f6 100644 (file)
@@ -605,12 +605,41 @@ static void macsec_encrypt_done(struct crypto_async_request *base, int err)
        dev_put(dev);
 }
 
+static struct aead_request *macsec_alloc_req(struct crypto_aead *tfm,
+                                            unsigned char **iv,
+                                            struct scatterlist **sg)
+{
+       size_t size, iv_offset, sg_offset;
+       struct aead_request *req;
+       void *tmp;
+
+       size = sizeof(struct aead_request) + crypto_aead_reqsize(tfm);
+       iv_offset = size;
+       size += GCM_AES_IV_LEN;
+
+       size = ALIGN(size, __alignof__(struct scatterlist));
+       sg_offset = size;
+       size += sizeof(struct scatterlist) * (MAX_SKB_FRAGS + 1);
+
+       tmp = kmalloc(size, GFP_ATOMIC);
+       if (!tmp)
+               return NULL;
+
+       *iv = (unsigned char *)(tmp + iv_offset);
+       *sg = (struct scatterlist *)(tmp + sg_offset);
+       req = tmp;
+
+       aead_request_set_tfm(req, tfm);
+
+       return req;
+}
+
 static struct sk_buff *macsec_encrypt(struct sk_buff *skb,
                                      struct net_device *dev)
 {
        int ret;
-       struct scatterlist sg[MAX_SKB_FRAGS + 1];
-       unsigned char iv[GCM_AES_IV_LEN];
+       struct scatterlist *sg;
+       unsigned char *iv;
        struct ethhdr *eth;
        struct macsec_eth_header *hh;
        size_t unprotected_len;
@@ -668,8 +697,6 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb,
        macsec_fill_sectag(hh, secy, pn);
        macsec_set_shortlen(hh, unprotected_len - 2 * ETH_ALEN);
 
-       macsec_fill_iv(iv, secy->sci, pn);
-
        skb_put(skb, secy->icv_len);
 
        if (skb->len - ETH_HLEN > macsec_priv(dev)->real_dev->mtu) {
@@ -684,13 +711,15 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb,
                return ERR_PTR(-EINVAL);
        }
 
-       req = aead_request_alloc(tx_sa->key.tfm, GFP_ATOMIC);
+       req = macsec_alloc_req(tx_sa->key.tfm, &iv, &sg);
        if (!req) {
                macsec_txsa_put(tx_sa);
                kfree_skb(skb);
                return ERR_PTR(-ENOMEM);
        }
 
+       macsec_fill_iv(iv, secy->sci, pn);
+
        sg_init_table(sg, MAX_SKB_FRAGS + 1);
        skb_to_sgvec(skb, sg, 0, skb->len);
 
@@ -861,7 +890,6 @@ static void macsec_decrypt_done(struct crypto_async_request *base, int err)
 out:
        macsec_rxsa_put(rx_sa);
        dev_put(dev);
-       return;
 }
 
 static struct sk_buff *macsec_decrypt(struct sk_buff *skb,
@@ -871,8 +899,8 @@ static struct sk_buff *macsec_decrypt(struct sk_buff *skb,
                                      struct macsec_secy *secy)
 {
        int ret;
-       struct scatterlist sg[MAX_SKB_FRAGS + 1];
-       unsigned char iv[GCM_AES_IV_LEN];
+       struct scatterlist *sg;
+       unsigned char *iv;
        struct aead_request *req;
        struct macsec_eth_header *hdr;
        u16 icv_len = secy->icv_len;
@@ -882,7 +910,7 @@ static struct sk_buff *macsec_decrypt(struct sk_buff *skb,
        if (!skb)
                return ERR_PTR(-ENOMEM);
 
-       req = aead_request_alloc(rx_sa->key.tfm, GFP_ATOMIC);
+       req = macsec_alloc_req(rx_sa->key.tfm, &iv, &sg);
        if (!req) {
                kfree_skb(skb);
                return ERR_PTR(-ENOMEM);