crypto: sun8i-ce-hash - fix error handling in sun8i_ce_hash_run()

[ Upstream commit ea4dd134ef332bd9e3e734c1ba0a1521f436b678 ]

Rework error handling in sun8i_ce_hash_run() to unmap the dma buffers in
case of failure. Currently, the dma unmap functions are not called if the
function errors out at various points.

Fixes: 56f6d5aee8 ("crypto: sun8i-ce - support hash algorithms")
Signed-off-by: Ovidiu Panait <ovidiu.panait.oss@gmail.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Ovidiu Panait
2025-04-01 22:23:16 +03:00
committed by Greg Kroah-Hartman
parent 5dea6398f2
commit 76c7b1407a

View File

@@ -343,9 +343,8 @@ int sun8i_ce_hash_run(struct crypto_engine *engine, void *breq)
u32 common; u32 common;
u64 byte_count; u64 byte_count;
__le32 *bf; __le32 *bf;
void *buf = NULL; void *buf, *result;
int j, i, todo; int j, i, todo;
void *result = NULL;
u64 bs; u64 bs;
int digestsize; int digestsize;
dma_addr_t addr_res, addr_pad; dma_addr_t addr_res, addr_pad;
@@ -365,14 +364,14 @@ int sun8i_ce_hash_run(struct crypto_engine *engine, void *breq)
buf = kzalloc(bs * 2, GFP_KERNEL | GFP_DMA); buf = kzalloc(bs * 2, GFP_KERNEL | GFP_DMA);
if (!buf) { if (!buf) {
err = -ENOMEM; err = -ENOMEM;
goto theend; goto err_out;
} }
bf = (__le32 *)buf; bf = (__le32 *)buf;
result = kzalloc(digestsize, GFP_KERNEL | GFP_DMA); result = kzalloc(digestsize, GFP_KERNEL | GFP_DMA);
if (!result) { if (!result) {
err = -ENOMEM; err = -ENOMEM;
goto theend; goto err_free_buf;
} }
flow = rctx->flow; flow = rctx->flow;
@@ -398,7 +397,7 @@ int sun8i_ce_hash_run(struct crypto_engine *engine, void *breq)
if (nr_sgs <= 0 || nr_sgs > MAX_SG) { if (nr_sgs <= 0 || nr_sgs > MAX_SG) {
dev_err(ce->dev, "Invalid sg number %d\n", nr_sgs); dev_err(ce->dev, "Invalid sg number %d\n", nr_sgs);
err = -EINVAL; err = -EINVAL;
goto theend; goto err_free_result;
} }
len = areq->nbytes; len = areq->nbytes;
@@ -411,7 +410,7 @@ int sun8i_ce_hash_run(struct crypto_engine *engine, void *breq)
if (len > 0) { if (len > 0) {
dev_err(ce->dev, "remaining len %d\n", len); dev_err(ce->dev, "remaining len %d\n", len);
err = -EINVAL; err = -EINVAL;
goto theend; goto err_unmap_src;
} }
addr_res = dma_map_single(ce->dev, result, digestsize, DMA_FROM_DEVICE); addr_res = dma_map_single(ce->dev, result, digestsize, DMA_FROM_DEVICE);
cet->t_dst[0].addr = cpu_to_le32(addr_res); cet->t_dst[0].addr = cpu_to_le32(addr_res);
@@ -419,7 +418,7 @@ int sun8i_ce_hash_run(struct crypto_engine *engine, void *breq)
if (dma_mapping_error(ce->dev, addr_res)) { if (dma_mapping_error(ce->dev, addr_res)) {
dev_err(ce->dev, "DMA map dest\n"); dev_err(ce->dev, "DMA map dest\n");
err = -EINVAL; err = -EINVAL;
goto theend; goto err_unmap_src;
} }
byte_count = areq->nbytes; byte_count = areq->nbytes;
@@ -441,7 +440,7 @@ int sun8i_ce_hash_run(struct crypto_engine *engine, void *breq)
} }
if (!j) { if (!j) {
err = -EINVAL; err = -EINVAL;
goto theend; goto err_unmap_result;
} }
addr_pad = dma_map_single(ce->dev, buf, j * 4, DMA_TO_DEVICE); addr_pad = dma_map_single(ce->dev, buf, j * 4, DMA_TO_DEVICE);
@@ -450,7 +449,7 @@ int sun8i_ce_hash_run(struct crypto_engine *engine, void *breq)
if (dma_mapping_error(ce->dev, addr_pad)) { if (dma_mapping_error(ce->dev, addr_pad)) {
dev_err(ce->dev, "DMA error on padding SG\n"); dev_err(ce->dev, "DMA error on padding SG\n");
err = -EINVAL; err = -EINVAL;
goto theend; goto err_unmap_result;
} }
if (ce->variant->hash_t_dlen_in_bits) if (ce->variant->hash_t_dlen_in_bits)
@@ -463,16 +462,25 @@ int sun8i_ce_hash_run(struct crypto_engine *engine, void *breq)
err = sun8i_ce_run_task(ce, flow, crypto_ahash_alg_name(tfm)); err = sun8i_ce_run_task(ce, flow, crypto_ahash_alg_name(tfm));
dma_unmap_single(ce->dev, addr_pad, j * 4, DMA_TO_DEVICE); dma_unmap_single(ce->dev, addr_pad, j * 4, DMA_TO_DEVICE);
dma_unmap_sg(ce->dev, areq->src, ns, DMA_TO_DEVICE);
err_unmap_result:
dma_unmap_single(ce->dev, addr_res, digestsize, DMA_FROM_DEVICE); dma_unmap_single(ce->dev, addr_res, digestsize, DMA_FROM_DEVICE);
if (!err)
memcpy(areq->result, result, algt->alg.hash.base.halg.digestsize); memcpy(areq->result, result, algt->alg.hash.base.halg.digestsize);
theend:
kfree(buf); err_unmap_src:
dma_unmap_sg(ce->dev, areq->src, ns, DMA_TO_DEVICE);
err_free_result:
kfree(result); kfree(result);
err_free_buf:
kfree(buf);
err_out:
local_bh_disable(); local_bh_disable();
crypto_finalize_hash_request(engine, breq, err); crypto_finalize_hash_request(engine, breq, err);
local_bh_enable(); local_bh_enable();
return 0; return 0;
} }