All of lore.kernel.org
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	stable@vger.kernel.org, Liu Chao <liuchao741@huawei.com>,
	Eric Biggers <ebiggers@google.com>,
	Herbert Xu <herbert@gondor.apana.org.au>
Subject: [PATCH 3.18 14/15] crypto: ablkcipher - fix crash flushing dcache in error path
Date: Thu, 16 Aug 2018 20:41:51 +0200	[thread overview]
Message-ID: <20180816171634.099522281@linuxfoundation.org> (raw)
In-Reply-To: <20180816171633.546734046@linuxfoundation.org>

3.18-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Eric Biggers <ebiggers@google.com>

commit 318abdfbe708aaaa652c79fb500e9bd60521f9dc upstream.

Like the skcipher_walk and blkcipher_walk cases:

scatterwalk_done() is only meant to be called after a nonzero number of
bytes have been processed, since scatterwalk_pagedone() will flush the
dcache of the *previous* page.  But in the error case of
ablkcipher_walk_done(), e.g. if the input wasn't an integer number of
blocks, scatterwalk_done() was actually called after advancing 0 bytes.
This caused a crash ("BUG: unable to handle kernel paging request")
during '!PageSlab(page)' on architectures like arm and arm64 that define
ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE, provided that the input was
page-aligned as in that case walk->offset == 0.

Fix it by reorganizing ablkcipher_walk_done() to skip the
scatterwalk_advance() and scatterwalk_done() if an error has occurred.

Reported-by: Liu Chao <liuchao741@huawei.com>
Fixes: bf06099db18a ("crypto: skcipher - Add ablkcipher_walk interfaces")
Cc: <stable@vger.kernel.org> # v2.6.35+
Signed-off-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

---
 crypto/ablkcipher.c |   57 +++++++++++++++++++++++-----------------------------
 1 file changed, 26 insertions(+), 31 deletions(-)

--- a/crypto/ablkcipher.c
+++ b/crypto/ablkcipher.c
@@ -72,11 +72,9 @@ static inline u8 *ablkcipher_get_spot(u8
 	return max(start, end_page);
 }
 
-static inline unsigned int ablkcipher_done_slow(struct ablkcipher_walk *walk,
-						unsigned int bsize)
+static inline void ablkcipher_done_slow(struct ablkcipher_walk *walk,
+					unsigned int n)
 {
-	unsigned int n = bsize;
-
 	for (;;) {
 		unsigned int len_this_page = scatterwalk_pagelen(&walk->out);
 
@@ -88,17 +86,13 @@ static inline unsigned int ablkcipher_do
 		n -= len_this_page;
 		scatterwalk_start(&walk->out, scatterwalk_sg_next(walk->out.sg));
 	}
-
-	return bsize;
 }
 
