Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b9805a3d authored by AnilKumar Chimata's avatar AnilKumar Chimata Committed by Dinesh K Garg
Browse files

crypto: msm: Fix buffer overflow issue



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: default avatarAnilKumar Chimata <anilc@codeaurora.org>
parent d98d9ee8
Loading
Loading
Loading
Loading
+41 −10
Original line number Diff line number Diff line
@@ -57,6 +57,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 int qcedev_control_clocks(struct qcedev_control *podev, bool enable)
{
@@ -1699,12 +1700,18 @@ static inline long qcedev_ioctl(struct file *file,
					(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;
@@ -1722,32 +1729,42 @@ static inline long qcedev_ioctl(struct file *file,
					(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;
@@ -1764,16 +1781,22 @@ static inline long qcedev_ioctl(struct file *file,
					(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;
@@ -1788,20 +1811,28 @@ static inline long qcedev_ioctl(struct file *file,
					(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;