[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