crypto: qce: skcipher: Fix incorrect sg count for dma transfers
authorThara Gopinath <thara.gopinath@linaro.org>
Fri, 21 May 2021 02:20:23 +0000 (22:20 -0400)
committerHerbert Xu <herbert@gondor.apana.org.au>
Fri, 28 May 2021 07:11:45 +0000 (15:11 +0800)
Use the sg count returned by dma_map_sg to call into
dmaengine_prep_slave_sg rather than using the original sg count. dma_map_sg
can merge consecutive sglist entries, thus making the original sg count
wrong. This is a fix for memory coruption issues observed while testing
encryption/decryption of large messages using libkcapi framework.

Patch has been tested further by running full suite of tcrypt.ko tests
including fuzz tests.

Signed-off-by: Thara Gopinath <thara.gopinath@linaro.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/qce/skcipher.c

index c0a0d8c..2594184 100644 (file)
@@ -72,7 +72,7 @@ qce_skcipher_async_req_handle(struct crypto_async_request *async_req)
        struct scatterlist *sg;
        bool diff_dst;
        gfp_t gfp;
-       int ret;
+       int dst_nents, src_nents, ret;
 
        rctx->iv = req->iv;
        rctx->ivsize = crypto_skcipher_ivsize(skcipher);
@@ -123,21 +123,22 @@ qce_skcipher_async_req_handle(struct crypto_async_request *async_req)
        sg_mark_end(sg);
        rctx->dst_sg = rctx->dst_tbl.sgl;
 
-       ret = dma_map_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst);
-       if (ret < 0)
+       dst_nents = dma_map_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst);
+       if (dst_nents < 0)
                goto error_free;
 
        if (diff_dst) {
-               ret = dma_map_sg(qce->dev, req->src, rctx->src_nents, dir_src);
-               if (ret < 0)
+               src_nents = dma_map_sg(qce->dev, req->src, rctx->src_nents, dir_src);
+               if (src_nents < 0)
                        goto error_unmap_dst;
                rctx->src_sg = req->src;
        } else {
                rctx->src_sg = rctx->dst_sg;
+               src_nents = dst_nents - 1;
        }
 
-       ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, rctx->src_nents,
-                              rctx->dst_sg, rctx->dst_nents,
+       ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, src_nents,
+                              rctx->dst_sg, dst_nents,
                               qce_skcipher_done, async_req);
        if (ret)
                goto error_unmap_src;