Commit ea4dd134 authored by Ovidiu Panait's avatar Ovidiu Panait Committed by Herbert Xu
Browse files

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



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: 56f6d5ae ("crypto: sun8i-ce - support hash algorithms")
Signed-off-by: default avatarOvidiu Panait <ovidiu.panait.oss@gmail.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 3f8f0133
Loading
Loading
Loading
Loading
+21 −13
Original line number Diff line number Diff line
@@ -343,9 +343,8 @@ int sun8i_ce_hash_run(struct crypto_engine *engine, void *breq)
	u32 common;
	u64 byte_count;
	__le32 *bf;
	void *buf = NULL;
	void *buf, *result;
	int j, i, todo;
	void *result = NULL;
	u64 bs;
	int digestsize;
	dma_addr_t addr_res, addr_pad;
@@ -365,14 +364,14 @@ int sun8i_ce_hash_run(struct crypto_engine *engine, void *breq)
	buf = kcalloc(2, bs, GFP_KERNEL | GFP_DMA);
	if (!buf) {
		err = -ENOMEM;
		goto theend;
		goto err_out;
	}
	bf = (__le32 *)buf;

	result = kzalloc(digestsize, GFP_KERNEL | GFP_DMA);
	if (!result) {
		err = -ENOMEM;
		goto theend;
		goto err_free_buf;
	}

	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) {
		dev_err(ce->dev, "Invalid sg number %d\n", nr_sgs);
		err = -EINVAL;
		goto theend;
		goto err_free_result;
	}

	len = areq->nbytes;
@@ -411,7 +410,7 @@ int sun8i_ce_hash_run(struct crypto_engine *engine, void *breq)
	if (len > 0) {
		dev_err(ce->dev, "remaining len %d\n", len);
		err = -EINVAL;
		goto theend;
		goto err_unmap_src;
	}
	addr_res = dma_map_single(ce->dev, result, digestsize, DMA_FROM_DEVICE);
	cet->t_dst[0].addr = desc_addr_val_le32(ce, 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)) {
		dev_err(ce->dev, "DMA map dest\n");
		err = -EINVAL;
		goto theend;
		goto err_unmap_src;
	}

	byte_count = areq->nbytes;
@@ -441,7 +440,7 @@ int sun8i_ce_hash_run(struct crypto_engine *engine, void *breq)
	}
	if (!j) {
		err = -EINVAL;
		goto theend;
		goto err_unmap_result;
	}

	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)) {
		dev_err(ce->dev, "DMA error on padding SG\n");
		err = -EINVAL;
		goto theend;
		goto err_unmap_result;
	}

	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));

	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);
	if (!err)
		memcpy(areq->result, result, algt->alg.hash.base.halg.digestsize);

err_unmap_src:
	dma_unmap_sg(ce->dev, areq->src, ns, DMA_TO_DEVICE);

	memcpy(areq->result, result, algt->alg.hash.base.halg.digestsize);
theend:
	kfree(buf);
err_free_result:
	kfree(result);

err_free_buf:
	kfree(buf);

err_out:
	local_bh_disable();
	crypto_finalize_hash_request(engine, breq, err);
	local_bh_enable();

	return 0;
}