Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5d9649b3 authored by Sabrina Dubroca's avatar Sabrina Dubroca Committed by David S. Miller
Browse files

macsec: allocate sg and iv on the heap



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: c09440f7 ("macsec: introduce IEEE 802.1AE driver")
Signed-off-by: default avatarSabrina Dubroca <sd@queasysnail.net>
Acked-by: default avatarHannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b196c22a
Loading
Loading
Loading
Loading
+37 −9
Original line number Original line Diff line number Diff line
@@ -605,12 +605,41 @@ static void macsec_encrypt_done(struct crypto_async_request *base, int err)
	dev_put(dev);
	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,
static struct sk_buff *macsec_encrypt(struct sk_buff *skb,
				      struct net_device *dev)
				      struct net_device *dev)
{
{
	int ret;
	int ret;
	struct scatterlist sg[MAX_SKB_FRAGS + 1];
	struct scatterlist *sg;
	unsigned char iv[GCM_AES_IV_LEN];
	unsigned char *iv;
	struct ethhdr *eth;
	struct ethhdr *eth;
	struct macsec_eth_header *hh;
	struct macsec_eth_header *hh;
	size_t unprotected_len;
	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_fill_sectag(hh, secy, pn);
	macsec_set_shortlen(hh, unprotected_len - 2 * ETH_ALEN);
	macsec_set_shortlen(hh, unprotected_len - 2 * ETH_ALEN);


	macsec_fill_iv(iv, secy->sci, pn);

	skb_put(skb, secy->icv_len);
	skb_put(skb, secy->icv_len);


	if (skb->len - ETH_HLEN > macsec_priv(dev)->real_dev->mtu) {
	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);
		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) {
	if (!req) {
		macsec_txsa_put(tx_sa);
		macsec_txsa_put(tx_sa);
		kfree_skb(skb);
		kfree_skb(skb);
		return ERR_PTR(-ENOMEM);
		return ERR_PTR(-ENOMEM);
	}
	}


	macsec_fill_iv(iv, secy->sci, pn);

	sg_init_table(sg, MAX_SKB_FRAGS + 1);
	sg_init_table(sg, MAX_SKB_FRAGS + 1);
	skb_to_sgvec(skb, sg, 0, skb->len);
	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:
out:
	macsec_rxsa_put(rx_sa);
	macsec_rxsa_put(rx_sa);
	dev_put(dev);
	dev_put(dev);
	return;
}
}


static struct sk_buff *macsec_decrypt(struct sk_buff *skb,
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)
				      struct macsec_secy *secy)
{
{
	int ret;
	int ret;
	struct scatterlist sg[MAX_SKB_FRAGS + 1];
	struct scatterlist *sg;
	unsigned char iv[GCM_AES_IV_LEN];
	unsigned char *iv;
	struct aead_request *req;
	struct aead_request *req;
	struct macsec_eth_header *hdr;
	struct macsec_eth_header *hdr;
	u16 icv_len = secy->icv_len;
	u16 icv_len = secy->icv_len;
@@ -882,7 +910,7 @@ static struct sk_buff *macsec_decrypt(struct sk_buff *skb,
	if (!skb)
	if (!skb)
		return ERR_PTR(-ENOMEM);
		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) {
	if (!req) {
		kfree_skb(skb);
		kfree_skb(skb);
		return ERR_PTR(-ENOMEM);
		return ERR_PTR(-ENOMEM);