diff options
author | Thomas Petazzoni <thomas.petazzoni@free-electrons.com> | 2015-09-18 11:25:36 -0400 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2015-09-21 10:57:36 -0400 |
commit | cfcd2271a9076a9891014bc8e18d4fd48acccffe (patch) | |
tree | ea6f3f654525f9d2f4c434576626010cb0e98106 /drivers/crypto/marvell/cipher.c | |
parent | 84cba178a3b88efe2668a9039f70abda072faa21 (diff) |
crypto: marvell - properly handle CRYPTO_TFM_REQ_MAY_BACKLOG-flagged requests
The mv_cesa_queue_req() function calls crypto_enqueue_request() to
enqueue a request. In the normal case (i.e the queue isn't full), this
function returns -EINPROGRESS. The current Marvell CESA crypto driver
takes this into account and cleans up the request only if an error
occured, i.e if the return value is not -EINPROGRESS.
Unfortunately this causes problems with
CRYPTO_TFM_REQ_MAY_BACKLOG-flagged requests. When such a request is
passed to crypto_enqueue_request() and the queue is full,
crypto_enqueue_request() will return -EBUSY, but will keep the request
enqueued nonetheless. This situation was not properly handled by the
Marvell CESA driver, which was anyway cleaning up the request in such
a situation. When later on the request was taken out of the backlog
and actually processed, a kernel crash occured due to the internal
driver data structures for this structure having been cleaned up.
To avoid this situation, this commit adds a
mv_cesa_req_needs_cleanup() helper function which indicates if the
request needs to be cleaned up or not after a call to
crypto_enqueue_request(). This helper allows to do the cleanup only in
the appropriate cases, and all call sites of mv_cesa_queue_req() are
fixed to use this new helper function.
Reported-by: Vincent Donnefort <vdonnefort@gmail.com>
Fixes: db509a45339fd ("crypto: marvell/cesa - add TDMA support")
Cc: <stable@vger.kernel.org> # v4.2+
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Acked-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Tested-by: Vincent Donnefort <vdonnefort@gmail.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/crypto/marvell/cipher.c')
-rw-r--r-- | drivers/crypto/marvell/cipher.c | 7 |
1 files changed, 3 insertions, 4 deletions
diff --git a/drivers/crypto/marvell/cipher.c b/drivers/crypto/marvell/cipher.c index 0745cf3b9c0e..3df2f4e7adb2 100644 --- a/drivers/crypto/marvell/cipher.c +++ b/drivers/crypto/marvell/cipher.c | |||
@@ -189,7 +189,6 @@ static inline void mv_cesa_ablkcipher_prepare(struct crypto_async_request *req, | |||
189 | { | 189 | { |
190 | struct ablkcipher_request *ablkreq = ablkcipher_request_cast(req); | 190 | struct ablkcipher_request *ablkreq = ablkcipher_request_cast(req); |
191 | struct mv_cesa_ablkcipher_req *creq = ablkcipher_request_ctx(ablkreq); | 191 | struct mv_cesa_ablkcipher_req *creq = ablkcipher_request_ctx(ablkreq); |
192 | |||
193 | creq->req.base.engine = engine; | 192 | creq->req.base.engine = engine; |
194 | 193 | ||
195 | if (creq->req.base.type == CESA_DMA_REQ) | 194 | if (creq->req.base.type == CESA_DMA_REQ) |
@@ -431,7 +430,7 @@ static int mv_cesa_des_op(struct ablkcipher_request *req, | |||
431 | return ret; | 430 | return ret; |
432 | 431 | ||
433 | ret = mv_cesa_queue_req(&req->base); | 432 | ret = mv_cesa_queue_req(&req->base); |
434 | if (ret && ret != -EINPROGRESS) | 433 | if (mv_cesa_req_needs_cleanup(&req->base, ret)) |
435 | mv_cesa_ablkcipher_cleanup(req); | 434 | mv_cesa_ablkcipher_cleanup(req); |
436 | 435 | ||
437 | return ret; | 436 | return ret; |
@@ -551,7 +550,7 @@ static int mv_cesa_des3_op(struct ablkcipher_request *req, | |||
551 | return ret; | 550 | return ret; |
552 | 551 | ||
553 | ret = mv_cesa_queue_req(&req->base); | 552 | ret = mv_cesa_queue_req(&req->base); |
554 | if (ret && ret != -EINPROGRESS) | 553 | if (mv_cesa_req_needs_cleanup(&req->base, ret)) |
555 | mv_cesa_ablkcipher_cleanup(req); | 554 | mv_cesa_ablkcipher_cleanup(req); |
556 | 555 | ||
557 | return ret; | 556 | return ret; |
@@ -693,7 +692,7 @@ static int mv_cesa_aes_op(struct ablkcipher_request *req, | |||
693 | return ret; | 692 | return ret; |
694 | 693 | ||
695 | ret = mv_cesa_queue_req(&req->base); | 694 | ret = mv_cesa_queue_req(&req->base); |
696 | if (ret && ret != -EINPROGRESS) | 695 | if (mv_cesa_req_needs_cleanup(&req->base, ret)) |
697 | mv_cesa_ablkcipher_cleanup(req); | 696 | mv_cesa_ablkcipher_cleanup(req); |
698 | 697 | ||
699 | return ret; | 698 | return ret; |