diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2025-03-21 16:43:28 +0800 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2025-03-22 07:25:19 +0800 |
commit | 108ce629cf73a3df32fa04b17aedc97c1431b2ac (patch) | |
tree | 38c9b37bc5bffccf38c778fbf6bcf5419bbcff8b /crypto | |
parent | 3846c01d42526bc31f511b75ed5282cae22c5064 (diff) |
crypto: hash - Fix synchronous ahash chaining fallback
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>
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/ahash.c | 60 |
1 files changed, 28 insertions, 32 deletions
diff --git a/crypto/ahash.c b/crypto/ahash.c index 06559e5a715b..9f57b925b116 100644 --- a/crypto/ahash.c +++ b/crypto/ahash.c @@ -58,8 +58,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) @@ -369,14 +370,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) @@ -430,7 +432,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; @@ -449,7 +456,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; @@ -525,13 +533,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; @@ -590,18 +595,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; @@ -692,9 +694,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) @@ -708,8 +709,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; } @@ -726,7 +729,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; @@ -736,20 +739,17 @@ out: 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) @@ -791,13 +791,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) @@ -812,7 +811,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; } @@ -829,7 +828,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; @@ -839,20 +838,17 @@ out: 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) |