-static inline unsigned int ablkcipher_done_fast(struct ablkcipher_walk *walk,
-						unsigned int n)
+static inline void ablkcipher_done_fast(struct ablkcipher_walk *walk,
+					unsigned int n)
 {
 	scatterwalk_advance(&walk->in, n);
 	scatterwalk_advance(&walk->out, n);
-
-	return n;
 }
 
 static int ablkcipher_walk_next(struct ablkcipher_request *req,
@@ -108,39 +102,40 @@ int ablkcipher_walk_done(struct ablkciph
 			 struct ablkcipher_walk *walk, int err)
 {
 	struct crypto_tfm *tfm = req->base.tfm;
-	unsigned int nbytes = 0;
+	unsigned int n; /* bytes processed */
+	bool more;
 
-	if (likely(err >= 0)) {
-		unsigned int n = walk->nbytes - err;
+	if (unlikely(err < 0))
+		goto finish;
 
-		if (likely(!(walk->flags & ABLKCIPHER_WALK_SLOW)))
-			n = ablkcipher_done_fast(walk, n);
-		else if (WARN_ON(err)) {
+	n = walk->nbytes - err;
+	walk->total -= n;
+	more = (walk->total != 0);
+
+	if (likely(!(walk->flags & ABLKCIPHER_WALK_SLOW))) {
+		ablkcipher_done_fast(walk, n);
+	} else {
+		if (WARN_ON(err)) {
+			/* unexpected case; didn't process all bytes */
 			err = -EINVAL;
-			goto err;
-		} else
-			n = ablkcipher_done_slow(walk, n);
-
-		nbytes = walk->total - n;
-		err = 0;
+			goto finish;
+		}
+		ablkcipher_done_slow(walk, n);
 	}
 
-	scatterwalk_done(&walk->in, 0, nbytes);
-	scatterwalk_done(&walk->out, 1, nbytes);
+	scatterwalk_done(&walk->in, 0, more);
+	scatterwalk_done(&walk->out, 1, more);
 
-err:
-	walk->total = nbytes;
-	walk->nbytes = nbytes;
-
-	if (nbytes) {
+	if (more) {
 		crypto_yield(req->base.flags);
 		return ablkcipher_walk_next(req, walk);
 	}
-
+	err = 0;
+finish:
+	walk->nbytes = 0;
 	if (walk->iv != req->info)
 		memcpy(req->info, walk->iv, tfm->crt_ablkcipher.ivsize);
 	kfree(walk->iv_buffer);
-
 	return err;
 }
 EXPORT_SYMBOL_GPL(ablkcipher_walk_done);



  parent reply	other threads:[~2018-08-16 18:42 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-08-16 18:41 [PATCH 3.18 00/15] 3.18.119-stable review Greg Kroah-Hartman
2018-08-16 18:41 ` [PATCH 3.18 01/15] xen/netfront: dont cache skb_shinfo() Greg Kroah-Hartman
2018-08-16 18:41 ` [PATCH 3.18 02/15] root dentries need RCU-delayed freeing Greg Kroah-Hartman
2018-08-16 18:41 ` [PATCH 3.18 03/15] fix mntput/mntput race Greg Kroah-Hartman
2018-08-16 18:41 ` [PATCH 3.18 04/15] fix __legitimize_mnt()/mntput() race Greg Kroah-Hartman
2018-08-16 18:41 ` [PATCH 3.18 05/15] ARM: dts: imx6sx: fix irq for pcie bridge Greg Kroah-Hartman
2018-08-16 18:41 ` [PATCH 3.18 06/15] kprobes/x86: Fix %p uses in error messages Greg Kroah-Hartman
2018-08-16 18:41   ` Greg Kroah-Hartman
2018-08-16 18:41 ` [PATCH 3.18 07/15] ALSA: info: Check for integer overflow in snd_info_entry_write() Greg Kroah-Hartman
2018-08-16 18:41 ` [PATCH 3.18 08/15] mm: slub: fix format mismatches in slab_err() callers Greg Kroah-Hartman
2018-08-16 18:41 ` [PATCH 3.18 09/15] i2c: ismt: fix wrong device address when unmap the data buffer Greg Kroah-Hartman
2018-08-16 18:41 ` [PATCH 3.18 10/15] kbuild: verify that $DEPMOD is installed Greg Kroah-Hartman
2018-08-16 18:41 ` [PATCH 3.18 11/15] crypto: vmac - require a block cipher with 128-bit block size Greg Kroah-Hartman
2018-08-16 18:41 ` [PATCH 3.18 12/15] crypto: vmac - separate tfm and request context Greg Kroah-Hartman
2018-08-16 18:41 ` [PATCH 3.18 13/15] crypto: blkcipher - fix crash flushing dcache in error path Greg Kroah-Hartman
2018-08-16 18:41 ` Greg Kroah-Hartman [this message]
2018-08-16 18:41 ` [PATCH 3.18 15/15] Bluetooth: hidp: buffer overflow in hidp_process_report Greg Kroah-Hartman
2018-08-16 19:44 ` [PATCH 3.18 00/15] 3.18.119-stable review Nathan Chancellor
2018-08-17 10:08   ` Greg Kroah-Hartman
2018-08-17 13:59 ` Harsh 'Shandilya
2018-08-17 17:13   ` Greg Kroah-Hartman
2018-08-17 17:16 ` Guenter Roeck

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180816171634.099522281@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=ebiggers@google.com \
    --cc=herbert@gondor.apana.org.au \
    --cc=linux-kernel@vger.kernel.org \
    --cc=liuchao741@huawei.com \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.