Commit 61266d5f authored by David S. Miller's avatar David S. Miller

[IPSEC]: In ESP, do not put scatterlist array on stack.

Put it in per-esp data instead.  Noticed by Linus.
Signed-off-by: default avatarDavid S. Miller <davem@redhat.com>
parent b4321277
...@@ -2,9 +2,14 @@ ...@@ -2,9 +2,14 @@
#define _NET_ESP_H #define _NET_ESP_H
#include <net/xfrm.h> #include <net/xfrm.h>
#include <asm/scatterlist.h>
#define ESP_NUM_FAST_SG 4
struct esp_data struct esp_data
{ {
struct scatterlist sgbuf[ESP_NUM_FAST_SG];
/* Confidentiality */ /* Confidentiality */
struct { struct {
u8 *key; /* Key */ u8 *key; /* Key */
......
...@@ -11,8 +11,6 @@ ...@@ -11,8 +11,6 @@
#include <net/icmp.h> #include <net/icmp.h>
#include <net/udp.h> #include <net/udp.h>
#define MAX_SG_ONSTACK 4
/* decapsulation data for use when post-processing */ /* decapsulation data for use when post-processing */
struct esp_decap_data { struct esp_decap_data {
xfrm_address_t saddr; xfrm_address_t saddr;
...@@ -185,17 +183,16 @@ int esp_output(struct sk_buff **pskb) ...@@ -185,17 +183,16 @@ int esp_output(struct sk_buff **pskb)
crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm));
do { do {
struct scatterlist sgbuf[nfrags>MAX_SG_ONSTACK ? 0 : nfrags]; struct scatterlist *sg = &esp->sgbuf[0];
struct scatterlist *sg = sgbuf;
if (unlikely(nfrags > MAX_SG_ONSTACK)) { if (unlikely(nfrags > ESP_NUM_FAST_SG)) {
sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC); sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC);
if (!sg) if (!sg)
goto error; goto error;
} }
skb_to_sgvec(*pskb, sg, esph->enc_data+esp->conf.ivlen-(*pskb)->data, clen); skb_to_sgvec(*pskb, sg, esph->enc_data+esp->conf.ivlen-(*pskb)->data, clen);
crypto_cipher_encrypt(tfm, sg, sg, clen); crypto_cipher_encrypt(tfm, sg, sg, clen);
if (unlikely(sg != sgbuf)) if (unlikely(sg != &esp->sgbuf[0]))
kfree(sg); kfree(sg);
} while (0); } while (0);
...@@ -283,19 +280,18 @@ int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_bu ...@@ -283,19 +280,18 @@ int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_bu
{ {
u8 nexthdr[2]; u8 nexthdr[2];
struct scatterlist sgbuf[nfrags>MAX_SG_ONSTACK ? 0 : nfrags]; struct scatterlist *sg = &esp->sgbuf[0];
struct scatterlist *sg = sgbuf;
u8 workbuf[60]; u8 workbuf[60];
int padlen; int padlen;
if (unlikely(nfrags > MAX_SG_ONSTACK)) { if (unlikely(nfrags > ESP_NUM_FAST_SG)) {
sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC); sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC);
if (!sg) if (!sg)
goto out; goto out;
} }
skb_to_sgvec(skb, sg, sizeof(struct ip_esp_hdr) + esp->conf.ivlen, elen); skb_to_sgvec(skb, sg, sizeof(struct ip_esp_hdr) + esp->conf.ivlen, elen);
crypto_cipher_decrypt(esp->conf.tfm, sg, sg, elen); crypto_cipher_decrypt(esp->conf.tfm, sg, sg, elen);
if (unlikely(sg != sgbuf)) if (unlikely(sg != &esp->sgbuf[0]))
kfree(sg); kfree(sg);
if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2)) if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2))
......
...@@ -38,8 +38,6 @@ ...@@ -38,8 +38,6 @@
#include <net/ipv6.h> #include <net/ipv6.h>
#include <linux/icmpv6.h> #include <linux/icmpv6.h>
#define MAX_SG_ONSTACK 4
int esp6_output(struct sk_buff **pskb) int esp6_output(struct sk_buff **pskb)
{ {
int err; int err;
...@@ -151,17 +149,16 @@ int esp6_output(struct sk_buff **pskb) ...@@ -151,17 +149,16 @@ int esp6_output(struct sk_buff **pskb)
crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm));
do { do {
struct scatterlist sgbuf[nfrags>MAX_SG_ONSTACK ? 0 : nfrags]; struct scatterlist *sg = &esp->sgbuf[0];
struct scatterlist *sg = sgbuf;
if (unlikely(nfrags > MAX_SG_ONSTACK)) { if (unlikely(nfrags > ESP_NUM_FAST_SG)) {
sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC); sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC);
if (!sg) if (!sg)
goto error; goto error;
} }
skb_to_sgvec(*pskb, sg, esph->enc_data+esp->conf.ivlen-(*pskb)->data, clen); skb_to_sgvec(*pskb, sg, esph->enc_data+esp->conf.ivlen-(*pskb)->data, clen);
crypto_cipher_encrypt(tfm, sg, sg, clen); crypto_cipher_encrypt(tfm, sg, sg, clen);
if (unlikely(sg != sgbuf)) if (unlikely(sg != &esp->sgbuf[0]))
kfree(sg); kfree(sg);
} while (0); } while (0);
...@@ -259,12 +256,11 @@ int esp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_b ...@@ -259,12 +256,11 @@ int esp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_b
{ {
u8 nexthdr[2]; u8 nexthdr[2];
struct scatterlist sgbuf[nfrags>MAX_SG_ONSTACK ? 0 : nfrags]; struct scatterlist *sg = &esp->sgbuf[0];
struct scatterlist *sg = sgbuf;
u8 padlen; u8 padlen;
u8 *prevhdr; u8 *prevhdr;
if (unlikely(nfrags > MAX_SG_ONSTACK)) { if (unlikely(nfrags > ESP_NUM_FAST_SG)) {
sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC); sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC);
if (!sg) { if (!sg) {
ret = -ENOMEM; ret = -ENOMEM;
...@@ -273,7 +269,7 @@ int esp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_b ...@@ -273,7 +269,7 @@ int esp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_b
} }
skb_to_sgvec(skb, sg, sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen, elen); skb_to_sgvec(skb, sg, sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen, elen);
crypto_cipher_decrypt(esp->conf.tfm, sg, sg, elen); crypto_cipher_decrypt(esp->conf.tfm, sg, sg, elen);
if (unlikely(sg != sgbuf)) if (unlikely(sg != &esp->sgbuf[0]))
kfree(sg); kfree(sg);
if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2)) if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment