Commit 5d1cdfde authored by Ira Weiny's avatar Ira Weiny Committed by Herbert Xu

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: default avatarIra Weiny <ira.weiny@intel.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 3a61cdf4
...@@ -1072,27 +1072,32 @@ int hash_hw_update(struct ahash_request *req) ...@@ -1072,27 +1072,32 @@ int hash_hw_update(struct ahash_request *req)
struct hash_ctx *ctx = crypto_ahash_ctx(tfm); struct hash_ctx *ctx = crypto_ahash_ctx(tfm);
struct hash_req_ctx *req_ctx = ahash_request_ctx(req); struct hash_req_ctx *req_ctx = ahash_request_ctx(req);
struct crypto_hash_walk walk; struct crypto_hash_walk walk;
int msg_length = crypto_hash_walk_first(req, &walk); int msg_length;
/* Empty message ("") is correct indata */
if (msg_length == 0)
return ret;
index = req_ctx->state.index; index = req_ctx->state.index;
buffer = (u8 *)req_ctx->state.buffer; 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 /* Check if ctx->state.length + msg_length
overflows */ overflows */
if (msg_length > (req_ctx->state.length.low_word + msg_length) && if (msg_length > (req_ctx->state.length.low_word + msg_length) &&
HASH_HIGH_WORD_MAX_VAL == req_ctx->state.length.high_word) { HASH_HIGH_WORD_MAX_VAL == req_ctx->state.length.high_word) {
pr_err("%s: HASH_MSG_LENGTH_OVERFLOW!\n", __func__); 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 */ /* Main loop */
while (0 != msg_length) { while (0 != msg_length) {
data_buffer = walk.data; data_buffer = walk.data;
...@@ -1102,7 +1107,8 @@ int hash_hw_update(struct ahash_request *req) ...@@ -1102,7 +1107,8 @@ int hash_hw_update(struct ahash_request *req)
if (ret) { if (ret) {
dev_err(device_data->dev, "%s: hash_internal_hw_update() failed!\n", dev_err(device_data->dev, "%s: hash_internal_hw_update() failed!\n",
__func__); __func__);
goto out; crypto_hash_walk_done(&walk, ret);
goto release_dev;
} }
msg_length = crypto_hash_walk_done(&walk, 0); msg_length = crypto_hash_walk_done(&walk, 0);
...@@ -1112,7 +1118,7 @@ int hash_hw_update(struct ahash_request *req) ...@@ -1112,7 +1118,7 @@ int hash_hw_update(struct ahash_request *req)
dev_dbg(device_data->dev, "%s: indata length=%d, bin=%d\n", dev_dbg(device_data->dev, "%s: indata length=%d, bin=%d\n",
__func__, req_ctx->state.index, req_ctx->state.bit_index); __func__, req_ctx->state.index, req_ctx->state.bit_index);
out: release_dev:
release_hash_device(device_data); release_hash_device(device_data);
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment