mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2024-10-01 01:35:54 -04:00
152 lines
5.2 KiB
Diff
152 lines
5.2 KiB
Diff
|
From f4948193c46f75e16d4382c4472485ab12b7bd17 Mon Sep 17 00:00:00 2001
|
||
|
From: Zhen Kong <zkong@codeaurora.org>
|
||
|
Date: Mon, 25 Nov 2013 13:05:35 -0800
|
||
|
Subject: qseecom: Add checks for user space buffer pointers
|
||
|
|
||
|
Validate pointers send from user space and pointers
|
||
|
embedded within the mesasge sent from user space.
|
||
|
|
||
|
Change-Id: I1be54924ef3d301908af6e8d4e6506f2aa7f6428
|
||
|
Signed-off-by: Mona Hossain <mhossain@codeaurora.org>
|
||
|
Signed-off-by: Zhen Kong <zkong@codeaurora.org>
|
||
|
---
|
||
|
drivers/misc/qseecom.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++-
|
||
|
1 file changed, 60 insertions(+), 1 deletion(-)
|
||
|
|
||
|
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
|
||
|
index 0bc18fb..c5c0ce8 100644
|
||
|
--- a/drivers/misc/qseecom.c
|
||
|
+++ b/drivers/misc/qseecom.c
|
||
|
@@ -99,7 +99,7 @@ static DEFINE_MUTEX(clk_access_lock);
|
||
|
struct qseecom_registered_listener_list {
|
||
|
struct list_head list;
|
||
|
struct qseecom_register_listener_req svc;
|
||
|
- u8 *sb_reg_req;
|
||
|
+ uint32_t user_virt_sb_base;
|
||
|
u8 *sb_virt;
|
||
|
s32 sb_phys;
|
||
|
size_t sb_length;
|
||
|
@@ -319,6 +319,10 @@ static int qseecom_register_listener(struct qseecom_dev_handle *data,
|
||
|
pr_err("copy_from_user failed\n");
|
||
|
return ret;
|
||
|
}
|
||
|
+ if (!access_ok(VERIFY_WRITE, (void __user *)rcvd_lstnr.virt_sb_base,
|
||
|
+ rcvd_lstnr.sb_size))
|
||
|
+ return -EFAULT;
|
||
|
+
|
||
|
data->listener.id = 0;
|
||
|
if (!__qseecom_is_svc_unique(data, &rcvd_lstnr)) {
|
||
|
pr_err("Service is not unique and is already registered\n");
|
||
|
@@ -336,6 +340,7 @@ static int qseecom_register_listener(struct qseecom_dev_handle *data,
|
||
|
|
||
|
new_entry->svc.listener_id = rcvd_lstnr.listener_id;
|
||
|
new_entry->sb_length = rcvd_lstnr.sb_size;
|
||
|
+ new_entry->user_virt_sb_base = rcvd_lstnr.virt_sb_base;
|
||
|
if (__qseecom_set_sb_memory(new_entry, data, &rcvd_lstnr)) {
|
||
|
pr_err("qseecom_set_sb_memoryfailed\n");
|
||
|
kzfree(new_entry);
|
||
|
@@ -446,6 +451,10 @@ static int qseecom_set_client_mem_param(struct qseecom_dev_handle *data,
|
||
|
req.ifd_data_fd, req.sb_len, req.virt_sb_base);
|
||
|
return -EFAULT;
|
||
|
}
|
||
|
+ if (!access_ok(VERIFY_WRITE, (void __user *)req.virt_sb_base,
|
||
|
+ req.sb_len))
|
||
|
+ return -EFAULT;
|
||
|
+
|
||
|
/* Get the handle of the shared fd */
|
||
|
data->client.ihandle = ion_import_dma_buf(qseecom.ion_clnt,
|
||
|
req.ifd_data_fd);
|
||
|
@@ -861,6 +870,13 @@ static uint32_t __qseecom_uvirt_to_kphys(struct qseecom_dev_handle *data,
|
||
|
return data->client.sb_phys + (virt - data->client.user_virt_sb_base);
|
||
|
}
|
||
|
|
||
|
+static uint32_t __qseecom_uvirt_to_kvirt(struct qseecom_dev_handle *data,
|
||
|
+ uint32_t virt)
|
||
|
+{
|
||
|
+ return (uint32_t)data->client.sb_virt +
|
||
|
+ (virt - data->client.user_virt_sb_base);
|
||
|
+}
|
||
|
+
|
||
|
int __qseecom_process_rpmb_svc_cmd(struct qseecom_dev_handle *data_ptr,
|
||
|
struct qseecom_send_svc_cmd_req *req_ptr,
|
||
|
struct qseecom_client_send_service_ireq *send_svc_ireq_ptr)
|
||
|
@@ -1269,6 +1285,24 @@ static int qseecom_send_modfd_cmd(struct qseecom_dev_handle *data,
|
||
|
pr_err("copy_from_user failed\n");
|
||
|
return ret;
|
||
|
}
|
||
|
+
|
||
|
+ if (req.cmd_req_buf == NULL || req.resp_buf == NULL) {
|
||
|
+ 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;
|
||
|
+ }
|
||
|
send_cmd_req.cmd_req_buf = req.cmd_req_buf;
|
||
|
send_cmd_req.cmd_req_len = req.cmd_req_len;
|
||
|
send_cmd_req.resp_buf = req.resp_buf;
|
||
|
@@ -1282,6 +1316,11 @@ static int qseecom_send_modfd_cmd(struct qseecom_dev_handle *data,
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
}
|
||
|
+ req.cmd_req_buf = (void *)__qseecom_uvirt_to_kvirt(data,
|
||
|
+ (uint32_t)req.cmd_req_buf);
|
||
|
+ req.resp_buf = (void *)__qseecom_uvirt_to_kvirt(data,
|
||
|
+ (uint32_t)req.resp_buf);
|
||
|
+
|
||
|
ret = __qseecom_update_cmd_buf(&req, false, data, false);
|
||
|
if (ret)
|
||
|
return ret;
|
||
|
@@ -1877,11 +1916,20 @@ static int qseecom_send_modfd_resp(struct qseecom_dev_handle *data,
|
||
|
{
|
||
|
struct qseecom_send_modfd_listener_resp resp;
|
||
|
int i;
|
||
|
+ struct qseecom_registered_listener_list *this_lstnr = NULL;
|
||
|
|
||
|
if (copy_from_user(&resp, argp, sizeof(resp))) {
|
||
|
pr_err("copy_from_user failed");
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
+ this_lstnr = __qseecom_find_svc(data->listener.id);
|
||
|
+ if (this_lstnr == NULL)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ if (resp.resp_buf_ptr == NULL) {
|
||
|
+ pr_err("Invalid resp_buf_ptr\n");
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
/* validate offsets */
|
||
|
for (i = 0; i < MAX_ION_FD; i++) {
|
||
|
if (resp.ifd_data[i].cmd_buf_offset >= resp.resp_len) {
|
||
|
@@ -1890,6 +1938,17 @@ static int qseecom_send_modfd_resp(struct qseecom_dev_handle *data,
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
}
|
||
|
+
|
||
|
+ if (((uint32_t)resp.resp_buf_ptr <
|
||
|
+ this_lstnr->user_virt_sb_base)
|
||
|
+ || ((uint32_t)resp.resp_buf_ptr >=
|
||
|
+ (this_lstnr->user_virt_sb_base +
|
||
|
+ this_lstnr->sb_length))) {
|
||
|
+ pr_err("resp_buf_ptr address not within shared buffer\n");
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+ resp.resp_buf_ptr = (uint32_t)this_lstnr->sb_virt +
|
||
|
+ (resp.resp_buf_ptr - this_lstnr->user_virt_sb_base);
|
||
|
__qseecom_update_cmd_buf(&resp, false, data, true);
|
||
|
qseecom.send_resp_flag = 1;
|
||
|
wake_up_interruptible(&qseecom.send_resp_wq);
|
||
|
--
|
||
|
cgit v1.1
|
||
|
|