diff mbox series

[1/4] crypto: hash - Fix synchronous ahash chaining fallback

Message ID 9a84f666cc312786bb85def7d7f03b771a16d397.1742546178.git.herbert@gondor.apana.org.au
State Accepted
Commit 108ce629cf73a3df32fa04b17aedc97c1431b2ac
Headers show
Series Fix synchronous fallback path for request chaining | expand

Commit Message

Herbert Xu March 21, 2025, 8:43 a.m. UTC
The synchronous ahash fallback code paths are broken because the
ahash_restore_req assumes there is always a state object.  Fix this
by removing the state from ahash_restore_req and localising it to
the asynchronous completion callback.

Also add a missing synchronous finish call in ahash_def_digest_finish.

Fixes: f2ffe5a9183d ("crypto: hash - Add request chaining API")
Fixes: 439963cdc3aa ("crypto: ahash - Add virtual address support")
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
 crypto/ahash.c | 60 +++++++++++++++++++++++---------------------------
 1 file changed, 28 insertions(+), 32 deletions(-)
diff mbox series

Patch

diff --git a/crypto/ahash.c b/crypto/ahash.c
index 9c26175c21a8..f0068c72a9e1 100644
--- a/crypto/ahash.c
+++ b/crypto/ahash.c
@@ -57,8 +57,9 @@  struct ahash_save_req_state {
 
 static void ahash_reqchain_done(void *data, int err);
 static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt);
-static void ahash_restore_req(struct ahash_save_req_state *state);
+static void ahash_restore_req(struct ahash_request *req);
 static void ahash_def_finup_done1(void *data, int err);
+static int ahash_def_finup_finish1(struct ahash_request *req, int err);
 static int ahash_def_finup(struct ahash_request *req);
 
 static int hash_walk_next(struct crypto_hash_walk *walk)
@@ -357,14 +358,15 @@  static int ahash_reqchain_virt(struct ahash_save_req_state *state,
 	return err;
 }
 
-static int ahash_reqchain_finish(struct ahash_save_req_state *state,
+static int ahash_reqchain_finish(struct ahash_request *req0,
+				 struct ahash_save_req_state *state,
 				 int err, u32 mask)
 {
-	struct ahash_request *req0 = state->req0;
 	struct ahash_request *req = state->cur;
 	struct crypto_ahash *tfm;
 	struct ahash_request *n;
 	bool update;
+	u8 *page;
 
 	err = ahash_reqchain_virt(state, err, mask);
 	if (err == -EINPROGRESS || err == -EBUSY)
@@ -418,7 +420,12 @@  static int ahash_reqchain_finish(struct ahash_save_req_state *state,
 		list_add_tail(&req->base.list, &req0->base.list);
 	}
 
-	ahash_restore_req(state);
+	page = state->page;
+	if (page) {
+		memset(page, 0, PAGE_SIZE);
+		free_page((unsigned long)page);
+	}
+	ahash_restore_req(req0);
 
 out:
 	return err;
@@ -437,7 +444,8 @@  static void ahash_reqchain_done(void *data, int err)
 		goto notify;
 	}
 
-	err = ahash_reqchain_finish(state, err, CRYPTO_TFM_REQ_MAY_BACKLOG);
+	err = ahash_reqchain_finish(state->req0, state, err,
+				    CRYPTO_TFM_REQ_MAY_BACKLOG);
 	if (err == -EBUSY)
 		return;
 
@@ -513,13 +521,10 @@  static int ahash_do_req_chain(struct ahash_request *req,
 	if (err == -EBUSY || err == -EINPROGRESS)
 		return -EBUSY;
 
-	return ahash_reqchain_finish(state, err, ~0);
+	return ahash_reqchain_finish(req, state, err, ~0);
 
 out_free_page:
-	if (page) {
-		memset(page, 0, PAGE_SIZE);
-		free_page((unsigned long)page);
-	}
+	free_page((unsigned long)page);
 
 out_set_chain:
 	req->base.err = err;
@@ -578,18 +583,15 @@  static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt)
 	req->base.complete = cplt;
 	req->base.data = state;
 	state->req0 = req;
-	state->page = NULL;
 
 	return 0;
 }
 
