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:
committed by
Greg Kroah-Hartman
parent
5dea6398f2
commit
76c7b1407a
@@ -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;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user