[linux] 11/11: Add fix for CVE-2017-7618 and earlier fixes to crypto/ahash.c that it depends on

debian-kernel at lists.debian.org debian-kernel at lists.debian.org
Wed Apr 26 23:25:03 UTC 2017


This is an automated email from the git hooks/post-receive script.

benh pushed a commit to branch wheezy-security
in repository linux.

commit ac64cdc412a88925e93dec92be9931395d77212d
Author: Ben Hutchings <ben at decadent.org.uk>
Date:   Thu Apr 27 00:21:53 2017 +0100

    Add fix for CVE-2017-7618 and earlier fixes to crypto/ahash.c that it depends on
---
 debian/changelog                                   |   5 +
 ...ash-fix-einprogress-notification-callback.patch | 226 +++++++++++++++++++++
 ...h-fully-restore-ahash-request-before-comp.patch |  35 ++++
 ...-Fix-the-pointer-voodoo-in-unaligned-ahas.patch | 118 +++++++++++
 ...-pull-out-the-functions-to-save-restore-r.patch | 152 ++++++++++++++
 ...h-simplify-the-ahash_finup-implementation.patch | 115 +++++++++++
 debian/patches/series                              |   5 +
 7 files changed, 656 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index e05176a..3eb6bc5 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -191,6 +191,11 @@ linux (3.2.88-1) UNRELEASED; urgency=medium
     (CVE-2017-7472)
   * mm/mempolicy.c: fix error handling in set_mempolicy and mbind
     (CVE-2017-7616)
+  * crypto: ahash - Fully restore ahash request before completing
+  * crypto: hash - Fix the pointer voodoo in unaligned ahash
+  * crypto: hash - Pull out the functions to save/restore request
+  * crypto: hash - Simplify the ahash_finup implementation
+  * crypto: ahash - Fix EINPROGRESS notification callback (CVE-2017-7618)
 
  -- Ben Hutchings <ben at decadent.org.uk>  Mon, 13 Mar 2017 23:12:35 +0000
 