-static void ahash_restore_req(struct ahash_save_req_state *state)
+static void ahash_restore_req(struct ahash_request *req)
 {
-	struct ahash_request *req = state->req0;
+	struct ahash_save_req_state *state;
 	struct crypto_ahash *tfm;
 
-	free_page((unsigned long)state->page);
-
 	tfm = crypto_ahash_reqtfm(req);
 	if (!ahash_is_async(tfm))
 		return;
@@ -680,9 +682,8 @@  int crypto_ahash_finup(struct ahash_request *req)
 }
 EXPORT_SYMBOL_GPL(crypto_ahash_finup);
 
-static int ahash_def_digest_finish(struct ahash_save_req_state *state, int err)
+static int ahash_def_digest_finish(struct ahash_request *req, int err)
 {
-	struct ahash_request *req = state->req0;
 	struct crypto_ahash *tfm;
 
 	if (err)
@@ -696,8 +697,10 @@  static int ahash_def_digest_finish(struct ahash_save_req_state *state, int err)
 	if (err == -EINPROGRESS || err == -EBUSY)
 		return err;
 
+	return ahash_def_finup_finish1(req, err);
+
 out:
-	ahash_restore_req(state);
+	ahash_restore_req(req);
 	return err;
 }
 
@@ -714,7 +717,7 @@  static void ahash_def_digest_done(void *data, int err)
 
 	areq->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
 
-	err = ahash_def_digest_finish(state0, err);
+	err = ahash_def_digest_finish(areq, err);
 	if (err == -EINPROGRESS || err == -EBUSY)
 		return;
 
@@ -724,20 +727,17 @@  static void ahash_def_digest_done(void *data, int err)
 
 static int ahash_def_digest(struct ahash_request *req)
 {
-	struct ahash_save_req_state *state;
 	int err;
 
 	err = ahash_save_req(req, ahash_def_digest_done);
 	if (err)
 		return err;
 
-	state = req->base.data;
-
 	err = crypto_ahash_init(req);
 	if (err == -EINPROGRESS || err == -EBUSY)
 		return err;
 
-	return ahash_def_digest_finish(state, err);
+	return ahash_def_digest_finish(req, err);
 }
 
 int crypto_ahash_digest(struct ahash_request *req)
@@ -779,13 +779,12 @@  static void ahash_def_finup_done2(void *data, int err)
 	if (err == -EINPROGRESS)
 		return;
 
-	ahash_restore_req(state);
+	ahash_restore_req(areq);
 	ahash_request_complete(areq, err);
 }
 
-static int ahash_def_finup_finish1(struct ahash_save_req_state *state, int err)
+static int ahash_def_finup_finish1(struct ahash_request *req, int err)
 {
-	struct ahash_request *req = state->req0;
 	struct crypto_ahash *tfm;
 
 	if (err)
@@ -800,7 +799,7 @@  static int ahash_def_finup_finish1(struct ahash_save_req_state *state, int err)
 		return err;
 
 out:
-	ahash_restore_req(state);
+	ahash_restore_req(req);
 	return err;
 }
 
@@ -817,7 +816,7 @@  static void ahash_def_finup_done1(void *data, int err)
 
 	areq->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
 
-	err = ahash_def_finup_finish1(state0, err);
+	err = ahash_def_finup_finish1(areq, err);
 	if (err == -EINPROGRESS || err == -EBUSY)
 		return;
 
@@ -827,20 +826,17 @@  static void ahash_def_finup_done1(void *data, int err)
 
 static int ahash_def_finup(struct ahash_request *req)
 {
-	struct ahash_save_req_state *state;
 	int err;
 
 	err = ahash_save_req(req, ahash_def_finup_done1);
 	if (err)
 		return err;
 
-	state = req->base.data;
-
 	err = crypto_ahash_update(req);
 	if (err == -EINPROGRESS || err == -EBUSY)
 		return err;
 
-	return ahash_def_finup_finish1(state, err);
+	return ahash_def_finup_finish1(req, err);
 }
 
 int crypto_ahash_export(struct ahash_request *req, void *out)