diff mbox

crypto: ahash - Fix early termination in hash walk

Message ID 20180325154958.16439-1-elicooper@gmx.com (mailing list archive)
State Superseded
Delegated to: Herbert Xu
Headers show

Commit Message

Eli Cooper March 25, 2018, 3:49 p.m. UTC
When supplied with an offset equal to PAGE_SIZE, the hash walk code returns
zero, resulting in early termination and, in the observed scenario, memory
corruption.  This patch fixes it by clamping nbytes only when walk->offset
is not at the PAGE_SIZE boundary.

Cc: stable@vger.kernel.org
Signed-off-by: Eli Cooper <elicooper@gmx.com>
---
 crypto/ahash.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)
diff mbox

Patch

diff --git a/crypto/ahash.c b/crypto/ahash.c
index 3a35d67de7d9..03cbe04c53b1 100644
--- a/crypto/ahash.c
+++ b/crypto/ahash.c
@@ -46,8 +46,11 @@  static int hash_walk_next(struct crypto_hash_walk *walk)
 {
 	unsigned int alignmask = walk->alignmask;
 	unsigned int offset = walk->offset;
-	unsigned int nbytes = min(walk->entrylen,
-				  ((unsigned int)(PAGE_SIZE)) - offset);
+	unsigned int pagelen, nbytes = walk->entrylen;
+
+	pagelen = ((unsigned int)(PAGE_SIZE)) - offset;
+	if (pagelen)
+		nbytes = min(nbytes, pagelen);
 
 	if (walk->flags & CRYPTO_ALG_ASYNC)
 		walk->data = kmap(walk->pg);
@@ -86,7 +89,7 @@  static int hash_walk_new_entry(struct crypto_hash_walk *walk)
 int crypto_hash_walk_done(struct crypto_hash_walk *walk, int err)
 {
 	unsigned int alignmask = walk->alignmask;
-	unsigned int nbytes = walk->entrylen;
+	unsigned int pagelen, nbytes = walk->entrylen;
 
 	walk->data -= walk->offset;
 
@@ -94,8 +97,9 @@  int crypto_hash_walk_done(struct crypto_hash_walk *walk, int err)
 		walk->offset = ALIGN(walk->offset, alignmask + 1);
 		walk->data += walk->offset;
 
-		nbytes = min(nbytes,
-			     ((unsigned int)(PAGE_SIZE)) - walk->offset);
+		pagelen = ((unsigned int)(PAGE_SIZE)) - walk->offset;
+		if (pagelen)
+			nbytes = min(nbytes, pagelen);
 		walk->entrylen -= nbytes;
 
 		return nbytes;