From ec38f82e85532bdde27af8dea8e6c09e26f88e16 Mon Sep 17 00:00:00 2001 From: Romain Perier Date: Fri, 22 Jul 2016 14:40:39 +0200 Subject: crypto: marvell - Fix memory leaks in TDMA chain for cipher requests So far in mv_cesa_ablkcipher_dma_req_init, if an error is thrown while the tdma chain is built there is a memory leak. This issue exists because the chain is assigned later at the end of the function, so the cleanup function is called with the wrong version of the chain. Fixes: db509a45339f ("crypto: marvell/cesa - add TDMA support") Signed-off-by: Romain Perier Acked-by: Boris Brezillon Signed-off-by: Herbert Xu diff --git a/drivers/crypto/marvell/cipher.c b/drivers/crypto/marvell/cipher.c index 48df03a..8391aba 100644 --- a/drivers/crypto/marvell/cipher.c +++ b/drivers/crypto/marvell/cipher.c @@ -320,7 +320,6 @@ static int mv_cesa_ablkcipher_dma_req_init(struct ablkcipher_request *req, GFP_KERNEL : GFP_ATOMIC; struct mv_cesa_req *basereq = &creq->base; struct mv_cesa_ablkcipher_dma_iter iter; - struct mv_cesa_tdma_chain chain; bool skip_ctx = false; int ret; unsigned int ivsize; @@ -347,13 +346,13 @@ static int mv_cesa_ablkcipher_dma_req_init(struct ablkcipher_request *req, return -ENOMEM; } - mv_cesa_tdma_desc_iter_init(&chain); + mv_cesa_tdma_desc_iter_init(&basereq->chain); mv_cesa_ablkcipher_req_iter_init(&iter, req); do { struct mv_cesa_op_ctx *op; - op = mv_cesa_dma_add_op(&chain, op_templ, skip_ctx, flags); + op = mv_cesa_dma_add_op(&basereq->chain, op_templ, skip_ctx, flags); if (IS_ERR(op)) { ret = PTR_ERR(op); goto err_free_tdma; @@ -363,18 +362,18 @@ static int mv_cesa_ablkcipher_dma_req_init(struct ablkcipher_request *req, mv_cesa_set_crypt_op_len(op, iter.base.op_len); /* Add input transfers */ - ret = mv_cesa_dma_add_op_transfers(&chain, &iter.base, + ret = mv_cesa_dma_add_op_transfers(&basereq->chain, &iter.base, &iter.src, flags); if (ret) goto err_free_tdma; /* Add dummy desc to launch the crypto operation */ - ret = mv_cesa_dma_add_dummy_launch(&chain, flags); + ret = mv_cesa_dma_add_dummy_launch(&basereq->chain, flags); if (ret) goto err_free_tdma; /* Add output transfers */ - ret = mv_cesa_dma_add_op_transfers(&chain, &iter.base, + ret = mv_cesa_dma_add_op_transfers(&basereq->chain, &iter.base, &iter.dst, flags); if (ret) goto err_free_tdma; @@ -383,13 +382,12 @@ static int mv_cesa_ablkcipher_dma_req_init(struct ablkcipher_request *req, /* Add output data for IV */ ivsize = crypto_ablkcipher_ivsize(crypto_ablkcipher_reqtfm(req)); - ret = mv_cesa_dma_add_iv_op(&chain, CESA_SA_CRYPT_IV_SRAM_OFFSET, + ret = mv_cesa_dma_add_iv_op(&basereq->chain, CESA_SA_CRYPT_IV_SRAM_OFFSET, ivsize, CESA_TDMA_SRC_IN_SRAM, flags); if (ret) goto err_free_tdma; - basereq->chain = chain; basereq->chain.last->flags |= CESA_TDMA_END_OF_REQ; return 0; -- cgit v0.10.2 From 603e989ebee21bfa9cddf8390d0515a07324edc8 Mon Sep 17 00:00:00 2001 From: Romain Perier Date: Fri, 22 Jul 2016 14:40:55 +0200 Subject: crypto: marvell - Don't chain at DMA level when backlog is disabled The flag CRYPTO_TFM_REQ_MAY_BACKLOG is optional and can be set from the user to put requests into the backlog queue when the main cryptographic queue is full. Before calling mv_cesa_tdma_chain we must check the value of the return status to be sure that the current request has been correctly queued or added to the backlog. Fixes: 85030c5168f1 ("crypto: marvell - Add support for chaining...") Signed-off-by: Romain Perier Acked-by: Boris Brezillon Signed-off-by: Herbert Xu diff --git a/drivers/crypto/marvell/cesa.c b/drivers/crypto/marvell/cesa.c index e373cc6..d64af86 100644 --- a/drivers/crypto/marvell/cesa.c +++ b/drivers/crypto/marvell/cesa.c @@ -180,10 +180,11 @@ int mv_cesa_queue_req(struct crypto_async_request *req, struct mv_cesa_engine *engine = creq->engine; spin_lock_bh(&engine->lock); - if (mv_cesa_req_get_type(creq) == CESA_DMA_REQ) - mv_cesa_tdma_chain(engine, creq); - ret = crypto_enqueue_request(&engine->queue, req); + if ((mv_cesa_req_get_type(creq) == CESA_DMA_REQ) && + (ret == -EINPROGRESS || + (ret == -EBUSY && req->flags & CRYPTO_TFM_REQ_MAY_BACKLOG))) + mv_cesa_tdma_chain(engine, creq); spin_unlock_bh(&engine->lock); if (ret != -EINPROGRESS) -- cgit v0.10.2 From 64ec6ccb76e6ef13c40ad68e125545f8807a26c8 Mon Sep 17 00:00:00 2001 From: Romain Perier Date: Fri, 22 Jul 2016 15:46:24 +0200 Subject: crypto: marvell - Update cache with input sg only when it is unmapped So far, the cache of the ahash requests was updated from the 'complete' operation. This complete operation is called from mv_cesa_tdma_process before the cleanup operation, which means that the content of req->src can be read and copied when it is still mapped. This commit fixes the issue by moving this cache update from mv_cesa_ahash_complete to mv_cesa_ahash_req_cleanup, so the copy is done once the sglist is unmapped. Fixes: 1bf6682cb31d ("crypto: marvell - Add a complete operation for..") Signed-off-by: Romain Perier Acked-by: Boris Brezillon Signed-off-by: Herbert Xu diff --git a/drivers/crypto/marvell/hash.c b/drivers/crypto/marvell/hash.c index c35912b..82e0f4e6 100644 --- a/drivers/crypto/marvell/hash.c +++ b/drivers/crypto/marvell/hash.c @@ -315,12 +315,6 @@ static void mv_cesa_ahash_complete(struct crypto_async_request *req) for (i = 0; i < digsize / 4; i++) creq->state[i] = readl_relaxed(engine->regs + CESA_IVDIG(i)); - if (creq->cache_ptr) - sg_pcopy_to_buffer(ahashreq->src, creq->src_nents, - creq->cache, - creq->cache_ptr, - ahashreq->nbytes - creq->cache_ptr); - if (creq->last_req) { /* * Hardware's MD5 digest is in little endian format, but @@ -365,6 +359,12 @@ static void mv_cesa_ahash_req_cleanup(struct crypto_async_request *req) mv_cesa_ahash_last_cleanup(ahashreq); mv_cesa_ahash_cleanup(ahashreq); + + if (creq->cache_ptr) + sg_pcopy_to_buffer(ahashreq->src, creq->src_nents, + creq->cache, + creq->cache_ptr, + ahashreq->nbytes - creq->cache_ptr); } static const struct mv_cesa_req_ops mv_cesa_ahash_req_ops = { -- cgit v0.10.2 From 4816c9406430d0d3d4fa58a212a7a869d429b315 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 28 Jul 2016 13:29:17 +0800 Subject: lib/mpi: Fix SG miter leak In mpi_read_raw_from_sgl we may leak the SG miter resouces after reading the leading zeroes. This patch fixes this by stopping the iteration once the leading zeroes have been read. Fixes: 127827b9c295 ("lib/mpi: Do not do sg_virt") Reported-by: Nicolai Stange Tested-by: Nicolai Stange Signed-off-by: Herbert Xu diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c index c6272ae..5a0f75a 100644 --- a/lib/mpi/mpicoder.c +++ b/lib/mpi/mpicoder.c @@ -363,6 +363,9 @@ MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes) lzeros = 0; } + miter.consumed = lzeros; + sg_miter_stop(&miter); + nbytes -= lzeros; nbits = nbytes * 8; if (nbits > MAX_EXTERN_MPI_BITS) { @@ -390,7 +393,10 @@ MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes) z = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; z %= BYTES_PER_MPI_LIMB; - for (;;) { + while (sg_miter_next(&miter)) { + buff = miter.addr; + len = miter.length; + for (x = 0; x < len; x++) { a <<= 8; a |= *buff++; @@ -400,12 +406,6 @@ MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes) } } z += x; - - if (!sg_miter_next(&miter)) - break; - - buff = miter.addr; - len = miter.length; } return val; -- cgit v0.10.2 From 8cf740ae85df69fb6376f31b42eb2ac7a138721f Mon Sep 17 00:00:00 2001 From: Romain Perier Date: Thu, 28 Jul 2016 11:59:43 +0200 Subject: crypto: marvell - Don't copy IV vectors from the _process op for ciphers The IV output vectors should only be copied from the _complete operation and not from the _process operation, i.e only from the operation that is designed to copy the result of the request to the right location. This copy is already done in the _complete operation, so this commit removes the duplicated code in the _process op. Fixes: 3610d6cd5231 ("crypto: marvell - Add a complete...") Signed-off-by: Romain Perier Acked-by: Boris Brezillon Signed-off-by: Herbert Xu diff --git a/drivers/crypto/marvell/cipher.c b/drivers/crypto/marvell/cipher.c index 8391aba..d19dc96 100644 --- a/drivers/crypto/marvell/cipher.c +++ b/drivers/crypto/marvell/cipher.c @@ -139,20 +139,11 @@ static int mv_cesa_ablkcipher_process(struct crypto_async_request *req, struct ablkcipher_request *ablkreq = ablkcipher_request_cast(req); struct mv_cesa_ablkcipher_req *creq = ablkcipher_request_ctx(ablkreq); struct mv_cesa_req *basereq = &creq->base; - unsigned int ivsize; - int ret; if (mv_cesa_req_get_type(basereq) == CESA_STD_REQ) return mv_cesa_ablkcipher_std_process(ablkreq, status); - ret = mv_cesa_dma_process(basereq, status); - if (ret) - return ret; - - ivsize = crypto_ablkcipher_ivsize(crypto_ablkcipher_reqtfm(ablkreq)); - memcpy_fromio(ablkreq->info, basereq->chain.last->data, ivsize); - - return 0; + return mv_cesa_dma_process(basereq, status); } static void mv_cesa_ablkcipher_step(struct crypto_async_request *req) -- cgit v0.10.2