diff options
author | Ira Weiny <ira.weiny@intel.com> | 2020-08-10 17:40:14 -0700 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2020-08-21 14:47:49 +1000 |
commit | 5d1cdfde11a5f0c9a21b8b2b085bac678e8a18b7 (patch) | |
tree | 7f37db3e3fdb1d0408a83ce589e9f39cd761f7a4 /drivers/crypto/ux500 | |
parent | 3a61cdf43e670b99404436a5854aae993ef616ed (diff) |
crypto: ux500 - Fix kmap() bug
Once the crypto hash walk is started by crypto_hash_walk_first()
returning non-zero, crypto_hash_walk_done() must be called to unmap any
memory which was mapped by *_walk_first().
Ensure crypto_hash_walk_done() is called properly by:
1) Re-arranging the check for device data to be prior to calling
*_walk_first()
2) on error call crypto_hash_walk_done() with an error code to
allow the hash walk code to clean up.
While we are at it clean up the 'out' label to be more meaningful.
Signed-off-by: Ira Weiny <ira.weiny@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/crypto/ux500')
-rw-r--r-- | drivers/crypto/ux500/hash/hash_core.c | 30 |
1 files changed, 18 insertions, 12 deletions
diff --git a/drivers/crypto/ux500/hash/hash_core.c b/drivers/crypto/ux500/hash/hash_core.c index c231d3710f83..3d407eebb2ba 100644 --- a/drivers/crypto/ux500/hash/hash_core.c +++ b/drivers/crypto/ux500/hash/hash_core.c @@ -1072,27 +1072,32 @@ int hash_hw_update(struct ahash_request *req) struct hash_ctx *ctx = crypto_ahash_ctx(tfm); struct hash_req_ctx *req_ctx = ahash_request_ctx(req); struct crypto_hash_walk walk; - int msg_length = crypto_hash_walk_first(req, &walk); - - /* Empty message ("") is correct indata */ - if (msg_length == 0) - return ret; + int msg_length; index = req_ctx->state.index; buffer = (u8 *)req_ctx->state.buffer; + ret = hash_get_device_data(ctx, &device_data); + if (ret) + return ret; + + msg_length = crypto_hash_walk_first(req, &walk); + + /* Empty message ("") is correct indata */ + if (msg_length == 0) { + ret = 0; + goto release_dev; + } + /* Check if ctx->state.length + msg_length overflows */ if (msg_length > (req_ctx->state.length.low_word + msg_length) && HASH_HIGH_WORD_MAX_VAL == req_ctx->state.length.high_word) { pr_err("%s: HASH_MSG_LENGTH_OVERFLOW!\n", __func__); - return -EPERM; + ret = crypto_hash_walk_done(&walk, -EPERM); + goto release_dev; } - ret = hash_get_device_data(ctx, &device_data); - if (ret) - return ret; - /* Main loop */ while (0 != msg_length) { data_buffer = walk.data; @@ -1102,7 +1107,8 @@ int hash_hw_update(struct ahash_request *req) if (ret) { dev_err(device_data->dev, "%s: hash_internal_hw_update() failed!\n", __func__); - goto out; + crypto_hash_walk_done(&walk, ret); + goto release_dev; } msg_length = crypto_hash_walk_done(&walk, 0); @@ -1112,7 +1118,7 @@ int hash_hw_update(struct ahash_request *req) dev_dbg(device_data->dev, "%s: indata length=%d, bin=%d\n", __func__, req_ctx->state.index, req_ctx->state.bit_index); -out: +release_dev: release_hash_device(device_data); return ret; |