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

Commit e8dee207 authored by AnilKumar Chimata's avatar AnilKumar Chimata Committed by Gerrit - the friendly Code Review server
Browse files

crypto: qcedev: Fix out of memory issue



Fixes memory leak issue which is caused due to unfreed memory
of req struct after processing the user space request , this
happens for every client who are using from user space through
ioctls.

Change-Id: I2f267b960a2c73a65b85e72b0bff9a87df68b4e0
Signed-off-by: default avatarAnilKumar Chimata <anilc@codeaurora.org>
Signed-off-by: default avatarSwetha Chikkaboraiah <schikk@codeaurora.org>
parent d9add1d7
Loading
Loading
Loading
Loading
+81 −44
Original line number Original line Diff line number Diff line
@@ -1618,12 +1618,15 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
	if (podev == NULL || podev->magic != QCEDEV_MAGIC) {
	if (podev == NULL || podev->magic != QCEDEV_MAGIC) {
		pr_err("%s: invalid handle %pK\n",
		pr_err("%s: invalid handle %pK\n",
			__func__, podev);
			__func__, podev);
		return -ENOENT;
		err = -ENOENT;
		goto exit_free_qcedev_areq;
	}
	}


	/* Verify user arguments. */
	/* Verify user arguments. */
	if (_IOC_TYPE(cmd) != QCEDEV_IOC_MAGIC)
	if (_IOC_TYPE(cmd) != QCEDEV_IOC_MAGIC) {
		return -ENOTTY;
		err = -ENOTTY;
		goto exit_free_qcedev_areq;
	}


	init_completion(&qcedev_areq->complete);
	init_completion(&qcedev_areq->complete);
	pstat = &_qcedev_stat;
	pstat = &_qcedev_stat;
@@ -1633,21 +1636,27 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
	case QCEDEV_IOCTL_DEC_REQ:
	case QCEDEV_IOCTL_DEC_REQ:
		if (copy_from_user(&qcedev_areq->cipher_op_req,
		if (copy_from_user(&qcedev_areq->cipher_op_req,
				(void __user *)arg,
				(void __user *)arg,
				sizeof(struct qcedev_cipher_op_req)))
				sizeof(struct qcedev_cipher_op_req))) {
			return -EFAULT;
			err = -EFAULT;
			goto exit_free_qcedev_areq;
		}
		qcedev_areq->op_type = QCEDEV_CRYPTO_OPER_CIPHER;
		qcedev_areq->op_type = QCEDEV_CRYPTO_OPER_CIPHER;


		if (qcedev_check_cipher_params(&qcedev_areq->cipher_op_req,
		if (qcedev_check_cipher_params(&qcedev_areq->cipher_op_req,
				podev))
				podev)) {
			return -EINVAL;
			err = -EINVAL;
			goto exit_free_qcedev_areq;
		}


		err = qcedev_vbuf_ablk_cipher(qcedev_areq, handle);
		err = qcedev_vbuf_ablk_cipher(qcedev_areq, handle);
		if (err)
		if (err)
			return err;
			goto exit_free_qcedev_areq;
		if (copy_to_user((void __user *)arg,
		if (copy_to_user((void __user *)arg,
					&qcedev_areq->cipher_op_req,
					&qcedev_areq->cipher_op_req,
					sizeof(struct qcedev_cipher_op_req)))
					sizeof(struct qcedev_cipher_op_req))) {
			return -EFAULT;
			err = -EFAULT;
			goto exit_free_qcedev_areq;
		}
		break;
		break;


	case QCEDEV_IOCTL_SHA_INIT_REQ:
	case QCEDEV_IOCTL_SHA_INIT_REQ:
