Re: HIFN+IPsec crashes in current -git

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Patrick.

On Thu, Feb 21, 2008 at 04:29:54PM +0100, Patrick McHardy (kaber@xxxxxxxxx) wrote:
> Unfortunately still no luck. I got an error from ablkcipher_add()
> because of this condition:

...

> - further down it uses dst->length in the last while-loop,
>   which seems to need a similar change.

Does this patch  (on top of unpatched tree) helps?
I can not test it with real hardware, since I'm sicking at home with
laptop only, but I already know how to make a test case for this problem
without complex setup, so if it does not work, I will investigate it
further as soon as be able to move to office with testing machine :)

diff --git a/drivers/crypto/hifn_795x.c b/drivers/crypto/hifn_795x.c
index dfbf24c..7807ca9 100644
--- a/drivers/crypto/hifn_795x.c
+++ b/drivers/crypto/hifn_795x.c
@@ -1464,7 +1464,7 @@ static int ablkcipher_walk(struct ablkcipher_request *req,
 		crypto_ablkcipher_alignmask(crypto_ablkcipher_reqtfm(req));
 	struct scatterlist *src, *dst, *t;
 	void *daddr;
-	unsigned int nbytes = req->nbytes, offset, copy, diff;
+	unsigned int nbytes = req->nbytes, offset, copy, diff, nb;
 	int idx, tidx, err;
 
 	tidx = idx = 0;
@@ -1475,11 +1475,13 @@ static int ablkcipher_walk(struct ablkcipher_request *req,
 
 		src = &req->src[idx];
 		dst = &req->dst[idx];
+		
+		nb = min(nbytes, src->length);
 
 		dprintk("\n%s: slen: %u, dlen: %u, soff: %u, doff: %u, offset: %u, "
-				"blocksize: %u, nbytes: %u.\n",
+				"blocksize: %u, nbytes: %u, nb: %u.\n",
 				__func__, src->length, dst->length, src->offset,
-				dst->offset, offset, blocksize, nbytes);
+				dst->offset, offset, blocksize, nbytes, nb);
 
 		if (src->length & (blocksize - 1) ||
 				src->offset & (alignmask - 1) ||
@@ -1492,7 +1494,7 @@ static int ablkcipher_walk(struct ablkcipher_request *req,
 			t = &w->cache[idx];
 
 			daddr = kmap_atomic(sg_page(t), KM_SOFTIRQ0);
-			err = ablkcipher_add(daddr, &dlen, src, slen, &nbytes);
+			err = ablkcipher_add(daddr, &dlen, src, nb, &nbytes);
 			if (err < 0)
 				goto err_out_unmap;
 
@@ -1501,7 +1503,7 @@ static int ablkcipher_walk(struct ablkcipher_request *req,
 			copy = slen & ~(blocksize - 1);
 			diff = slen & (blocksize - 1);
 
-			if (dlen < nbytes) {
+			if (dlen < nb) {
 				/*
 				 * Destination page does not have enough space
 				 * to put there additional blocksized chunk,
@@ -1510,17 +1512,17 @@ static int ablkcipher_walk(struct ablkcipher_request *req,
 				 * 	t->length = (slen & ~(blocksize - 1));
 				 * and increase number of bytes to be processed
 				 * in next chunk:
-				 * 	nbytes += diff;
+				 * 	nb += diff;
 				 */
-				nbytes += diff;
+				nb += diff;
 
 				/*
 				 * Temporary of course...
 				 * Kick author if you will catch this one.
 				 */
 				printk(KERN_ERR "%s: dlen: %u, nbytes: %u,"
-					"slen: %u, offset: %u.\n",
-					__func__, dlen, nbytes, slen, offset);
+					"slen: %u, offset: %u, nb: %u.\n",
+					__func__, dlen, nbytes, slen, offset, nb);
 				printk(KERN_ERR "%s: please contact author to fix this "
 					"issue, generally you should not catch "
 					"this path under any condition but who "
@@ -1528,11 +1530,11 @@ static int ablkcipher_walk(struct ablkcipher_request *req,
 					"Thank you.\n",	__func__);
 				BUG();
 			} else {
-				copy += diff + nbytes;
+				copy += diff + nb;
 
 				src = &req->src[idx];
 
-				err = ablkcipher_add(daddr + slen, &dlen, src, nbytes, &nbytes);
+				err = ablkcipher_add(daddr + slen, &dlen, src, nb, &nbytes);
 				if (err < 0)
 					goto err_out_unmap;
 
@@ -1544,7 +1546,7 @@ static int ablkcipher_walk(struct ablkcipher_request *req,
 
 			kunmap_atomic(daddr, KM_SOFTIRQ0);
 		} else {
-			nbytes -= src->length;
+			nbytes -= nb;
 			idx++;
 		}
 
@@ -1564,7 +1566,7 @@ static int hifn_setup_session(struct ablkcipher_request *req)
 	struct hifn_device *dev = ctx->dev;
 	struct page *spage, *dpage;
 	unsigned long soff, doff, flags;
-	unsigned int nbytes = req->nbytes, idx = 0, len;
+	unsigned int nbytes = req->nbytes, idx = 0, len, nb;
 	int err = -EINVAL, sg_num;
 	struct scatterlist *src, *dst, *t;
 	unsigned blocksize =
@@ -1581,6 +1583,8 @@ static int hifn_setup_session(struct ablkcipher_request *req)
 		src = &req->src[idx];
 		dst = &req->dst[idx];
 
+		nb = min(src->length, nbytes);
+
 		if (src->length & (blocksize - 1) ||
 				src->offset & (alignmask - 1) ||
 				dst->length & (blocksize - 1) ||
@@ -1588,7 +1592,7 @@ static int hifn_setup_session(struct ablkcipher_request *req)
 			ctx->walk.flags |= ASYNC_FLAGS_MISALIGNED;
 		}
 
-		nbytes -= src->length;
+		nbytes -= nb;
 		idx++;
 	}
 
@@ -1602,6 +1606,10 @@ static int hifn_setup_session(struct ablkcipher_request *req)
 	idx = 0;
 
 	sg_num = ablkcipher_walk(req, &ctx->walk);
+	if (sg_num < 0) {
+		err = sg_num;
+		goto err_out_exit;
+	}
 
 	atomic_set(&ctx->sg_num, sg_num);
 
@@ -1632,10 +1640,12 @@ static int hifn_setup_session(struct ablkcipher_request *req)
 
 			len = dst->length;
 		}
+		
+		nb = min(len, nbytes);
 
 		idx++;
 
-		err = hifn_setup_dma(dev, spage, soff, dpage, doff, nbytes,
+		err = hifn_setup_dma(dev, spage, soff, dpage, doff, nb,
 				req, ctx);
 		if (err)
 			goto err_out;
@@ -1652,7 +1662,7 @@ err_out:
 	spin_unlock_irqrestore(&dev->lock, flags);
 err_out_exit:
 	if (err && printk_ratelimit())
-		dprintk("%s: iv: %p [%d], key: %p [%d], mode: %u, op: %u, "
+		printk("%s: iv: %p [%d], key: %p [%d], mode: %u, op: %u, "
 				"type: %u, err: %d.\n",
 			dev->name, ctx->iv, ctx->ivsize,
 			ctx->key, ctx->keysize,
@@ -1786,7 +1796,7 @@ static void hifn_process_ready(struct ablkcipher_request *req, int error)
 		BUG();
 
 	if (atomic_dec_and_test(&ctx->sg_num)) {
-		unsigned int nbytes = req->nbytes;
+		unsigned int nbytes = req->nbytes, nb;
 		int idx = 0, err;
 		struct scatterlist *dst, *t;
 		void *saddr;
@@ -1796,6 +1806,8 @@ static void hifn_process_ready(struct ablkcipher_request *req, int error)
 				t = &ctx->walk.cache[idx];
 				dst = &req->dst[idx];
 
+				nb = min(nbytes, dst->length);
+
 				dprintk("\n%s: sg_page(t): %p, t->length: %u, "
 					"sg_page(dst): %p, dst->length: %u, "
 					"nbytes: %u.\n",
@@ -1803,7 +1815,7 @@ static void hifn_process_ready(struct ablkcipher_request *req, int error)
 					sg_page(dst), dst->length, nbytes);
 
 				if (!t->length) {
-					nbytes -= dst->length;
+					nbytes -= nb;
 					idx++;
 					continue;
 				}
@@ -1811,7 +1823,7 @@ static void hifn_process_ready(struct ablkcipher_request *req, int error)
 				saddr = kmap_atomic(sg_page(t), KM_IRQ1);
 
 				err = ablkcipher_get(saddr, &t->length, t->offset,
-						dst, nbytes, &nbytes);
+						dst, nb, &nbytes);
 				if (err < 0) {
 					kunmap_atomic(saddr, KM_IRQ1);
 					break;


-- 
	Evgeniy Polyakov
-
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Kernel]     [Gnu Classpath]     [Gnu Crypto]     [DM Crypt]     [Netfilter]     [Bugtraq]

  Powered by Linux