summaryrefslogtreecommitdiff
path: root/crypto
diff options
context:
space:
mode:
authorJoy Latten <latten@austin.ibm.com>2008-04-04 20:05:02 +0800
committerChris Wright <chrisw@sous-sol.org>2008-04-18 18:53:22 -0700
commitc116e98be7180bdac3aea5c0a428718e14785315 (patch)
tree3db4f6b3ba66eca6cb32088acf2594f9dc3b0ea7 /crypto
parentf1920b5f097b15dace2d84fedb82121cb09c86b4 (diff)
CRYPTO xcbc: Fix crash when ipsec uses xcbc-mac with big data chunk
upstream commit: 1edcf2e1ee2babb011cfca80ad9d202e9c491669 The kernel crashes when ipsec passes a udp packet of about 14XX bytes of data to aes-xcbc-mac. It seems the first xxxx bytes of the data are in first sg entry, and remaining xx bytes are in next sg entry. But we don't check next sg entry to see if we need to go look the page up. I noticed in hmac.c, we do a scatterwalk_sg_next(), to do this check and possible lookup, thus xcbc.c needs to use this routine too. A 15-hour run of an ipsec stress test sending streams of tcp and udp packets of various sizes, using this patch and aes-xcbc-mac completed successfully, so hopefully this fixes the problem. Signed-off-by: Joy Latten <latten@austin.ibm.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> [chrisw@sous-sol.org: backport to 2.6.24.4] Signed-off-by: Chris Wright <chrisw@sous-sol.org>
Diffstat (limited to 'crypto')
-rw-r--r--crypto/xcbc.c17
1 files changed, 9 insertions, 8 deletions
diff --git a/crypto/xcbc.c b/crypto/xcbc.c
index a957373832b3..25a153743f50 100644
--- a/crypto/xcbc.c
+++ b/crypto/xcbc.c
@@ -116,13 +116,11 @@ static int crypto_xcbc_digest_update2(struct hash_desc *pdesc,
struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(parent);
struct crypto_cipher *tfm = ctx->child;
int bs = crypto_hash_blocksize(parent);
- unsigned int i = 0;
- do {
-
- struct page *pg = sg_page(&sg[i]);
- unsigned int offset = sg[i].offset;
- unsigned int slen = sg[i].length;
+ for (;;) {
+ struct page *pg = sg_page(sg);
+ unsigned int offset = sg->offset;
+ unsigned int slen = sg->length;
if (unlikely(slen > nbytes))
slen = nbytes;
@@ -182,8 +180,11 @@ static int crypto_xcbc_digest_update2(struct hash_desc *pdesc,
offset = 0;
pg++;
}
- i++;
- } while (nbytes>0);
+
+ if (!nbytes)
+ break;
+ sg = sg_next(sg);
+ }
return 0;
}