diff options
author | AnilKumar Chimata <anilc@codeaurora.org> | 2019-02-08 15:42:48 +0530 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2020-04-21 00:43:37 -0700 |
commit | e8dee20786a900f096572e8c7ace2107baceac75 (patch) | |
tree | f99d06de8f79962f9d4e51b770c7db841db8f0be /drivers/crypto | |
parent | d9add1d73d8fdbed8ee29108e24cd710b5d8cbe0 (diff) |
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: AnilKumar Chimata <anilc@codeaurora.org>
Signed-off-by: Swetha Chikkaboraiah <schikk@codeaurora.org>
Diffstat (limited to 'drivers/crypto')
-rw-r--r-- | drivers/crypto/msm/qcedev.c | 125 |
1 files changed, 81 insertions, 44 deletions
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c index bbbb15fdd4f8..f4cd405717d1 100644 --- a/drivers/crypto/msm/qcedev.c +++ b/drivers/crypto/msm/qcedev.c @@ -1618,12 +1618,15 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg) 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; @@ -1633,21 +1636,27 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg) 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: @@ -1656,41 +1665,51 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg) 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; @@ -1698,18 +1717,19 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg) 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; } } @@ -1717,7 +1737,8 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg) 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], @@ -1725,7 +1746,8 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg) 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; @@ -1733,28 +1755,33 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg) 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], @@ -1762,8 +1789,10 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg) 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; @@ -1773,30 +1802,34 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg) 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], @@ -1804,15 +1837,19 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg) 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; + } } break; - default: - return -ENOTTY; + err = -ENOTTY; + goto exit_free_qcedev_areq; } +exit_free_qcedev_areq: + kfree(qcedev_areq); return err; } EXPORT_SYMBOL(qcedev_ioctl); |