mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-04-13 09:59:31 +00:00
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:f2ffe5a918
("crypto: hash - Add request chaining API") Fixes:439963cdc3
("crypto: ahash - Add virtual address support") Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
parent
3846c01d42
commit
108ce629cf
1 changed files with 28 additions and 32 deletions
|
@ -58,8 +58,9 @@ struct ahash_save_req_state {
|
||||||
|
|
||||||
static void ahash_reqchain_done(void *data, int err);
|
static void ahash_reqchain_done(void *data, int err);
|
||||||
static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt);
|
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 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 ahash_def_finup(struct ahash_request *req);
|
||||||
|
|
||||||
static int hash_walk_next(struct crypto_hash_walk *walk)
|
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;
|
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)
|
int err, u32 mask)
|
||||||
{
|
{
|
||||||
struct ahash_request *req0 = state->req0;
|
|
||||||
struct ahash_request *req = state->cur;
|
struct ahash_request *req = state->cur;
|
||||||
struct crypto_ahash *tfm;
|
struct crypto_ahash *tfm;
|
||||||
struct ahash_request *n;
|
struct ahash_request *n;
|
||||||
bool update;
|
bool update;
|
||||||
|
u8 *page;
|
||||||
|
|
||||||
err = ahash_reqchain_virt(state, err, mask);
|
err = ahash_reqchain_virt(state, err, mask);
|
||||||
if (err == -EINPROGRESS || err == -EBUSY)
|
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);
|
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:
|
out:
|
||||||
return err;
|
return err;
|
||||||
|
@ -449,7 +456,8 @@ static void ahash_reqchain_done(void *data, int err)
|
||||||
goto notify;
|
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)
|
if (err == -EBUSY)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -525,13 +533,10 @@ static int ahash_do_req_chain(struct ahash_request *req,
|
||||||
if (err == -EBUSY || err == -EINPROGRESS)
|
if (err == -EBUSY || err == -EINPROGRESS)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
return ahash_reqchain_finish(state, err, ~0);
|
return ahash_reqchain_finish(req, state, err, ~0);
|
||||||
|
|
||||||
out_free_page:
|
out_free_page:
|
||||||
if (page) {
|
free_page((unsigned long)page);
|
||||||
memset(page, 0, PAGE_SIZE);
|
|
||||||
free_page((unsigned long)page);
|
|
||||||
}
|
|
||||||
|
|
||||||
out_set_chain:
|
out_set_chain:
|
||||||
req->base.err = err;
|
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.complete = cplt;
|
||||||
req->base.data = state;
|
req->base.data = state;
|
||||||
state->req0 = req;
|
state->req0 = req;
|
||||||
state->page = NULL;
|
|
||||||
|
|
||||||
return 0;
|
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;
|
struct crypto_ahash *tfm;
|
||||||
|
|
||||||
free_page((unsigned long)state->page);
|
|
||||||
|
|
||||||
tfm = crypto_ahash_reqtfm(req);
|
tfm = crypto_ahash_reqtfm(req);
|
||||||
if (!ahash_is_async(tfm))
|
if (!ahash_is_async(tfm))
|
||||||
return;
|
return;
|
||||||
|
@ -692,9 +694,8 @@ int crypto_ahash_finup(struct ahash_request *req)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(crypto_ahash_finup);
|
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;
|
struct crypto_ahash *tfm;
|
||||||
|
|
||||||
if (err)
|
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)
|
if (err == -EINPROGRESS || err == -EBUSY)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
return ahash_def_finup_finish1(req, err);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
ahash_restore_req(state);
|
ahash_restore_req(req);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -726,7 +729,7 @@ static void ahash_def_digest_done(void *data, int err)
|
||||||
|
|
||||||
areq->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
|
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)
|
if (err == -EINPROGRESS || err == -EBUSY)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -736,20 +739,17 @@ out:
|
||||||
|
|
||||||
static int ahash_def_digest(struct ahash_request *req)
|
static int ahash_def_digest(struct ahash_request *req)
|
||||||
{
|
{
|
||||||
struct ahash_save_req_state *state;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = ahash_save_req(req, ahash_def_digest_done);
|
err = ahash_save_req(req, ahash_def_digest_done);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
state = req->base.data;
|
|
||||||
|
|
||||||
err = crypto_ahash_init(req);
|
err = crypto_ahash_init(req);
|
||||||
if (err == -EINPROGRESS || err == -EBUSY)
|
if (err == -EINPROGRESS || err == -EBUSY)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
return ahash_def_digest_finish(state, err);
|
return ahash_def_digest_finish(req, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
int crypto_ahash_digest(struct ahash_request *req)
|
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)
|
if (err == -EINPROGRESS)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ahash_restore_req(state);
|
ahash_restore_req(areq);
|
||||||
ahash_request_complete(areq, err);
|
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;
|
struct crypto_ahash *tfm;
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -812,7 +811,7 @@ static int ahash_def_finup_finish1(struct ahash_save_req_state *state, int err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
ahash_restore_req(state);
|
ahash_restore_req(req);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -829,7 +828,7 @@ static void ahash_def_finup_done1(void *data, int err)
|
||||||
|
|
||||||
areq->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
|
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)
|
if (err == -EINPROGRESS || err == -EBUSY)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -839,20 +838,17 @@ out:
|
||||||
|
|
||||||
static int ahash_def_finup(struct ahash_request *req)
|
static int ahash_def_finup(struct ahash_request *req)
|
||||||
{
|
{
|
||||||
struct ahash_save_req_state *state;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = ahash_save_req(req, ahash_def_finup_done1);
|
err = ahash_save_req(req, ahash_def_finup_done1);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
state = req->base.data;
|
|
||||||
|
|
||||||
err = crypto_ahash_update(req);
|
err = crypto_ahash_update(req);
|
||||||
if (err == -EINPROGRESS || err == -EBUSY)
|
if (err == -EINPROGRESS || err == -EBUSY)
|
||||||
return err;
|
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)
|
int crypto_ahash_export(struct ahash_request *req, void *out)
|
||||||
|
|
Loading…
Add table
Reference in a new issue