diff --git a/debian/patches/bugfix/all/crypto-ahash-fix-einprogress-notification-callback.patch b/debian/patches/bugfix/all/crypto-ahash-fix-einprogress-notification-callback.patch
new file mode 100644
index 0000000..5d324c7
--- /dev/null
+++ b/debian/patches/bugfix/all/crypto-ahash-fix-einprogress-notification-callback.patch
@@ -0,0 +1,226 @@
+From: Herbert Xu <herbert at gondor.apana.org.au>
+Date: Mon, 10 Apr 2017 17:27:57 +0800
+Subject: crypto: ahash - Fix EINPROGRESS notification callback
+Origin: https://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6.git/commit?id=ef0579b64e93188710d48667cb5e014926af9f1b
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2017-7618
+
+The ahash API modifies the request's callback function in order
+to clean up after itself in some corner cases (unaligned final
+and missing finup).
+
+When the request is complete ahash will restore the original
+callback and everything is fine.  However, when the request gets
+an EBUSY on a full queue, an EINPROGRESS callback is made while
+the request is still ongoing.
+
+In this case the ahash API will incorrectly call its own callback.
+
+This patch fixes the problem by creating a temporary request
+object on the stack which is used to relay EINPROGRESS back to
+the original completion function.
+
+This patch also adds code to preserve the original flags value.
+
+Fixes: ab6bf4e5e5e4 ("crypto: hash - Fix the pointer voodoo in...")
+Cc: <stable at vger.kernel.org>
+Reported-by: Sabrina Dubroca <sd at queasysnail.net>
+Tested-by: Sabrina Dubroca <sd at queasysnail.net>
+Signed-off-by: Herbert Xu <herbert at gondor.apana.org.au>
+---
+ crypto/ahash.c                 | 79 ++++++++++++++++++++++++++----------------
+ include/crypto/internal/hash.h | 10 ++++++
+ 2 files changed, 60 insertions(+), 29 deletions(-)
+
+--- a/crypto/ahash.c
++++ b/crypto/ahash.c
+@@ -30,6 +30,7 @@ struct ahash_request_priv {
+ 	crypto_completion_t complete;
+ 	void *data;
+ 	u8 *result;
++	u32 flags;
+ 	void *ubuf[] CRYPTO_MINALIGN_ATTR;
+ };
+ 
+@@ -232,6 +233,8 @@ static int ahash_save_req(struct ahash_r
+ 	priv->result = req->result;
+ 	priv->complete = req->base.complete;
+ 	priv->data = req->base.data;
++	priv->flags = req->base.flags;
++
+ 	/*
+ 	 * WARNING: We do not backup req->priv here! The req->priv
+ 	 *          is for internal use of the Crypto API and the
+@@ -246,38 +249,44 @@ static int ahash_save_req(struct ahash_r
+ 	return 0;
+ }
+ 
+-static void ahash_restore_req(struct ahash_request *req)
++static void ahash_restore_req(struct ahash_request *req, int err)
+ {
+ 	struct ahash_request_priv *priv = req->priv;
+ 
++	if (!err)
++		memcpy(priv->result, req->result,
++		       crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
++
+ 	/* Restore the original crypto request. */
+ 	req->result = priv->result;
+-	req->base.complete = priv->complete;
+-	req->base.data = priv->data;
++
++	ahash_request_set_callback(req, priv->flags,
++				   priv->complete, priv->data);
+ 	req->priv = NULL;
+ 
+ 	/* Free the req->priv.priv from the ADJUSTED request. */
+ 	kzfree(priv);
+ }
+ 
+-static void ahash_op_unaligned_finish(struct ahash_request *req, int err)
++static void ahash_notify_einprogress(struct ahash_request *req)
+ {
+ 	struct ahash_request_priv *priv = req->priv;
++	struct crypto_async_request oreq;
+ 
+-	if (err == -EINPROGRESS)
+-		return;
+-
+-	if (!err)
+-		memcpy(priv->result, req->result,
+-		       crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
++	oreq.data = priv->data;
+ 
+-	ahash_restore_req(req);
++	priv->complete(&oreq, -EINPROGRESS);
+ }
+ 
+ static void ahash_op_unaligned_done(struct crypto_async_request *req, int err)
+ {
+ 	struct ahash_request *areq = req->data;
+ 
++	if (err == -EINPROGRESS) {
++		ahash_notify_einprogress(areq);
++		return;
++	}
++
+ 	/*
+ 	 * Restore the original request, see ahash_op_unaligned() for what
+ 	 * goes where.
+@@ -288,7 +297,7 @@ static void ahash_op_unaligned_done(stru
+ 	 */
+ 
+ 	/* First copy req->result into req->priv.result */
+-	ahash_op_unaligned_finish(areq, err);
++	ahash_restore_req(areq, err);
+ 
+ 	/* Complete the ORIGINAL request. */
+ 	areq->base.complete(&areq->base, err);
+@@ -304,7 +313,12 @@ static int ahash_op_unaligned(struct aha
+ 		return err;
+ 
+ 	err = op(req);
+-	ahash_op_unaligned_finish(req, err);
++	if (err == -EINPROGRESS ||
++	    (err == -EBUSY && (ahash_request_flags(req) &
++			       CRYPTO_TFM_REQ_MAY_BACKLOG)))
++		return err;
++
++	ahash_restore_req(req, err);
+ 
+ 	return err;
+ }
+@@ -339,25 +353,14 @@ int crypto_ahash_digest(struct ahash_req
+ }
+ EXPORT_SYMBOL_GPL(crypto_ahash_digest);
+ 
+-static void ahash_def_finup_finish2(struct ahash_request *req, int err)
++static void ahash_def_finup_done2(struct crypto_async_request *req, int err)
+ {
+-	struct ahash_request_priv *priv = req->priv;
++	struct ahash_request *areq = req->data;
+ 
+ 	if (err == -EINPROGRESS)
+ 		return;
+ 
+-	if (!err)
+-		memcpy(priv->result, req->result,
+-		       crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
+-
+-	ahash_restore_req(req);
+-}
+-
+-static void ahash_def_finup_done2(struct crypto_async_request *req, int err)
+-{
+-	struct ahash_request *areq = req->data;
+-
+-	ahash_def_finup_finish2(areq, err);
++	ahash_restore_req(areq, err);
+ 
+ 	areq->base.complete(&areq->base, err);
+ }
+@@ -368,11 +371,15 @@ static int ahash_def_finup_finish1(struc
+ 		goto out;
+ 
+ 	req->base.complete = ahash_def_finup_done2;
+-	req->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
++
+ 	err = crypto_ahash_reqtfm(req)->final(req);
++	if (err == -EINPROGRESS ||
++	    (err == -EBUSY && (ahash_request_flags(req) &
++			       CRYPTO_TFM_REQ_MAY_BACKLOG)))
++		return err;
+ 
+ out:
+-	ahash_def_finup_finish2(req, err);
++	ahash_restore_req(req, err);
+ 	return err;
+ }
+ 
+@@ -380,7 +387,16 @@ static void ahash_def_finup_done1(struct
+ {
+ 	struct ahash_request *areq = req->data;
+ 
++	if (err == -EINPROGRESS) {
++		ahash_notify_einprogress(areq);
++		return;
++	}
++
++	areq->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
++
+ 	err = ahash_def_finup_finish1(areq, err);
++	if (areq->priv)
++		return;
+ 
+ 	areq->base.complete(&areq->base, err);
+ }
+@@ -395,6 +411,11 @@ static int ahash_def_finup(struct ahash_
+ 		return err;
+ 
+ 	err = tfm->update(req);
++	if (err == -EINPROGRESS ||
++	    (err == -EBUSY && (ahash_request_flags(req) &
++			       CRYPTO_TFM_REQ_MAY_BACKLOG)))
++		return err;
++
+ 	return ahash_def_finup_finish1(req, err);
+ }
+ 
+--- a/include/crypto/internal/hash.h
++++ b/include/crypto/internal/hash.h
+@@ -149,6 +149,16 @@ static inline struct ahash_instance *aha
+ 	return crypto_alloc_instance2(name, alg, ahash_instance_headroom());
+ }
+ 
++static inline void ahash_request_complete(struct ahash_request *req, int err)
++{
++	req->base.complete(&req->base, err);
++}
++
++static inline u32 ahash_request_flags(struct ahash_request *req)
++{
++	return req->base.flags;
++}
++
+ static inline struct crypto_ahash *crypto_spawn_ahash(
+ 	struct crypto_ahash_spawn *spawn)
+ {
diff --git a/debian/patches/bugfix/all/crypto-ahash-fully-restore-ahash-request-before-comp.patch b/debian/patches/bugfix/all/crypto-ahash-fully-restore-ahash-request-before-comp.patch
new file mode 100644
index 0000000..dbac0bd
--- /dev/null
+++ b/debian/patches/bugfix/all/crypto-ahash-fully-restore-ahash-request-before-comp.patch
@@ -0,0 +1,35 @@
+From: Marek Vasut <marex at denx.de>
+Date: Tue, 10 Dec 2013 20:26:19 +0100
+Subject: crypto: ahash - Fully restore ahash request before completing
+Origin: https://git.kernel.org/linus/1d9a394b97b833d3ab37f49caf12d0be3c88050b
+
+When finishing the ahash request, the ahash_op_unaligned_done() will
+call complete() on the request. Yet, this will not call the correct
+complete callback. The correct complete callback was previously stored
+in the requests' private data, as seen in ahash_op_unaligned(). This
+patch restores the correct complete callback and .data field of the
+request before calling complete() on it.
+
+Signed-off-by: Marek Vasut <marex at denx.de>
+Cc: David S. Miller <davem at davemloft.net>
+Cc: Fabio Estevam <fabio.estevam at freescale.com>
+Cc: Shawn Guo <shawn.guo at linaro.org>
+Signed-off-by: Herbert Xu <herbert at gondor.apana.org.au>
+---
+ crypto/ahash.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/crypto/ahash.c
++++ b/crypto/ahash.c
+@@ -214,7 +214,10 @@ static void ahash_op_unaligned_done(stru
+ 
+ 	ahash_op_unaligned_finish(areq, err);
+ 
+-	complete(data, err);
++	areq->base.complete = complete;
++	areq->base.data = data;
++
++	complete(&areq->base, err);
+ }
+ 
+ static int ahash_op_unaligned(struct ahash_request *req,
diff --git a/debian/patches/bugfix/all/crypto-hash-Fix-the-pointer-voodoo-in-unaligned-ahas.patch b/debian/patches/bugfix/all/crypto-hash-Fix-the-pointer-voodoo-in-unaligned-ahas.patch
new file mode 100644
index 0000000..69bfa93
--- /dev/null
+++ b/debian/patches/bugfix/all/crypto-hash-Fix-the-pointer-voodoo-in-unaligned-ahas.patch
@@ -0,0 +1,118 @@
+From: Marek Vasut <marex at denx.de>
+Date: Fri, 14 Mar 2014 02:37:04 +0100
+Subject: crypto: hash - Fix the pointer voodoo in unaligned ahash
+Origin: https://git.kernel.org/linus/ab6bf4e5e5e4298e8649e635bee25542cccbfd97
+
+Add documentation for the pointer voodoo that is happening in crypto/ahash.c
+in ahash_op_unaligned(). This code is quite confusing, so add a beefy chunk
+of documentation.
+
+Moreover, make sure the mangled request is completely restored after finishing
+this unaligned operation. This means restoring all of .result, .base.data
+and .base.complete .
+
+Also, remove the crypto_completion_t complete = ... line present in the
+ahash_op_unaligned_done() function. This type actually declares a function
+pointer, which is very confusing.
+
+Finally, yet very important nonetheless, make sure the req->priv is free()'d
+only after the original request is restored in ahash_op_unaligned_done().
+The req->priv data must not be free()'d before that in ahash_op_unaligned_finish(),
+since we would be accessing previously free()'d data in ahash_op_unaligned_done()
+and cause corruption.
+
+Signed-off-by: Marek Vasut <marex at denx.de>
+Cc: David S. Miller <davem at davemloft.net>
+Cc: Fabio Estevam <fabio.estevam at freescale.com>
+Cc: Herbert Xu <herbert at gondor.apana.org.au>
+Cc: Shawn Guo <shawn.guo at linaro.org>
+Cc: Tom Lendacky <thomas.lendacky at amd.com>
+Signed-off-by: Herbert Xu <herbert at gondor.apana.org.au>
+---
+ crypto/ahash.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++-------
+ 1 file changed, 49 insertions(+), 7 deletions(-)
+
+--- a/crypto/ahash.c
++++ b/crypto/ahash.c
+@@ -202,22 +202,34 @@ static void ahash_op_unaligned_finish(st
+ 		memcpy(priv->result, req->result,
+ 		       crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
+ 
++	/* Restore the original crypto request. */
++	req->result = priv->result;
++	req->base.complete = priv->complete;
++	req->base.data = priv->data;
++	req->priv = NULL;
++
++	/* Free the req->priv.priv from the ADJUSTED request. */
+ 	kzfree(priv);
+ }
+ 
+ static void ahash_op_unaligned_done(struct crypto_async_request *req, int err)
+ {
+ 	struct ahash_request *areq = req->data;
+-	struct ahash_request_priv *priv = areq->priv;
+-	crypto_completion_t complete = priv->complete;
+-	void *data = priv->data;
+ 
+-	ahash_op_unaligned_finish(areq, err);
++	/*
++	 * Restore the original request, see ahash_op_unaligned() for what
++	 * goes where.
++	 *
++	 * The "struct ahash_request *req" here is in fact the "req.base"
++	 * from the ADJUSTED request from ahash_op_unaligned(), thus as it
++	 * is a pointer to self, it is also the ADJUSTED "req" .
++	 */
+ 
+-	areq->base.complete = complete;
+-	areq->base.data = data;
++	/* First copy areq->result into areq->priv.result */
++	ahash_op_unaligned_finish(areq, err);
+ 
+-	complete(&areq->base, err);
++	/* Complete the ORIGINAL request. */
++	areq->base.complete(&areq->base, err);
+ }
+ 
+ static int ahash_op_unaligned(struct ahash_request *req,
+@@ -235,9 +247,39 @@ static int ahash_op_unaligned(struct aha
+ 	if (!priv)
+ 		return -ENOMEM;
+ 
++	/*
++	 * WARNING: Voodoo programming below!
++	 *
++	 * The code below is obscure and hard to understand, thus explanation
++	 * is necessary. See include/crypto/hash.h and include/linux/crypto.h
++	 * to understand the layout of structures used here!
++	 *
++	 * The code here will replace portions of the ORIGINAL request with
++	 * pointers to new code and buffers so the hashing operation can store
++	 * the result in aligned buffer. We will call the modified request
++	 * an ADJUSTED request.
++	 *
++	 * The newly mangled request will look as such:
++	 *
++	 * req {
++	 *   .result        = ADJUSTED[new aligned buffer]
++	 *   .base.complete = ADJUSTED[pointer to completion function]
++	 *   .base.data     = ADJUSTED[*req (pointer to self)]
++	 *   .priv          = ADJUSTED[new priv] {
++	 *           .result   = ORIGINAL(result)
++	 *           .complete = ORIGINAL(base.complete)
++	 *           .data     = ORIGINAL(base.data)
++	 *   }
++	 */
++
+ 	priv->result = req->result;
+ 	priv->complete = req->base.complete;
+ 	priv->data = req->base.data;
++	/*
++	 * WARNING: We do not backup req->priv here! The req->priv
++	 *          is for internal use of the Crypto API and the
++	 *          user must _NOT_ _EVER_ depend on it's content!
++	 */
+ 
+ 	req->result = PTR_ALIGN((u8 *)priv->ubuf, alignmask + 1);
+ 	req->base.complete = ahash_op_unaligned_done;
diff --git a/debian/patches/bugfix/all/crypto-hash-pull-out-the-functions-to-save-restore-r.patch b/debian/patches/bugfix/all/crypto-hash-pull-out-the-functions-to-save-restore-r.patch
new file mode 100644
index 0000000..81bb8d2
--- /dev/null
+++ b/debian/patches/bugfix/all/crypto-hash-pull-out-the-functions-to-save-restore-r.patch
@@ -0,0 +1,152 @@
+From: Marek Vasut <marex at denx.de>
+Date: Fri, 14 Mar 2014 02:37:05 +0100
+Subject: crypto: hash - Pull out the functions to save/restore request
+Origin: https://git.kernel.org/linus/1ffc9fbd1e5071948b6d48f9a27d845738ee890f
+
+The functions to save original request within a newly adjusted request
+and it's counterpart to restore the original request can be re-used by
+more code in the crypto/ahash.c file. Pull these functions out from the
+code so they're available.
+
+Signed-off-by: Marek Vasut <marex at denx.de>
+Cc: David S. Miller <davem at davemloft.net>
+Cc: Fabio Estevam <fabio.estevam at freescale.com>
+Cc: Herbert Xu <herbert at gondor.apana.org.au>
+Cc: Shawn Guo <shawn.guo at linaro.org>
+Cc: Tom Lendacky <thomas.lendacky at amd.com>
+Signed-off-by: Herbert Xu <herbert at gondor.apana.org.au>
+---
+ crypto/ahash.c | 107 +++++++++++++++++++++++++++++++++------------------------
+ 1 file changed, 62 insertions(+), 45 deletions(-)
+
+--- a/crypto/ahash.c
++++ b/crypto/ahash.c
+@@ -191,55 +191,12 @@ static inline unsigned int ahash_align_b
+ 	return len + (mask & ~(crypto_tfm_ctx_alignment() - 1));
+ }
+ 
+-static void ahash_op_unaligned_finish(struct ahash_request *req, int err)
+-{
+-	struct ahash_request_priv *priv = req->priv;
+-
+-	if (err == -EINPROGRESS)
+-		return;
+-
+-	if (!err)
+-		memcpy(priv->result, req->result,
+-		       crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
+-
+-	/* Restore the original crypto request. */
+-	req->result = priv->result;
+-	req->base.complete = priv->complete;
+-	req->base.data = priv->data;
+-	req->priv = NULL;
+-
+-	/* Free the req->priv.priv from the ADJUSTED request. */
+-	kzfree(priv);
+-}
+-
+-static void ahash_op_unaligned_done(struct crypto_async_request *req, int err)
+-{
+-	struct ahash_request *areq = req->data;
+-
+-	/*
+-	 * Restore the original request, see ahash_op_unaligned() for what
+-	 * goes where.
+-	 *
+-	 * The "struct ahash_request *req" here is in fact the "req.base"
+-	 * from the ADJUSTED request from ahash_op_unaligned(), thus as it
+-	 * is a pointer to self, it is also the ADJUSTED "req" .
+-	 */
+-
+-	/* First copy areq->result into areq->priv.result */
+-	ahash_op_unaligned_finish(areq, err);
+-
+-	/* Complete the ORIGINAL request. */
+-	areq->base.complete(&areq->base, err);
+-}
+-
+-static int ahash_op_unaligned(struct ahash_request *req,
+-			      int (*op)(struct ahash_request *))
++static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt)
+ {
+ 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ 	unsigned long alignmask = crypto_ahash_alignmask(tfm);
+ 	unsigned int ds = crypto_ahash_digestsize(tfm);
+ 	struct ahash_request_priv *priv;
+-	int err;
+ 
+ 	priv = kmalloc(sizeof(*priv) + ahash_align_buffer_size(ds, alignmask),
+ 		       (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
+@@ -282,10 +239,70 @@ static int ahash_op_unaligned(struct aha
+ 	 */
+ 
+ 	req->result = PTR_ALIGN((u8 *)priv->ubuf, alignmask + 1);
+-	req->base.complete = ahash_op_unaligned_done;
++	req->base.complete = cplt;
+ 	req->base.data = req;
+ 	req->priv = priv;
+ 
++	return 0;
++}
++
++static void ahash_restore_req(struct ahash_request *req)
++{
++	struct ahash_request_priv *priv = req->priv;
++
++	/* Restore the original crypto request. */
++	req->result = priv->result;
++	req->base.complete = priv->complete;
++	req->base.data = priv->data;
++	req->priv = NULL;
++
++	/* Free the req->priv.priv from the ADJUSTED request. */
++	kzfree(priv);
++}
++
++static void ahash_op_unaligned_finish(struct ahash_request *req, int err)
++{
++	struct ahash_request_priv *priv = req->priv;
++
++	if (err == -EINPROGRESS)
++		return;
++
++	if (!err)
++		memcpy(priv->result, req->result,
++		       crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
++
++	ahash_restore_req(req);
++}
++
++static void ahash_op_unaligned_done(struct crypto_async_request *req, int err)
++{
++	struct ahash_request *areq = req->data;
++
++	/*
++	 * Restore the original request, see ahash_op_unaligned() for what
++	 * goes where.
++	 *
++	 * The "struct ahash_request *req" here is in fact the "req.base"
++	 * from the ADJUSTED request from ahash_op_unaligned(), thus as it
++	 * is a pointer to self, it is also the ADJUSTED "req" .
++	 */
++
++	/* First copy req->result into req->priv.result */
++	ahash_op_unaligned_finish(areq, err);
++
++	/* Complete the ORIGINAL request. */
++	areq->base.complete(&areq->base, err);
++}
++
++static int ahash_op_unaligned(struct ahash_request *req,
++			      int (*op)(struct ahash_request *))
++{
++	int err;
++
++	err = ahash_save_req(req, ahash_op_unaligned_done);
++	if (err)
++		return err;
++
+ 	err = op(req);
+ 	ahash_op_unaligned_finish(req, err);
+ 
diff --git a/debian/patches/bugfix/all/crypto-hash-simplify-the-ahash_finup-implementation.patch b/debian/patches/bugfix/all/crypto-hash-simplify-the-ahash_finup-implementation.patch
new file mode 100644
index 0000000..fd65c03
--- /dev/null
+++ b/debian/patches/bugfix/all/crypto-hash-simplify-the-ahash_finup-implementation.patch
@@ -0,0 +1,115 @@
+From: Marek Vasut <marex at denx.de>
+Date: Fri, 14 Mar 2014 02:37:06 +0100
+Subject: crypto: hash - Simplify the ahash_finup implementation
+Origin: https://git.kernel.org/linus/d4a7a0fbe959e12bdd071b79b50ed34853a6db8f
+
+The ahash_def_finup() can make use of the request save/restore functions,
+thus make it so. This simplifies the code a little and unifies the code
+paths.
+
+Note that the same remark about free()ing the req->priv applies here, the
+req->priv can only be free()'d after the original request was restored.
+
+Finally, squash a bug in the invocation of completion in the ASYNC path.
+In both ahash_def_finup_done{1,2}, the function areq->base.complete(X, err);
+was called with X=areq->base.data . This is incorrect , as X=&areq->base
+is the correct value. By analysis of the data structures, we see the areq is
+of type 'struct ahash_request' , areq->base is of type 'struct crypto_async_request'
+and areq->base.completion is of type crypto_completion_t, which is defined in
+include/linux/crypto.h as:
+
+  typedef void (*crypto_completion_t)(struct crypto_async_request *req, int err);
+
+This is one lead that the X should be &areq->base . Next up, we can inspect
+other code which calls the completion callback to give us kind-of statistical
+idea of how this callback is used. We can try:
+
+  $ git grep base\.complete\( drivers/crypto/
+
+Finally, by inspecting ahash_request_set_callback() implementation defined
+in include/crypto/hash.h , we observe that the .data entry of 'struct
+crypto_async_request' is intended for arbitrary data, not for completion
+argument.
+
+Signed-off-by: Marek Vasut <marex at denx.de>
+Cc: David S. Miller <davem at davemloft.net>
+Cc: Fabio Estevam <fabio.estevam at freescale.com>
+Cc: Herbert Xu <herbert at gondor.apana.org.au>
+Cc: Shawn Guo <shawn.guo at linaro.org>
+Cc: Tom Lendacky <thomas.lendacky at amd.com>
+Signed-off-by: Herbert Xu <herbert at gondor.apana.org.au>
+---
+ crypto/ahash.c | 36 +++++++++---------------------------
+ 1 file changed, 9 insertions(+), 27 deletions(-)
+
+--- a/crypto/ahash.c
++++ b/crypto/ahash.c
+@@ -350,19 +350,16 @@ static void ahash_def_finup_finish2(stru
+ 		memcpy(priv->result, req->result,
+ 		       crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
+ 
+-	kzfree(priv);
++	ahash_restore_req(req);
+ }
+ 
+ static void ahash_def_finup_done2(struct crypto_async_request *req, int err)
+ {
+ 	struct ahash_request *areq = req->data;
+-	struct ahash_request_priv *priv = areq->priv;
+-	crypto_completion_t complete = priv->complete;
+-	void *data = priv->data;
+ 
+ 	ahash_def_finup_finish2(areq, err);
+ 
+-	complete(data, err);
++	areq->base.complete(&areq->base, err);
+ }
+ 
+ static int ahash_def_finup_finish1(struct ahash_request *req, int err)
+@@ -382,38 +379,23 @@ out:
+ static void ahash_def_finup_done1(struct crypto_async_request *req, int err)
+ {
+ 	struct ahash_request *areq = req->data;
+-	struct ahash_request_priv *priv = areq->priv;
+-	crypto_completion_t complete = priv->complete;
+-	void *data = priv->data;
+ 
+ 	err = ahash_def_finup_finish1(areq, err);
+ 
+-	complete(data, err);
++	areq->base.complete(&areq->base, err);
+ }
+ 
+ static int ahash_def_finup(struct ahash_request *req)
+ {
+ 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+-	unsigned long alignmask = crypto_ahash_alignmask(tfm);
+-	unsigned int ds = crypto_ahash_digestsize(tfm);
+-	struct ahash_request_priv *priv;
+-
+-	priv = kmalloc(sizeof(*priv) + ahash_align_buffer_size(ds, alignmask),
+-		       (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
+-		       GFP_KERNEL : GFP_ATOMIC);
+-	if (!priv)
+-		return -ENOMEM;
+-
+-	priv->result = req->result;
+-	priv->complete = req->base.complete;
+-	priv->data = req->base.data;
+-
+-	req->result = PTR_ALIGN((u8 *)priv->ubuf, alignmask + 1);
+-	req->base.complete = ahash_def_finup_done1;
+-	req->base.data = req;
+-	req->priv = priv;
++	int err;
+ 
+-	return ahash_def_finup_finish1(req, tfm->update(req));
++	err = ahash_save_req(req, ahash_def_finup_done1);
++	if (err)
++		return err;
++
++	err = tfm->update(req);
++	return ahash_def_finup_finish1(req, err);
+ }
+ 
+ static int ahash_no_export(struct ahash_request *req, void *out)
diff --git a/debian/patches/series b/debian/patches/series
index e4e860d..35a3f03 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1122,6 +1122,11 @@ bugfix/all/net-packet-fix-overflow-in-check-for-tp_frame_nr.patch
 bugfix/all/net-packet-fix-overflow-in-check-for-tp_reserve.patch
 bugfix/all/keys-fix-keyctl_set_reqkey_keyring-to-not-leak-threa.patch
 bugfix/all/mm-mempolicy.c-fix-error-handling-in-set_mempolicy-a.patch
+bugfix/all/crypto-ahash-fully-restore-ahash-request-before-comp.patch
+bugfix/all/crypto-hash-Fix-the-pointer-voodoo-in-unaligned-ahas.patch
+bugfix/all/crypto-hash-pull-out-the-functions-to-save-restore-r.patch
+bugfix/all/crypto-hash-simplify-the-ahash_finup-implementation.patch
+bugfix/all/crypto-ahash-fix-einprogress-notification-callback.patch
 
 # ABI maintenance
 debian/perf-hide-abi-change-in-3.2.30.patch

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/kernel/linux.git



More information about the Kernel-svn-changes mailing list