Skip to content

Commit

Permalink
crypto: msm: Fix buffer overflow issue
Browse files Browse the repository at this point in the history
In multi-threaded environment diglen variable could be modified
by multiple threads at the same time. Buffer overflow might
happen in current thread if another thread changes the diglen
variable. So add mutex locks to avoid this issue.

Change-Id: I62c63c55c028dedb1dd0eec862851bd8e818a5d3
Signed-off-by: AnilKumar Chimata <[email protected]>
  • Loading branch information
AnilKumar Chimata authored and Gerrit - the friendly Code Review server committed Apr 24, 2017
1 parent 8a45407 commit ef9d8a1
Showing 1 changed file with 41 additions and 10 deletions.
51 changes: 41 additions & 10 deletions drivers/crypto/msm/qcedev.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ static uint8_t _std_init_vector_sha256_uint8[] = {

static DEFINE_MUTEX(send_cmd_lock);
static DEFINE_MUTEX(qcedev_sent_bw_req);
static DEFINE_MUTEX(hash_access_lock);

static void qcedev_ce_high_bw_req(struct qcedev_control *podev,
bool high_bw_req)
Expand Down Expand Up @@ -1653,12 +1654,18 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
(void __user *)arg,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev))
mutex_lock(&hash_access_lock);
if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev)) {
mutex_unlock(&hash_access_lock);
return -EINVAL;
}
qcedev_areq.op_type = QCEDEV_CRYPTO_OPER_SHA;
err = qcedev_hash_init(&qcedev_areq, handle, &sg_src);
if (err)
if (err) {
mutex_unlock(&hash_access_lock);
return err;
}
mutex_unlock(&hash_access_lock);
if (copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
Expand All @@ -1676,32 +1683,42 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
(void __user *)arg,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev))
mutex_lock(&hash_access_lock);
if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev)) {
mutex_unlock(&hash_access_lock);
return -EINVAL;
}
qcedev_areq.op_type = QCEDEV_CRYPTO_OPER_SHA;

if (qcedev_areq.sha_op_req.alg == QCEDEV_ALG_AES_CMAC) {
err = qcedev_hash_cmac(&qcedev_areq, handle, &sg_src);
if (err)
if (err) {
mutex_unlock(&hash_access_lock);
return err;
}
} else {
if (handle->sha_ctxt.init_done == false) {
pr_err("%s Init was not called\n", __func__);
mutex_unlock(&hash_access_lock);
return -EINVAL;
}
err = qcedev_hash_update(&qcedev_areq, handle, &sg_src);
if (err)
if (err) {
mutex_unlock(&hash_access_lock);
return err;
}
}

if (handle->sha_ctxt.diglen > QCEDEV_MAX_SHA_DIGEST) {
pr_err("Invalid sha_ctxt.diglen %d\n",
handle->sha_ctxt.diglen);
mutex_unlock(&hash_access_lock);
return -EINVAL;
}
memcpy(&qcedev_areq.sha_op_req.digest[0],
&handle->sha_ctxt.digest[0],
handle->sha_ctxt.diglen);
mutex_unlock(&hash_access_lock);
if (copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
Expand All @@ -1718,16 +1735,22 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
(void __user *)arg,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev))
mutex_lock(&hash_access_lock);
if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev)) {
mutex_unlock(&hash_access_lock);
return -EINVAL;
}
qcedev_areq.op_type = QCEDEV_CRYPTO_OPER_SHA;
err = qcedev_hash_final(&qcedev_areq, handle);
if (err)
if (err) {
mutex_unlock(&hash_access_lock);
return err;
}
qcedev_areq.sha_op_req.diglen = handle->sha_ctxt.diglen;
memcpy(&qcedev_areq.sha_op_req.digest[0],
&handle->sha_ctxt.digest[0],
handle->sha_ctxt.diglen);
mutex_unlock(&hash_access_lock);
if (copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
Expand All @@ -1742,20 +1765,28 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
(void __user *)arg,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev))
mutex_lock(&hash_access_lock);
if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev)) {
mutex_unlock(&hash_access_lock);
return -EINVAL;
}
qcedev_areq.op_type = QCEDEV_CRYPTO_OPER_SHA;
qcedev_hash_init(&qcedev_areq, handle, &sg_src);
err = qcedev_hash_update(&qcedev_areq, handle, &sg_src);
if (err)
if (err) {
mutex_unlock(&hash_access_lock);
return err;
}
err = qcedev_hash_final(&qcedev_areq, handle);
if (err)
if (err) {
mutex_unlock(&hash_access_lock);
return err;
}
qcedev_areq.sha_op_req.diglen = handle->sha_ctxt.diglen;
memcpy(&qcedev_areq.sha_op_req.digest[0],
&handle->sha_ctxt.digest[0],
handle->sha_ctxt.diglen);
mutex_unlock(&hash_access_lock);
if (copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
Expand Down

0 comments on commit ef9d8a1

Please sign in to comment.