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

Commit 534a9eda authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "crypto: qcedev: Fix out of memory issue"

parents b0c1bbcb 0c0f7fab
Loading
Loading
Loading
Loading
+94 −51
Original line number Diff line number Diff line
/*
 * QTI CE device driver.
 *
 * Copyright (c) 2010-2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2010-2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -1676,12 +1676,15 @@ static inline long qcedev_ioctl(struct file *file,
	if (podev == NULL || podev->magic != QCEDEV_MAGIC) {
		pr_err("%s: invalid handle %pK\n",
			__func__, podev);
		return -ENOENT;
		err = -ENOENT;
		goto exit_free_qcedev_areq;
	}

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

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

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

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

	case QCEDEV_IOCTL_SHA_INIT_REQ:
@@ -1714,41 +1723,51 @@ static inline long qcedev_ioctl(struct file *file,

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

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

@@ -1756,18 +1775,19 @@ static inline long qcedev_ioctl(struct file *file,
			err = qcedev_hash_cmac(qcedev_areq, handle, &sg_src);
			if (err) {
				mutex_unlock(&hash_access_lock);
				return err;
				goto exit_free_qcedev_areq;
			}
		} 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 = -EINVAL;
				goto exit_free_qcedev_areq;
			}
			err = qcedev_hash_update(qcedev_areq, handle, &sg_src);
			if (err) {
				mutex_unlock(&hash_access_lock);
				return err;
				goto exit_free_qcedev_areq;
			}
		}

@@ -1775,7 +1795,8 @@ static inline long qcedev_ioctl(struct file *file,
			pr_err("Invalid sha_ctxt.diglen %d\n",
					handle->sha_ctxt.diglen);
			mutex_unlock(&hash_access_lock);
			return -EINVAL;
			err = -EINVAL;
			goto exit_free_qcedev_areq;
		}
		memcpy(&qcedev_areq->sha_op_req.digest[0],
				&handle->sha_ctxt.digest[0],
@@ -1783,7 +1804,8 @@ static inline long qcedev_ioctl(struct file *file,
		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;
			err = -EFAULT;
			goto exit_free_qcedev_areq;
		}
		break;

@@ -1791,28 +1813,33 @@ static inline long qcedev_ioctl(struct file *file,

		if (handle->sha_ctxt.init_done == false) {
			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,
					(void __user *)arg,
					sizeof(struct qcedev_sha_op_req)))
			return -EFAULT;
					sizeof(struct qcedev_sha_op_req))) {
			err = -EFAULT;
			goto exit_free_qcedev_areq;
		}
		mutex_lock(&hash_access_lock);
		if (qcedev_check_sha_params(&qcedev_areq->sha_op_req, podev)) {
			mutex_unlock(&hash_access_lock);
			return -EINVAL;
			err = -EINVAL;
			goto exit_free_qcedev_areq;
		}
		qcedev_areq->op_type = QCEDEV_CRYPTO_OPER_SHA;
		err = qcedev_hash_final(qcedev_areq, handle);
		if (err) {
			mutex_unlock(&hash_access_lock);
			return err;
			goto exit_free_qcedev_areq;
		}
		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;
			err = -EINVAL;
			goto exit_free_qcedev_areq;
		}
		qcedev_areq->sha_op_req.diglen = handle->sha_ctxt.diglen;
		memcpy(&qcedev_areq->sha_op_req.digest[0],
@@ -1820,8 +1847,10 @@ static inline long qcedev_ioctl(struct file *file,
				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;
					sizeof(struct qcedev_sha_op_req))) {
			err = -EFAULT;
			goto exit_free_qcedev_areq;
		}
		handle->sha_ctxt.init_done = false;
		break;

@@ -1831,30 +1860,34 @@ static inline long qcedev_ioctl(struct file *file,

		if (copy_from_user(&qcedev_areq->sha_op_req,
					(void __user *)arg,
					sizeof(struct qcedev_sha_op_req)))
			return -EFAULT;
					sizeof(struct qcedev_sha_op_req))) {
			err = -EFAULT;
			goto exit_free_qcedev_areq;
		}
		mutex_lock(&hash_access_lock);
		if (qcedev_check_sha_params(&qcedev_areq->sha_op_req, podev)) {
			mutex_unlock(&hash_access_lock);
			return -EINVAL;
			err = -EINVAL;
			goto exit_free_qcedev_areq;
		}
		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) {
			mutex_unlock(&hash_access_lock);
			return err;
			goto exit_free_qcedev_areq;
		}
		err = qcedev_hash_final(qcedev_areq, handle);
		if (err) {
			mutex_unlock(&hash_access_lock);
			return err;
			goto exit_free_qcedev_areq;
		}
		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;
			err = -EINVAL;
			goto exit_free_qcedev_areq;
		}
		qcedev_areq->sha_op_req.diglen =	handle->sha_ctxt.diglen;
		memcpy(&qcedev_areq->sha_op_req.digest[0],
@@ -1863,7 +1896,8 @@ static inline long qcedev_ioctl(struct file *file,
		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;
			err = -EFAULT;
			goto exit_free_qcedev_areq;
		}
		break;

@@ -1874,8 +1908,10 @@ static inline long qcedev_ioctl(struct file *file,
			int i = 0;

			if (copy_from_user(&map_buf,
					(void __user *)arg, sizeof(map_buf)))
				return -EFAULT;
					(void __user *)arg, sizeof(map_buf))) {
				err = -EFAULT;
				goto exit_free_qcedev_areq;
			}

			for (i = 0; i < map_buf.num_fds; i++) {
				err = qcedev_check_and_map_buffer(handle,
@@ -1887,7 +1923,7 @@ static inline long qcedev_ioctl(struct file *file,
					pr_err(
						"%s: err: failed to map fd(%d) - %d\n",
						__func__, map_buf.fd[i], err);
					return err;
					goto exit_free_qcedev_areq;
				}
				map_buf.buf_vaddr[i] = vaddr;
				pr_info("%s: info: vaddr = %llx\n",
@@ -1895,8 +1931,10 @@ static inline long qcedev_ioctl(struct file *file,
			}

			if (copy_to_user((void __user *)arg, &map_buf,
					sizeof(map_buf)))
				return -EFAULT;
					sizeof(map_buf))) {
				err = -EFAULT;
				goto exit_free_qcedev_areq;
			}
			break;
		}

@@ -1906,8 +1944,10 @@ static inline long qcedev_ioctl(struct file *file,
			int i = 0;

			if (copy_from_user(&unmap_buf,
					(void __user *)arg, sizeof(unmap_buf)))
				return -EFAULT;
				(void __user *)arg, sizeof(unmap_buf))) {
				err = -EFAULT;
				goto exit_free_qcedev_areq;
			}

			for (i = 0; i < unmap_buf.num_fds; i++) {
				err = qcedev_check_and_unmap_buffer(handle,
@@ -1917,16 +1957,19 @@ static inline long qcedev_ioctl(struct file *file,
						"%s: err: failed to unmap fd(%d) - %d\n",
						 __func__,
						unmap_buf.fd[i], err);
					return err;
					goto exit_free_qcedev_areq;
				}
			}
			break;
		}

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

exit_free_qcedev_areq:
	kfree(qcedev_areq);
	return err;
}