@@ -1656,41 +1665,51 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)


		if (copy_from_user(&qcedev_areq->sha_op_req,
		if (copy_from_user(&qcedev_areq->sha_op_req,
					(void __user *)arg,
					(void __user *)arg,
					sizeof(struct qcedev_sha_op_req)))
					sizeof(struct qcedev_sha_op_req))) {
			return -EFAULT;
			err = -EFAULT;
			goto exit_free_qcedev_areq;
		}
		mutex_lock(&hash_access_lock);
		mutex_lock(&hash_access_lock);
		if (qcedev_check_sha_params(&qcedev_areq->sha_op_req, podev)) {
		if (qcedev_check_sha_params(&qcedev_areq->sha_op_req, podev)) {
			mutex_unlock(&hash_access_lock);
			mutex_unlock(&hash_access_lock);
			return -EINVAL;
			err = -EINVAL;
			goto exit_free_qcedev_areq;
		}
		}
		qcedev_areq->op_type = QCEDEV_CRYPTO_OPER_SHA;
		qcedev_areq->op_type = QCEDEV_CRYPTO_OPER_SHA;
		err = qcedev_hash_init(qcedev_areq, handle, &sg_src);
		err = qcedev_hash_init(qcedev_areq, handle, &sg_src);
		if (err) {
		if (err) {
			mutex_unlock(&hash_access_lock);
			mutex_unlock(&hash_access_lock);
			return err;
			goto exit_free_qcedev_areq;
		}
		}
		mutex_unlock(&hash_access_lock);
		mutex_unlock(&hash_access_lock);
		if (copy_to_user((void __user *)arg, &qcedev_areq->sha_op_req,
		if (copy_to_user((void __user *)arg, &qcedev_areq->sha_op_req,
					sizeof(struct qcedev_sha_op_req)))
					sizeof(struct qcedev_sha_op_req))) {
			return -EFAULT;
			err = -EFAULT;
			goto exit_free_qcedev_areq;
		}
		}
		handle->sha_ctxt.init_done = true;
		handle->sha_ctxt.init_done = true;
		}
		break;
		break;
	case QCEDEV_IOCTL_GET_CMAC_REQ:
	case QCEDEV_IOCTL_GET_CMAC_REQ:
		if (!podev->ce_support.cmac)
		if (!podev->ce_support.cmac) {
			return -ENOTTY;
			err = -ENOTTY;
			goto exit_free_qcedev_areq;
		}
	case QCEDEV_IOCTL_SHA_UPDATE_REQ:
	case QCEDEV_IOCTL_SHA_UPDATE_REQ:
		{
		{
		struct scatterlist sg_src;
		struct scatterlist sg_src;


		if (copy_from_user(&qcedev_areq->sha_op_req,
		if (copy_from_user(&qcedev_areq->sha_op_req,
					(void __user *)arg,
					(void __user *)arg,
					sizeof(struct qcedev_sha_op_req)))
					sizeof(struct qcedev_sha_op_req))) {
			return -EFAULT;
			err = -EFAULT;
			goto exit_free_qcedev_areq;
		}
		mutex_lock(&hash_access_lock);
		mutex_lock(&hash_access_lock);
		if (qcedev_check_sha_params(&qcedev_areq->sha_op_req, podev)) {
		if (qcedev_check_sha_params(&qcedev_areq->sha_op_req, podev)) {
			mutex_unlock(&hash_access_lock);
			mutex_unlock(&hash_access_lock);
			return -EINVAL;
			err = -EINVAL;
			goto exit_free_qcedev_areq;
		}
		}
		qcedev_areq->op_type = QCEDEV_CRYPTO_OPER_SHA;
		qcedev_areq->op_type = QCEDEV_CRYPTO_OPER_SHA;


@@ -1698,18 +1717,19 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
			err = qcedev_hash_cmac(qcedev_areq, handle, &sg_src);
			err = qcedev_hash_cmac(qcedev_areq, handle, &sg_src);
			if (err) {
			if (err) {
				mutex_unlock(&hash_access_lock);
				mutex_unlock(&hash_access_lock);
				return err;
				goto exit_free_qcedev_areq;
			}
			}
		} else {
		} else {
			if (handle->sha_ctxt.init_done == false) {
			if (handle->sha_ctxt.init_done == false) {
				pr_err("%s Init was not called\n", __func__);
				pr_err("%s Init was not called\n", __func__);
				mutex_unlock(&hash_access_lock);
				mutex_unlock(&hash_access_lock);
				return -EINVAL;
				err = -EINVAL;
				goto exit_free_qcedev_areq;
			}
			}
			err = qcedev_hash_update(qcedev_areq, handle, &sg_src);
			err = qcedev_hash_update(qcedev_areq, handle, &sg_src);
			if (err) {
			if (err) {
				mutex_unlock(&hash_access_lock);
				mutex_unlock(&hash_access_lock);
				return err;
				goto exit_free_qcedev_areq;
			}
			}
		}
		}


