aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhen Kong <zkong@codeaurora.org>2016-10-31 15:23:19 -0700
committerPat Tjin <pattjin@google.com>2017-01-18 23:28:50 +0000
commit7f8ca4dda02574eeca31a496f12fa009f189324c (patch)
treedbb617eb1923d72b48013eeb37a950f14005692a
parent83faf06ee99b5eb84c8992eef4bca788d7fbd22d (diff)
msm: crypto: fix issues on digest buf and copy_from_user in qcedev.candroid-7.0.0_r0.48
Make the digest length not larger than the size of the buffer qcedev_areq.sha_op_req.digest; and use the checked variants of the copy_from/to_user() APIs to avoid small race window of their unchecked variants. Bug: 31750232 Change-Id: I3db0c20ac5fa47ed278f3d60368c406f472430c1 Signed-off-by: Zhen Kong <zkong@codeaurora.org> Signed-off-by: Wei Wang <wvw@google.com>
-rw-r--r--drivers/crypto/msm/qcedev.c120
1 files changed, 27 insertions, 93 deletions
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index 94d6bad1dd62..75274f7e4c7d 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -704,7 +704,7 @@ static int qcedev_sha_update_max_xfer(struct qcedev_async_req *qcedev_areq,
while (len > 0) {
user_src =
(void __user *)qcedev_areq->sha_op_req.data[i].vaddr;
- if (user_src && __copy_from_user(k_src,
+ if (user_src && copy_from_user(k_src,
(void __user *)user_src,
qcedev_areq->sha_op_req.data[i].len))
return -EFAULT;
@@ -740,7 +740,7 @@ static int qcedev_sha_update_max_xfer(struct qcedev_async_req *qcedev_areq,
/* Copy data from user src(s) */
user_src = (void __user *)qcedev_areq->sha_op_req.data[0].vaddr;
- if (user_src && __copy_from_user(k_src,
+ if (user_src && copy_from_user(k_src,
(void __user *)user_src,
qcedev_areq->sha_op_req.data[0].len)) {
kzfree(k_buf_src);
@@ -749,7 +749,7 @@ static int qcedev_sha_update_max_xfer(struct qcedev_async_req *qcedev_areq,
k_src += qcedev_areq->sha_op_req.data[0].len;
for (i = 1; i < qcedev_areq->sha_op_req.entries; i++) {
user_src = (void __user *)qcedev_areq->sha_op_req.data[i].vaddr;
- if (user_src && __copy_from_user(k_src,
+ if (user_src && copy_from_user(k_src,
(void __user *)user_src,
qcedev_areq->sha_op_req.data[i].len)) {
kzfree(k_buf_src);
@@ -803,13 +803,6 @@ static int qcedev_sha_update(struct qcedev_async_req *qcedev_areq,
return -EINVAL;
}
- /* verify address src(s) */
- for (i = 0; i < qcedev_areq->sha_op_req.entries; i++)
- if (!access_ok(VERIFY_READ,
- (void __user *)qcedev_areq->sha_op_req.data[i].vaddr,
- qcedev_areq->sha_op_req.data[i].len))
- return -EFAULT;
-
if (qcedev_areq->sha_op_req.data_len > QCE_MAX_OPER_DATA) {
struct qcedev_sha_op_req *saved_req;
@@ -974,19 +967,7 @@ static int qcedev_hash_cmac(struct qcedev_async_req *qcedev_areq,
total = qcedev_areq->sha_op_req.data_len;
- /* verify address src(s) */
- for (i = 0; i < qcedev_areq->sha_op_req.entries; i++)
- if (!access_ok(VERIFY_READ,
- (void __user *)qcedev_areq->sha_op_req.data[i].vaddr,
- qcedev_areq->sha_op_req.data[i].len))
- return -EFAULT;
-
- /* Verify Source Address */
- if (!access_ok(VERIFY_READ,
- (void __user *)qcedev_areq->sha_op_req.authkey,
- qcedev_areq->sha_op_req.authklen))
- return -EFAULT;
- if (__copy_from_user(&handle->sha_ctxt.authkey[0],
+ if (copy_from_user(&handle->sha_ctxt.authkey[0],
(void __user *)qcedev_areq->sha_op_req.authkey,
qcedev_areq->sha_op_req.authklen))
return -EFAULT;
@@ -1006,7 +987,7 @@ static int qcedev_hash_cmac(struct qcedev_async_req *qcedev_areq,
for (i = 0; i < qcedev_areq->sha_op_req.entries; i++) {
user_src =
(void __user *)qcedev_areq->sha_op_req.data[i].vaddr;
- if (user_src && __copy_from_user(k_src, (void __user *)user_src,
+ if (user_src && copy_from_user(k_src, (void __user *)user_src,
qcedev_areq->sha_op_req.data[i].len)) {
kzfree(k_buf_src);
return -EFAULT;
@@ -1034,12 +1015,7 @@ static int qcedev_set_hmac_auth_key(struct qcedev_async_req *areq,
if (areq->sha_op_req.authklen <= QCEDEV_MAX_KEY_SIZE) {
qcedev_sha_init(areq, handle);
- /* Verify Source Address */
- if (!access_ok(VERIFY_READ,
- (void __user *)areq->sha_op_req.authkey,
- areq->sha_op_req.authklen))
- return -EFAULT;
- if (__copy_from_user(&handle->sha_ctxt.authkey[0],
+ if (copy_from_user(&handle->sha_ctxt.authkey[0],
(void __user *)areq->sha_op_req.authkey,
areq->sha_op_req.authklen))
return -EFAULT;
@@ -1252,7 +1228,7 @@ static int qcedev_vbuf_ablk_cipher_max_xfer(struct qcedev_async_req *areq,
byteoffset = areq->cipher_op_req.byteoffset;
user_src = (void __user *)areq->cipher_op_req.vbuf.src[0].vaddr;
- if (user_src && __copy_from_user((k_align_src + byteoffset),
+ if (user_src && copy_from_user((k_align_src + byteoffset),
(void __user *)user_src,
areq->cipher_op_req.vbuf.src[0].len))
return -EFAULT;
@@ -1262,7 +1238,7 @@ static int qcedev_vbuf_ablk_cipher_max_xfer(struct qcedev_async_req *areq,
for (i = 1; i < areq->cipher_op_req.entries; i++) {
user_src =
(void __user *)areq->cipher_op_req.vbuf.src[i].vaddr;
- if (user_src && __copy_from_user(k_align_src,
+ if (user_src && copy_from_user(k_align_src,
(void __user *)user_src,
areq->cipher_op_req.vbuf.src[i].len)) {
return -EFAULT;
@@ -1294,7 +1270,7 @@ static int qcedev_vbuf_ablk_cipher_max_xfer(struct qcedev_async_req *areq,
while (creq->data_len > 0) {
if (creq->vbuf.dst[dst_i].len <= creq->data_len) {
- if (err == 0 && __copy_to_user(
+ if (err == 0 && copy_to_user(
(void __user *)creq->vbuf.dst[dst_i].vaddr,
(k_align_dst + byteoffset),
creq->vbuf.dst[dst_i].len))
@@ -1305,7 +1281,7 @@ static int qcedev_vbuf_ablk_cipher_max_xfer(struct qcedev_async_req *areq,
creq->data_len -= creq->vbuf.dst[dst_i].len;
dst_i++;
} else {
- if (err == 0 && __copy_to_user(
+ if (err == 0 && copy_to_user(
(void __user *)creq->vbuf.dst[dst_i].vaddr,
(k_align_dst + byteoffset),
creq->data_len))
@@ -1637,36 +1613,6 @@ static int qcedev_check_cipher_params(struct qcedev_cipher_op_req *req,
__func__, total, req->data_len);
goto error;
}
- /* Verify Source Address's */
- for (i = 0, total = 0; i < req->entries; i++) {
- if (total < req->data_len) {
- if (!access_ok(VERIFY_READ,
- (void __user *)req->vbuf.src[i].vaddr,
- req->vbuf.src[i].len)) {
- pr_err("%s:SRC RD_VERIFY err %d=0x%lx\n",
- __func__, i, (uintptr_t)
- req->vbuf.src[i].vaddr);
- goto error;
- }
- total += req->vbuf.src[i].len;
- }
- }
-
- /* Verify Destination Address's */
- for (i = 0, total = 0; i < QCEDEV_MAX_BUFFERS; i++) {
- if ((req->vbuf.dst[i].vaddr != 0) &&
- (total < req->data_len)) {
- if (!access_ok(VERIFY_WRITE,
- (void __user *)req->vbuf.dst[i].vaddr,
- req->vbuf.dst[i].len)) {
- pr_err("%s:DST WR_VERIFY err %d=0x%lx\n",
- __func__, i, (uintptr_t)
- req->vbuf.dst[i].vaddr);
- goto error;
- }
- total += req->vbuf.dst[i].len;
- }
- }
return 0;
error:
return -EINVAL;
@@ -1775,11 +1721,7 @@ static long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
break;
case QCEDEV_IOCTL_ENC_REQ:
case QCEDEV_IOCTL_DEC_REQ:
- if (!access_ok(VERIFY_WRITE, (void __user *)arg,
- sizeof(struct qcedev_cipher_op_req)))
- return -EFAULT;
-
- if (__copy_from_user(&qcedev_areq.cipher_op_req,
+ if (copy_from_user(&qcedev_areq.cipher_op_req,
(void __user *)arg,
sizeof(struct qcedev_cipher_op_req)))
return -EFAULT;
@@ -1792,20 +1734,17 @@ static long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
err = qcedev_vbuf_ablk_cipher(&qcedev_areq, handle);
if (err)
return err;
- if (__copy_to_user((void __user *)arg,
+ if (copy_to_user((void __user *)arg,
&qcedev_areq.cipher_op_req,
sizeof(struct qcedev_cipher_op_req)))
- return -EFAULT;
+ return -EFAULT;
break;
case QCEDEV_IOCTL_SHA_INIT_REQ:
{
struct scatterlist sg_src;
- if (!access_ok(VERIFY_WRITE, (void __user *)arg,
- sizeof(struct qcedev_sha_op_req)))
- return -EFAULT;
- if (__copy_from_user(&qcedev_areq.sha_op_req,
+ if (copy_from_user(&qcedev_areq.sha_op_req,
(void __user *)arg,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
@@ -1815,9 +1754,9 @@ static long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
err = qcedev_hash_init(&qcedev_areq, handle, &sg_src);
if (err)
return err;
- 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)))
- return -EFAULT;
+ return -EFAULT;
}
handle->sha_ctxt.init_done = true;
break;
@@ -1827,11 +1766,8 @@ static long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
case QCEDEV_IOCTL_SHA_UPDATE_REQ:
{
struct scatterlist sg_src;
- if (!access_ok(VERIFY_WRITE, (void __user *)arg,
- sizeof(struct qcedev_sha_op_req)))
- return -EFAULT;
- if (__copy_from_user(&qcedev_areq.sha_op_req,
+ if (copy_from_user(&qcedev_areq.sha_op_req,
(void __user *)arg,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
@@ -1853,10 +1789,15 @@ static long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
return err;
}
+ if (handle->sha_ctxt.diglen > QCEDEV_MAX_SHA_DIGEST) {
+ pr_err("Invalid sha_ctxt.diglen %d\n",
+ handle->sha_ctxt.diglen);
+ return -EINVAL;
+ }
memcpy(&qcedev_areq.sha_op_req.digest[0],
&handle->sha_ctxt.digest[0],
handle->sha_ctxt.diglen);
- 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)))
return -EFAULT;
}
@@ -1868,11 +1809,7 @@ static long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
pr_err("%s Init was not called\n", __func__);
return -EINVAL;
}
- if (!access_ok(VERIFY_WRITE, (void __user *)arg,
- sizeof(struct qcedev_sha_op_req)))
- return -EFAULT;
-
- if (__copy_from_user(&qcedev_areq.sha_op_req,
+ if (copy_from_user(&qcedev_areq.sha_op_req,
(void __user *)arg,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
@@ -1886,7 +1823,7 @@ static long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
memcpy(&qcedev_areq.sha_op_req.digest[0],
&handle->sha_ctxt.digest[0],
handle->sha_ctxt.diglen);
- 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)))
return -EFAULT;
handle->sha_ctxt.init_done = false;
@@ -1895,11 +1832,8 @@ static long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
case QCEDEV_IOCTL_GET_SHA_REQ:
{
struct scatterlist sg_src;
- if (!access_ok(VERIFY_WRITE, (void __user *)arg,
- sizeof(struct qcedev_sha_op_req)))
- return -EFAULT;
- if (__copy_from_user(&qcedev_areq.sha_op_req,
+ if (copy_from_user(&qcedev_areq.sha_op_req,
(void __user *)arg,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
@@ -1917,7 +1851,7 @@ static long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
memcpy(&qcedev_areq.sha_op_req.digest[0],
&handle->sha_ctxt.digest[0],
handle->sha_ctxt.diglen);
- 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)))
return -EFAULT;
}