diff options
author | Horia Geantă <horia.geanta@nxp.com> | 2017-02-10 07:07:23 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-05-14 08:00:13 -0400 |
commit | ccef31d22e802f98bd161aa7e54f2ad98bc5ba17 (patch) | |
tree | 20aa45ad5ff050b352b6ba0515b7244007004a77 /drivers/crypto | |
parent | 819e3601d3c5e483d8c42839a2acfbfb2eafe784 (diff) |
crypto: caam - fix error path for ctx_dma mapping failure
commit 87ec02e7409d787348c244039aa3536a812dfa8b upstream.
In case ctx_dma dma mapping fails, ahash_unmap_ctx() tries to
dma unmap an invalid address:
map_seq_out_ptr_ctx() / ctx_map_to_sec4_sg() -> goto unmap_ctx ->
-> ahash_unmap_ctx() -> dma unmap ctx_dma
There is also possible to reach ahash_unmap_ctx() with ctx_dma
uninitialzed or to try to unmap the same address twice.
Fix these by setting ctx_dma = 0 where needed:
-initialize ctx_dma in ahash_init()
-clear ctx_dma in case of mapping error (instead of holding
the error code returned by the dma map function)
-clear ctx_dma after each unmapping
Fixes: 32686d34f8fb6 ("crypto: caam - ensure that we clean up after an error")
Signed-off-by: Horia Geantă <horia.geanta@nxp.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/crypto')
-rw-r--r-- | drivers/crypto/caam/caamhash.c | 7 |
1 files changed, 6 insertions, 1 deletions
diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c index 660dc206969f..2474f1494955 100644 --- a/drivers/crypto/caam/caamhash.c +++ b/drivers/crypto/caam/caamhash.c | |||
@@ -154,6 +154,7 @@ static inline int map_seq_out_ptr_ctx(u32 *desc, struct device *jrdev, | |||
154 | ctx_len, DMA_FROM_DEVICE); | 154 | ctx_len, DMA_FROM_DEVICE); |
155 | if (dma_mapping_error(jrdev, state->ctx_dma)) { | 155 | if (dma_mapping_error(jrdev, state->ctx_dma)) { |
156 | dev_err(jrdev, "unable to map ctx\n"); | 156 | dev_err(jrdev, "unable to map ctx\n"); |
157 | state->ctx_dma = 0; | ||
157 | return -ENOMEM; | 158 | return -ENOMEM; |
158 | } | 159 | } |
159 | 160 | ||
@@ -214,6 +215,7 @@ static inline int ctx_map_to_sec4_sg(u32 *desc, struct device *jrdev, | |||
214 | state->ctx_dma = dma_map_single(jrdev, state->caam_ctx, ctx_len, flag); | 215 | state->ctx_dma = dma_map_single(jrdev, state->caam_ctx, ctx_len, flag); |
215 | if (dma_mapping_error(jrdev, state->ctx_dma)) { | 216 | if (dma_mapping_error(jrdev, state->ctx_dma)) { |
216 | dev_err(jrdev, "unable to map ctx\n"); | 217 | dev_err(jrdev, "unable to map ctx\n"); |
218 | state->ctx_dma = 0; | ||
217 | return -ENOMEM; | 219 | return -ENOMEM; |
218 | } | 220 | } |
219 | 221 | ||
@@ -620,8 +622,10 @@ static inline void ahash_unmap_ctx(struct device *dev, | |||
620 | struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); | 622 | struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); |
621 | struct caam_hash_state *state = ahash_request_ctx(req); | 623 | struct caam_hash_state *state = ahash_request_ctx(req); |
622 | 624 | ||
623 | if (state->ctx_dma) | 625 | if (state->ctx_dma) { |
624 | dma_unmap_single(dev, state->ctx_dma, ctx->ctx_len, flag); | 626 | dma_unmap_single(dev, state->ctx_dma, ctx->ctx_len, flag); |
627 | state->ctx_dma = 0; | ||
628 | } | ||
625 | ahash_unmap(dev, edesc, req, dst_len); | 629 | ahash_unmap(dev, edesc, req, dst_len); |
626 | } | 630 | } |
627 | 631 | ||
@@ -1605,6 +1609,7 @@ static int ahash_init(struct ahash_request *req) | |||
1605 | state->finup = ahash_finup_first; | 1609 | state->finup = ahash_finup_first; |
1606 | state->final = ahash_final_no_ctx; | 1610 | state->final = ahash_final_no_ctx; |
1607 | 1611 | ||
1612 | state->ctx_dma = 0; | ||
1608 | state->current_buf = 0; | 1613 | state->current_buf = 0; |
1609 | state->buf_dma = 0; | 1614 | state->buf_dma = 0; |
1610 | state->buflen_0 = 0; | 1615 | state->buflen_0 = 0; |