@@ -1717,7 +1737,8 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
			pr_err("Invalid sha_ctxt.diglen %d\n",
			pr_err("Invalid sha_ctxt.diglen %d\n",
					handle->sha_ctxt.diglen);
					handle->sha_ctxt.diglen);
			mutex_unlock(&hash_access_lock);
			mutex_unlock(&hash_access_lock);
			return -EINVAL;
			err = -EINVAL;
			goto exit_free_qcedev_areq;
		}
		}
		memcpy(&qcedev_areq->sha_op_req.digest[0],
		memcpy(&qcedev_areq->sha_op_req.digest[0],
				&handle->sha_ctxt.digest[0],
				&handle->sha_ctxt.digest[0],
@@ -1725,7 +1746,8 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
		mutex_unlock(&hash_access_lock);
		mutex_unlock(&hash_access_lock);
		if (copy_to_user((void __user *)arg, &qcedev_areq->sha_op_req,
		if (copy_to_user((void __user *)arg, &qcedev_areq->sha_op_req,
					sizeof(struct qcedev_sha_op_req)))
					sizeof(struct qcedev_sha_op_req)))
			return -EFAULT;
			err = -EFAULT;
			goto exit_free_qcedev_areq;
		}
		}
		break;
		break;


@@ -1733,28 +1755,33 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)


		if (handle->sha_ctxt.init_done == false) {
		if (handle->sha_ctxt.init_done == false) {
			pr_err("%s Init was not called\n", __func__);
			pr_err("%s Init was not called\n", __func__);
			return -EINVAL;
			err = -EINVAL;
			goto exit_free_qcedev_areq;
		}
		}
		if (copy_from_user(&qcedev_areq->sha_op_req,
		if (copy_from_user(&qcedev_areq->sha_op_req,
					(void __user *)arg,
					(void __user *)arg,
					sizeof(struct qcedev_sha_op_req)))
					sizeof(struct qcedev_sha_op_req))) {
			return -EFAULT;
			err = -EFAULT;
			goto exit_free_qcedev_areq;
		}
		mutex_lock(&hash_access_lock);
		mutex_lock(&hash_access_lock);
		if (qcedev_check_sha_params(&qcedev_areq->sha_op_req, podev)) {
		if (qcedev_check_sha_params(&qcedev_areq->sha_op_req, podev)) {
			mutex_unlock(&hash_access_lock);
			mutex_unlock(&hash_access_lock);
			return -EINVAL;
			err = -EINVAL;
			goto exit_free_qcedev_areq;
		}
		}
		qcedev_areq->op_type = QCEDEV_CRYPTO_OPER_SHA;
		qcedev_areq->op_type = QCEDEV_CRYPTO_OPER_SHA;
		err = qcedev_hash_final(qcedev_areq, handle);
		err = qcedev_hash_final(qcedev_areq, handle);
		if (err) {
		if (err) {
			mutex_unlock(&hash_access_lock);
			mutex_unlock(&hash_access_lock);
			return err;
			goto exit_free_qcedev_areq;
		}
		}
		if (handle->sha_ctxt.diglen > QCEDEV_MAX_SHA_DIGEST) {
		if (handle->sha_ctxt.diglen > QCEDEV_MAX_SHA_DIGEST) {
			pr_err("Invalid sha_ctxt.diglen %d\n",
			pr_err("Invalid sha_ctxt.diglen %d\n",
					handle->sha_ctxt.diglen);
					handle->sha_ctxt.diglen);
			mutex_unlock(&hash_access_lock);
			mutex_unlock(&hash_access_lock);
			return -EINVAL;
			err = -EINVAL;
			goto exit_free_qcedev_areq;
		}
		}
		qcedev_areq->sha_op_req.diglen = handle->sha_ctxt.diglen;
		qcedev_areq->sha_op_req.diglen = handle->sha_ctxt.diglen;
		memcpy(&qcedev_areq->sha_op_req.digest[0],
		memcpy(&qcedev_areq->sha_op_req.digest[0],
@@ -1762,8 +1789,10 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
				handle->sha_ctxt.diglen);
				handle->sha_ctxt.diglen);
		mutex_unlock(&hash_access_lock);
		mutex_unlock(&hash_access_lock);
		if (copy_to_user((void __user *)arg, &qcedev_areq->sha_op_req,
		if (copy_to_user((void __user *)arg, &qcedev_areq->sha_op_req,
					sizeof(struct qcedev_sha_op_req)))
					sizeof(struct qcedev_sha_op_req))) {
			return -EFAULT;
			err = -EFAULT;
			goto exit_free_qcedev_areq;
		}
		handle->sha_ctxt.init_done = false;
		handle->sha_ctxt.init_done = false;
		break;
		break;


