DivestOS/Patches/Linux_CVEs/CVE-2014-9865/0.patch

92 lines
3.0 KiB
Diff

From e65a876a155de945e306f2726f3a557415e6044e Mon Sep 17 00:00:00 2001
From: Mona Hossain <mhossain@codeaurora.org>
Date: Tue, 1 Oct 2013 14:08:20 -0700
Subject: qseecom: Validate inputs from user space
Validate send_cmd, send_modfd_cmd and send_mdfd_resp
input parameters: cmd and response pointers and buffer
lengths and offsets issued to modify data.
Change-Id: I381836d08aaa48357486fbdc6a122eb5b42bfa0b
Signed-off-by: Mona Hossain <mhossain@codeaurora.org>
---
drivers/misc/qseecom.c | 35 +++++++++++++++++++++++++++++++++--
1 file changed, 33 insertions(+), 2 deletions(-)
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 4c1943b..97f3362 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -1134,9 +1134,22 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data,
pr_err("cmd buffer or response buffer is null\n");
return -EINVAL;
}
+ if (((uint32_t)req->cmd_req_buf < data->client.user_virt_sb_base) ||
+ ((uint32_t)req->cmd_req_buf >= (data->client.user_virt_sb_base +
+ data->client.sb_length))) {
+ pr_err("cmd buffer address not within shared bufffer\n");
+ return -EINVAL;
+ }
+
+
+ if (((uint32_t)req->resp_buf < data->client.user_virt_sb_base) ||
+ ((uint32_t)req->resp_buf >= (data->client.user_virt_sb_base +
+ data->client.sb_length))){
+ pr_err("response buffer address not within shared bufffer\n");
+ return -EINVAL;
+ }
- if (req->cmd_req_len <= 0 ||
- req->resp_len <= 0 ||
+ if ((req->cmd_req_len == 0) || (req->resp_len == 0) ||
req->cmd_req_len > data->client.sb_length ||
req->resp_len > data->client.sb_length) {
pr_err("cmd buffer length or "
@@ -1371,6 +1384,7 @@ static int qseecom_send_modfd_cmd(struct qseecom_dev_handle *data,
void __user *argp)
{
int ret = 0;
+ int i;
struct qseecom_send_modfd_cmd_req req;
struct qseecom_send_cmd_req send_cmd_req;
@@ -1384,6 +1398,14 @@ static int qseecom_send_modfd_cmd(struct qseecom_dev_handle *data,
send_cmd_req.resp_buf = req.resp_buf;
send_cmd_req.resp_len = req.resp_len;
+ /* validate offsets */
+ for (i = 0; i < MAX_ION_FD; i++) {
+ if (req.ifd_data[i].cmd_buf_offset >= req.cmd_req_len) {
+ pr_err("Invalid offset %d = 0x%x\n",
+ i, req.ifd_data[i].cmd_buf_offset);
+ return -EINVAL;
+ }
+ }
ret = __qseecom_update_cmd_buf(&req, false, data, false);
if (ret)
return ret;
@@ -2001,11 +2023,20 @@ static int qseecom_send_modfd_resp(struct qseecom_dev_handle *data,
void __user *argp)
{
struct qseecom_send_modfd_listener_resp resp;
+ int i;
if (copy_from_user(&resp, argp, sizeof(resp))) {
pr_err("copy_from_user failed");
return -EINVAL;
}
+ /* validate offsets */
+ for (i = 0; i < MAX_ION_FD; i++) {
+ if (resp.ifd_data[i].cmd_buf_offset >= resp.resp_len) {
+ pr_err("Invalid offset %d = 0x%x\n",
+ i, resp.ifd_data[i].cmd_buf_offset);
+ return -EINVAL;
+ }
+ }
__qseecom_update_cmd_buf(&resp, false, data, true);
qseecom.send_resp_flag = 1;
wake_up_interruptible(&qseecom.send_resp_wq);
--
cgit v1.1