Loading drivers/misc/qseecom.c +134 −87 Original line number Diff line number Diff line Loading @@ -981,7 +981,7 @@ static int qseecom_scale_bus_bandwidth(struct qseecom_dev_handle *data, } if (req_mode > HIGH) { pr_err("Invalid bandwidth mode (%d)\n", req_mode); return ret; return -EINVAL; } /* Loading Loading @@ -1834,24 +1834,16 @@ exit: return ret; } static int __qseecom_send_cmd(struct qseecom_dev_handle *data, static int __validate_send_cmd_inputs(struct qseecom_dev_handle *data, struct qseecom_send_cmd_req *req) { int ret = 0; u32 reqd_len_sb_in = 0; struct qseecom_client_send_data_ireq send_data_req; struct qseecom_command_scm_resp resp; unsigned long flags; struct qseecom_registered_app_list *ptr_app; bool found_app = false; int name_len = 0; { if (!data || !data->client.ihandle) { pr_err("Client or client handle is not initialized\n"); return -EINVAL; } if (req->cmd_req_buf == NULL || req->resp_buf == NULL) { if (((req->resp_buf == NULL) && (req->resp_len != 0)) || (req->cmd_req_buf == NULL)) { pr_err("cmd buffer or response buffer is null\n"); return -EINVAL; } Loading @@ -1862,8 +1854,6 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data, pr_err("cmd buffer address not within shared bufffer\n"); return -EINVAL; } if (((uintptr_t)req->resp_buf < data->client.user_virt_sb_base) || ((uintptr_t)req->resp_buf >= Loading @@ -1871,27 +1861,62 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data, pr_err("response buffer address not within shared bufffer\n"); return -EINVAL; } 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 response buffer length not valid\n"); if ((req->cmd_req_len == 0) || (req->cmd_req_len > data->client.sb_length) || (req->resp_len > data->client.sb_length)) { pr_err("cmd buf length or response buf length not valid\n"); return -EINVAL; } if (req->cmd_req_len > UINT_MAX - req->resp_len) { pr_err("Integer overflow detected in req_len & rsp_len, exiting now\n"); pr_err("Integer overflow detected in req_len & rsp_len\n"); return -EINVAL; } reqd_len_sb_in = req->cmd_req_len + req->resp_len; if (reqd_len_sb_in > data->client.sb_length) { if ((req->cmd_req_len + req->resp_len) > data->client.sb_length) { pr_debug("Not enough memory to fit cmd_buf.\n"); pr_debug("resp_buf. Required: %u, Available: %zu\n", reqd_len_sb_in, data->client.sb_length); (req->cmd_req_len + req->resp_len), data->client.sb_length); return -ENOMEM; } if ((uintptr_t)req->cmd_req_buf > (ULONG_MAX - req->cmd_req_len)) { pr_err("Integer overflow in req_len & cmd_req_buf\n"); return -EINVAL; } if ((uintptr_t)req->resp_buf > (ULONG_MAX - req->resp_len)) { pr_err("Integer overflow in resp_len & resp_buf\n"); return -EINVAL; } if (data->client.user_virt_sb_base > (ULONG_MAX - data->client.sb_length)) { pr_err("Integer overflow in user_virt_sb_base & sb_length\n"); return -EINVAL; } if ((((uintptr_t)req->cmd_req_buf + req->cmd_req_len) > ((uintptr_t)data->client.user_virt_sb_base + data->client.sb_length)) || (((uintptr_t)req->resp_buf + req->resp_len) > ((uintptr_t)data->client.user_virt_sb_base + data->client.sb_length))) { pr_err("cmd buf or resp buf is out of shared buffer region\n"); return -EINVAL; } return 0; } static int __qseecom_send_cmd(struct qseecom_dev_handle *data, struct qseecom_send_cmd_req *req) { int ret = 0; u32 reqd_len_sb_in = 0; struct qseecom_client_send_data_ireq send_data_req; struct qseecom_command_scm_resp resp; unsigned long flags; struct qseecom_registered_app_list *ptr_app; bool found_app = false; int name_len = 0; reqd_len_sb_in = req->cmd_req_len + req->resp_len; /* find app_id & img_name from list */ spin_lock_irqsave(&qseecom.registered_app_list_lock, flags); list_for_each_entry(ptr_app, &qseecom.registered_app_list_head, Loading Loading @@ -1965,6 +1990,10 @@ static int qseecom_send_cmd(struct qseecom_dev_handle *data, void __user *argp) pr_err("copy_from_user failed\n"); return ret; } if (__validate_send_cmd_inputs(data, &req)) return -EINVAL; ret = __qseecom_send_cmd(data, &req); if (ret) Loading @@ -1973,50 +2002,54 @@ static int qseecom_send_cmd(struct qseecom_dev_handle *data, void __user *argp) return ret; } int boundary_checks_offset(struct qseecom_send_modfd_cmd_req *req, int __boundary_checks_offset(struct qseecom_send_modfd_cmd_req *req, struct qseecom_send_modfd_listener_resp *lstnr_resp, struct qseecom_dev_handle *data, bool qteec, int i) { int ret = 0; if ((data->type != QSEECOM_LISTENER_SERVICE) && (req->ifd_data[i].fd > 0)) { if (qteec) { if (req->ifd_data[i].cmd_buf_offset > req->cmd_req_len - TWO * sizeof(uint32_t)) { pr_err("Invalid offset 0x%x\n", if ((req->cmd_req_len < (TWO * sizeof(uint32_t))) || (req->ifd_data[i].cmd_buf_offset > req->cmd_req_len - (TWO * sizeof(uint32_t)))) { pr_err("Invalid offset (QTEEC req len) 0x%x\n", req->ifd_data[i].cmd_buf_offset); return ++ret; return -EINVAL; } } else { if (req->ifd_data[i].cmd_buf_offset > req->cmd_req_len - sizeof(uint32_t)) { pr_err("Invalid offset 0x%x\n", if ((req->cmd_req_len < sizeof(uint32_t)) || (req->ifd_data[i].cmd_buf_offset > req->cmd_req_len - sizeof(uint32_t))) { pr_err("Invalid offset (req len) 0x%x\n", req->ifd_data[i].cmd_buf_offset); return ++ret; return -EINVAL; } } } else if ((data->type == QSEECOM_LISTENER_SERVICE) && (lstnr_resp->ifd_data[i].fd > 0)) { if (qteec) { if (lstnr_resp->ifd_data[i].cmd_buf_offset > lstnr_resp->resp_len - TWO * sizeof(uint32_t)) { pr_err("Invalid offset 0x%x\n", if ((lstnr_resp->resp_len < TWO * sizeof(uint32_t)) || (lstnr_resp->ifd_data[i].cmd_buf_offset > lstnr_resp->resp_len - TWO*sizeof(uint32_t))) { pr_err("Invalid offset (QTEEC resp len) 0x%x\n", lstnr_resp->ifd_data[i].cmd_buf_offset); return ++ret; return -EINVAL; } } else { if (lstnr_resp->ifd_data[i].cmd_buf_offset > lstnr_resp->resp_len - sizeof(uint32_t)) { pr_err("Invalid offset 0x%x\n", if ((lstnr_resp->resp_len < sizeof(uint32_t)) || (lstnr_resp->ifd_data[i].cmd_buf_offset > lstnr_resp->resp_len - sizeof(uint32_t))) { pr_err("Invalid offset (lstnr resp len) 0x%x\n", lstnr_resp->ifd_data[i].cmd_buf_offset); return ++ret; return -EINVAL; } } } return ret; return 0; } #define SG_ENTRY_SZ sizeof(struct qseecom_sg_entry) static int __qseecom_update_cmd_buf(void *msg, bool cleanup, struct qseecom_dev_handle *data, bool qteec) { Loading Loading @@ -2095,7 +2128,7 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup, uint32_t *update; update = (uint32_t *) field; if (boundary_checks_offset(req, lstnr_resp, data, if (__boundary_checks_offset(req, lstnr_resp, data, qteec, i)) goto err; if (cleanup) Loading @@ -2112,22 +2145,25 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup, if ((data->type != QSEECOM_LISTENER_SERVICE) && (req->ifd_data[i].fd > 0)) { if (req->ifd_data[i].cmd_buf_offset > req->cmd_req_len - sizeof(struct qseecom_sg_entry)) { if ((req->cmd_req_len < SG_ENTRY_SZ * sg_ptr->nents) || (req->ifd_data[i].cmd_buf_offset > (req->cmd_req_len - SG_ENTRY_SZ * sg_ptr->nents))) { pr_err("Invalid offset = 0x%x\n", req->ifd_data[i]. cmd_buf_offset); req->ifd_data[i].cmd_buf_offset); goto err; } } else if ((data->type == QSEECOM_LISTENER_SERVICE) && (lstnr_resp->ifd_data[i].fd > 0)) { if (lstnr_resp->ifd_data[i].cmd_buf_offset > lstnr_resp->resp_len - sizeof(struct qseecom_sg_entry)) { pr_err("Invalid offset = 0x%x\n", lstnr_resp->ifd_data[i]. cmd_buf_offset); if ((lstnr_resp->resp_len < SG_ENTRY_SZ * sg_ptr->nents) || (lstnr_resp->ifd_data[i].cmd_buf_offset > (lstnr_resp->resp_len - SG_ENTRY_SZ * sg_ptr->nents))) { goto err; } } Loading Loading @@ -2179,37 +2215,14 @@ static int qseecom_send_modfd_cmd(struct qseecom_dev_handle *data, 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 (((uintptr_t)req.cmd_req_buf < data->client.user_virt_sb_base) || ((uintptr_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 (((uintptr_t)req.resp_buf < data->client.user_virt_sb_base) || ((uintptr_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.cmd_req_len > data->client.sb_length || req.resp_len > data->client.sb_length) { pr_err("cmd or response buffer length not valid\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; send_cmd_req.resp_len = req.resp_len; if (__validate_send_cmd_inputs(data, &send_cmd_req)) return -EINVAL; /* validate offsets */ for (i = 0; i < MAX_ION_FD; i++) { if (req.ifd_data[i].cmd_buf_offset >= req.cmd_req_len) { Loading Loading @@ -2897,6 +2910,9 @@ int qseecom_send_command(struct qseecom_handle *handle, void *send_buf, req.cmd_req_buf = send_buf; req.resp_buf = resp_buf; if (__validate_send_cmd_inputs(data, &req)) return -EINVAL; mutex_lock(&app_access_lock); atomic_inc(&data->ioctl_count); if (qseecom.support_bus_scaling) { Loading Loading @@ -4111,6 +4127,19 @@ static int qseecom_save_partition_hash(void __user *argp) static int __qseecom_qteec_validate_msg(struct qseecom_dev_handle *data, struct qseecom_qteec_req *req) { if (req->req_len > UINT_MAX - req->resp_len) { pr_err("Integer overflow detected in req_len & rsp_len\n"); return -EINVAL; } if (req->req_len + req->resp_len > data->client.sb_length) { pr_debug("Not enough memory to fit cmd_buf.\n"); pr_debug("resp_buf. Required: %u, Available: %zu\n", (req->req_len + req->resp_len), data->client.sb_length); return -ENOMEM; } if (req->req_ptr == NULL || req->resp_ptr == NULL) { pr_err("cmd buffer or response buffer is null\n"); return -EINVAL; Loading @@ -4131,15 +4160,33 @@ static int __qseecom_qteec_validate_msg(struct qseecom_dev_handle *data, return -EINVAL; } if ((req->req_len == 0) || (req->resp_len == 0) || req->req_len > data->client.sb_length || req->resp_len > data->client.sb_length) { if ((req->req_len == 0) || (req->resp_len == 0)) { pr_err("cmd buf lengtgh/response buf length not valid\n"); return -EINVAL; } if (req->req_len > UINT_MAX - req->resp_len) { pr_err("Integer overflow detected in req_len/rsp_len, exit\n"); if ((uintptr_t)req->req_ptr > (ULONG_MAX - req->req_len)) { pr_err("Integer overflow in req_len & req_ptr\n"); return -EINVAL; } if ((uintptr_t)req->resp_ptr > (ULONG_MAX - req->resp_len)) { pr_err("Integer overflow in resp_len & resp_ptr\n"); return -EINVAL; } if (data->client.user_virt_sb_base > (ULONG_MAX - data->client.sb_length)) { pr_err("Integer overflow in user_virt_sb_base & sb_length\n"); return -EINVAL; } if ((((uintptr_t)req->req_ptr + req->req_len) > ((uintptr_t)data->client.user_virt_sb_base + data->client.sb_length)) || (((uintptr_t)req->resp_ptr + req->resp_len) > ((uintptr_t)data->client.user_virt_sb_base + data->client.sb_length))) { pr_err("cmd buf or resp buf is out of shared buffer region\n"); return -EINVAL; } return 0; Loading Loading
drivers/misc/qseecom.c +134 −87 Original line number Diff line number Diff line Loading @@ -981,7 +981,7 @@ static int qseecom_scale_bus_bandwidth(struct qseecom_dev_handle *data, } if (req_mode > HIGH) { pr_err("Invalid bandwidth mode (%d)\n", req_mode); return ret; return -EINVAL; } /* Loading Loading @@ -1834,24 +1834,16 @@ exit: return ret; } static int __qseecom_send_cmd(struct qseecom_dev_handle *data, static int __validate_send_cmd_inputs(struct qseecom_dev_handle *data, struct qseecom_send_cmd_req *req) { int ret = 0; u32 reqd_len_sb_in = 0; struct qseecom_client_send_data_ireq send_data_req; struct qseecom_command_scm_resp resp; unsigned long flags; struct qseecom_registered_app_list *ptr_app; bool found_app = false; int name_len = 0; { if (!data || !data->client.ihandle) { pr_err("Client or client handle is not initialized\n"); return -EINVAL; } if (req->cmd_req_buf == NULL || req->resp_buf == NULL) { if (((req->resp_buf == NULL) && (req->resp_len != 0)) || (req->cmd_req_buf == NULL)) { pr_err("cmd buffer or response buffer is null\n"); return -EINVAL; } Loading @@ -1862,8 +1854,6 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data, pr_err("cmd buffer address not within shared bufffer\n"); return -EINVAL; } if (((uintptr_t)req->resp_buf < data->client.user_virt_sb_base) || ((uintptr_t)req->resp_buf >= Loading @@ -1871,27 +1861,62 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data, pr_err("response buffer address not within shared bufffer\n"); return -EINVAL; } 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 response buffer length not valid\n"); if ((req->cmd_req_len == 0) || (req->cmd_req_len > data->client.sb_length) || (req->resp_len > data->client.sb_length)) { pr_err("cmd buf length or response buf length not valid\n"); return -EINVAL; } if (req->cmd_req_len > UINT_MAX - req->resp_len) { pr_err("Integer overflow detected in req_len & rsp_len, exiting now\n"); pr_err("Integer overflow detected in req_len & rsp_len\n"); return -EINVAL; } reqd_len_sb_in = req->cmd_req_len + req->resp_len; if (reqd_len_sb_in > data->client.sb_length) { if ((req->cmd_req_len + req->resp_len) > data->client.sb_length) { pr_debug("Not enough memory to fit cmd_buf.\n"); pr_debug("resp_buf. Required: %u, Available: %zu\n", reqd_len_sb_in, data->client.sb_length); (req->cmd_req_len + req->resp_len), data->client.sb_length); return -ENOMEM; } if ((uintptr_t)req->cmd_req_buf > (ULONG_MAX - req->cmd_req_len)) { pr_err("Integer overflow in req_len & cmd_req_buf\n"); return -EINVAL; } if ((uintptr_t)req->resp_buf > (ULONG_MAX - req->resp_len)) { pr_err("Integer overflow in resp_len & resp_buf\n"); return -EINVAL; } if (data->client.user_virt_sb_base > (ULONG_MAX - data->client.sb_length)) { pr_err("Integer overflow in user_virt_sb_base & sb_length\n"); return -EINVAL; } if ((((uintptr_t)req->cmd_req_buf + req->cmd_req_len) > ((uintptr_t)data->client.user_virt_sb_base + data->client.sb_length)) || (((uintptr_t)req->resp_buf + req->resp_len) > ((uintptr_t)data->client.user_virt_sb_base + data->client.sb_length))) { pr_err("cmd buf or resp buf is out of shared buffer region\n"); return -EINVAL; } return 0; } static int __qseecom_send_cmd(struct qseecom_dev_handle *data, struct qseecom_send_cmd_req *req) { int ret = 0; u32 reqd_len_sb_in = 0; struct qseecom_client_send_data_ireq send_data_req; struct qseecom_command_scm_resp resp; unsigned long flags; struct qseecom_registered_app_list *ptr_app; bool found_app = false; int name_len = 0; reqd_len_sb_in = req->cmd_req_len + req->resp_len; /* find app_id & img_name from list */ spin_lock_irqsave(&qseecom.registered_app_list_lock, flags); list_for_each_entry(ptr_app, &qseecom.registered_app_list_head, Loading Loading @@ -1965,6 +1990,10 @@ static int qseecom_send_cmd(struct qseecom_dev_handle *data, void __user *argp) pr_err("copy_from_user failed\n"); return ret; } if (__validate_send_cmd_inputs(data, &req)) return -EINVAL; ret = __qseecom_send_cmd(data, &req); if (ret) Loading @@ -1973,50 +2002,54 @@ static int qseecom_send_cmd(struct qseecom_dev_handle *data, void __user *argp) return ret; } int boundary_checks_offset(struct qseecom_send_modfd_cmd_req *req, int __boundary_checks_offset(struct qseecom_send_modfd_cmd_req *req, struct qseecom_send_modfd_listener_resp *lstnr_resp, struct qseecom_dev_handle *data, bool qteec, int i) { int ret = 0; if ((data->type != QSEECOM_LISTENER_SERVICE) && (req->ifd_data[i].fd > 0)) { if (qteec) { if (req->ifd_data[i].cmd_buf_offset > req->cmd_req_len - TWO * sizeof(uint32_t)) { pr_err("Invalid offset 0x%x\n", if ((req->cmd_req_len < (TWO * sizeof(uint32_t))) || (req->ifd_data[i].cmd_buf_offset > req->cmd_req_len - (TWO * sizeof(uint32_t)))) { pr_err("Invalid offset (QTEEC req len) 0x%x\n", req->ifd_data[i].cmd_buf_offset); return ++ret; return -EINVAL; } } else { if (req->ifd_data[i].cmd_buf_offset > req->cmd_req_len - sizeof(uint32_t)) { pr_err("Invalid offset 0x%x\n", if ((req->cmd_req_len < sizeof(uint32_t)) || (req->ifd_data[i].cmd_buf_offset > req->cmd_req_len - sizeof(uint32_t))) { pr_err("Invalid offset (req len) 0x%x\n", req->ifd_data[i].cmd_buf_offset); return ++ret; return -EINVAL; } } } else if ((data->type == QSEECOM_LISTENER_SERVICE) && (lstnr_resp->ifd_data[i].fd > 0)) { if (qteec) { if (lstnr_resp->ifd_data[i].cmd_buf_offset > lstnr_resp->resp_len - TWO * sizeof(uint32_t)) { pr_err("Invalid offset 0x%x\n", if ((lstnr_resp->resp_len < TWO * sizeof(uint32_t)) || (lstnr_resp->ifd_data[i].cmd_buf_offset > lstnr_resp->resp_len - TWO*sizeof(uint32_t))) { pr_err("Invalid offset (QTEEC resp len) 0x%x\n", lstnr_resp->ifd_data[i].cmd_buf_offset); return ++ret; return -EINVAL; } } else { if (lstnr_resp->ifd_data[i].cmd_buf_offset > lstnr_resp->resp_len - sizeof(uint32_t)) { pr_err("Invalid offset 0x%x\n", if ((lstnr_resp->resp_len < sizeof(uint32_t)) || (lstnr_resp->ifd_data[i].cmd_buf_offset > lstnr_resp->resp_len - sizeof(uint32_t))) { pr_err("Invalid offset (lstnr resp len) 0x%x\n", lstnr_resp->ifd_data[i].cmd_buf_offset); return ++ret; return -EINVAL; } } } return ret; return 0; } #define SG_ENTRY_SZ sizeof(struct qseecom_sg_entry) static int __qseecom_update_cmd_buf(void *msg, bool cleanup, struct qseecom_dev_handle *data, bool qteec) { Loading Loading @@ -2095,7 +2128,7 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup, uint32_t *update; update = (uint32_t *) field; if (boundary_checks_offset(req, lstnr_resp, data, if (__boundary_checks_offset(req, lstnr_resp, data, qteec, i)) goto err; if (cleanup) Loading @@ -2112,22 +2145,25 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup, if ((data->type != QSEECOM_LISTENER_SERVICE) && (req->ifd_data[i].fd > 0)) { if (req->ifd_data[i].cmd_buf_offset > req->cmd_req_len - sizeof(struct qseecom_sg_entry)) { if ((req->cmd_req_len < SG_ENTRY_SZ * sg_ptr->nents) || (req->ifd_data[i].cmd_buf_offset > (req->cmd_req_len - SG_ENTRY_SZ * sg_ptr->nents))) { pr_err("Invalid offset = 0x%x\n", req->ifd_data[i]. cmd_buf_offset); req->ifd_data[i].cmd_buf_offset); goto err; } } else if ((data->type == QSEECOM_LISTENER_SERVICE) && (lstnr_resp->ifd_data[i].fd > 0)) { if (lstnr_resp->ifd_data[i].cmd_buf_offset > lstnr_resp->resp_len - sizeof(struct qseecom_sg_entry)) { pr_err("Invalid offset = 0x%x\n", lstnr_resp->ifd_data[i]. cmd_buf_offset); if ((lstnr_resp->resp_len < SG_ENTRY_SZ * sg_ptr->nents) || (lstnr_resp->ifd_data[i].cmd_buf_offset > (lstnr_resp->resp_len - SG_ENTRY_SZ * sg_ptr->nents))) { goto err; } } Loading Loading @@ -2179,37 +2215,14 @@ static int qseecom_send_modfd_cmd(struct qseecom_dev_handle *data, 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 (((uintptr_t)req.cmd_req_buf < data->client.user_virt_sb_base) || ((uintptr_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 (((uintptr_t)req.resp_buf < data->client.user_virt_sb_base) || ((uintptr_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.cmd_req_len > data->client.sb_length || req.resp_len > data->client.sb_length) { pr_err("cmd or response buffer length not valid\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; send_cmd_req.resp_len = req.resp_len; if (__validate_send_cmd_inputs(data, &send_cmd_req)) return -EINVAL; /* validate offsets */ for (i = 0; i < MAX_ION_FD; i++) { if (req.ifd_data[i].cmd_buf_offset >= req.cmd_req_len) { Loading Loading @@ -2897,6 +2910,9 @@ int qseecom_send_command(struct qseecom_handle *handle, void *send_buf, req.cmd_req_buf = send_buf; req.resp_buf = resp_buf; if (__validate_send_cmd_inputs(data, &req)) return -EINVAL; mutex_lock(&app_access_lock); atomic_inc(&data->ioctl_count); if (qseecom.support_bus_scaling) { Loading Loading @@ -4111,6 +4127,19 @@ static int qseecom_save_partition_hash(void __user *argp) static int __qseecom_qteec_validate_msg(struct qseecom_dev_handle *data, struct qseecom_qteec_req *req) { if (req->req_len > UINT_MAX - req->resp_len) { pr_err("Integer overflow detected in req_len & rsp_len\n"); return -EINVAL; } if (req->req_len + req->resp_len > data->client.sb_length) { pr_debug("Not enough memory to fit cmd_buf.\n"); pr_debug("resp_buf. Required: %u, Available: %zu\n", (req->req_len + req->resp_len), data->client.sb_length); return -ENOMEM; } if (req->req_ptr == NULL || req->resp_ptr == NULL) { pr_err("cmd buffer or response buffer is null\n"); return -EINVAL; Loading @@ -4131,15 +4160,33 @@ static int __qseecom_qteec_validate_msg(struct qseecom_dev_handle *data, return -EINVAL; } if ((req->req_len == 0) || (req->resp_len == 0) || req->req_len > data->client.sb_length || req->resp_len > data->client.sb_length) { if ((req->req_len == 0) || (req->resp_len == 0)) { pr_err("cmd buf lengtgh/response buf length not valid\n"); return -EINVAL; } if (req->req_len > UINT_MAX - req->resp_len) { pr_err("Integer overflow detected in req_len/rsp_len, exit\n"); if ((uintptr_t)req->req_ptr > (ULONG_MAX - req->req_len)) { pr_err("Integer overflow in req_len & req_ptr\n"); return -EINVAL; } if ((uintptr_t)req->resp_ptr > (ULONG_MAX - req->resp_len)) { pr_err("Integer overflow in resp_len & resp_ptr\n"); return -EINVAL; } if (data->client.user_virt_sb_base > (ULONG_MAX - data->client.sb_length)) { pr_err("Integer overflow in user_virt_sb_base & sb_length\n"); return -EINVAL; } if ((((uintptr_t)req->req_ptr + req->req_len) > ((uintptr_t)data->client.user_virt_sb_base + data->client.sb_length)) || (((uintptr_t)req->resp_ptr + req->resp_len) > ((uintptr_t)data->client.user_virt_sb_base + data->client.sb_length))) { pr_err("cmd buf or resp buf is out of shared buffer region\n"); return -EINVAL; } return 0; Loading