@@ -1773,30 +1802,34 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)


		if (copy_from_user(&qcedev_areq->sha_op_req,
		if (copy_from_user(&qcedev_areq->sha_op_req,
					(void __user *)arg,
					(void __user *)arg,
					sizeof(struct qcedev_sha_op_req)))
					sizeof(struct qcedev_sha_op_req))) {
			return -EFAULT;
			err = -EFAULT;
			goto exit_free_qcedev_areq;
		}
		mutex_lock(&hash_access_lock);
		mutex_lock(&hash_access_lock);
		if (qcedev_check_sha_params(&qcedev_areq->sha_op_req, podev)) {
		if (qcedev_check_sha_params(&qcedev_areq->sha_op_req, podev)) {
			mutex_unlock(&hash_access_lock);
			mutex_unlock(&hash_access_lock);
			return -EINVAL;
			err = -EINVAL;
			goto exit_free_qcedev_areq;
		}
		}
		qcedev_areq->op_type = QCEDEV_CRYPTO_OPER_SHA;
		qcedev_areq->op_type = QCEDEV_CRYPTO_OPER_SHA;
		qcedev_hash_init(qcedev_areq, handle, &sg_src);
		qcedev_hash_init(qcedev_areq, handle, &sg_src);
		err = qcedev_hash_update(qcedev_areq, handle, &sg_src);
		err = qcedev_hash_update(qcedev_areq, handle, &sg_src);
		if (err) {
		if (err) {
			mutex_unlock(&hash_access_lock);
			mutex_unlock(&hash_access_lock);
			return err;
			goto exit_free_qcedev_areq;
		}
		}
		err = qcedev_hash_final(qcedev_areq, handle);
		err = qcedev_hash_final(qcedev_areq, handle);
		if (err) {
		if (err) {
			mutex_unlock(&hash_access_lock);
			mutex_unlock(&hash_access_lock);
			return err;
			goto exit_free_qcedev_areq;
		}
		}
		if (handle->sha_ctxt.diglen > QCEDEV_MAX_SHA_DIGEST) {
		if (handle->sha_ctxt.diglen > QCEDEV_MAX_SHA_DIGEST) {
			pr_err("Invalid sha_ctxt.diglen %d\n",
			pr_err("Invalid sha_ctxt.diglen %d\n",
					handle->sha_ctxt.diglen);
					handle->sha_ctxt.diglen);
			mutex_unlock(&hash_access_lock);
			mutex_unlock(&hash_access_lock);
			return -EINVAL;
			err = -EINVAL;
			goto exit_free_qcedev_areq;
		}
		}
		qcedev_areq->sha_op_req.diglen =	handle->sha_ctxt.diglen;
		qcedev_areq->sha_op_req.diglen =	handle->sha_ctxt.diglen;
		memcpy(&qcedev_areq->sha_op_req.digest[0],
		memcpy(&qcedev_areq->sha_op_req.digest[0],
@@ -1804,15 +1837,19 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
				handle->sha_ctxt.diglen);
				handle->sha_ctxt.diglen);
		mutex_unlock(&hash_access_lock);
		mutex_unlock(&hash_access_lock);
		if (copy_to_user((void __user *)arg, &qcedev_areq->sha_op_req,
		if (copy_to_user((void __user *)arg, &qcedev_areq->sha_op_req,
					sizeof(struct qcedev_sha_op_req)))
					sizeof(struct qcedev_sha_op_req))) {
			return -EFAULT;
			err = -EFAULT;
			goto exit_free_qcedev_areq;
			}
		}
		}
		break;
		break;

	default:
	default:
		return -ENOTTY;
		err = -ENOTTY;
		goto exit_free_qcedev_areq;
	}
	}


exit_free_qcedev_areq:
	kfree(qcedev_areq);
	return err;
	return err;
}
}
EXPORT_SYMBOL(qcedev_ioctl);
EXPORT_SYMBOL(qcedev_ioctl);