diff options
Diffstat (limited to 'drivers/misc/qseecom.c')
-rw-r--r-- | drivers/misc/qseecom.c | 129 |
1 files changed, 49 insertions, 80 deletions
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index 21ad3dc3abaa..9704fc1f767c 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -1,7 +1,7 @@ /* * QTI Secure Execution Environment Communicator (QSEECOM) driver * - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -3542,53 +3542,60 @@ static int qseecom_send_cmd(struct qseecom_dev_handle *data, void __user *argp) int __boundary_checks_offset(struct qseecom_send_modfd_cmd_req *req, struct qseecom_send_modfd_listener_resp *lstnr_resp, - struct qseecom_dev_handle *data, int i) { + struct qseecom_dev_handle *data, int i, size_t size) +{ + char *curr_field = NULL; + char *temp_field = NULL; + int j = 0; if ((data->type != QSEECOM_LISTENER_SERVICE) && (req->ifd_data[i].fd > 0)) { - if ((req->cmd_req_len < sizeof(uint32_t)) || + if ((req->cmd_req_len < size) || (req->ifd_data[i].cmd_buf_offset > - req->cmd_req_len - sizeof(uint32_t))) { + req->cmd_req_len - size)) { pr_err("Invalid offset (req len) 0x%x\n", req->ifd_data[i].cmd_buf_offset); return -EINVAL; } - } else if ((data->type == QSEECOM_LISTENER_SERVICE) && - (lstnr_resp->ifd_data[i].fd > 0)) { - 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 -EINVAL; - } - } - return 0; -} -static int __boundary_checks_offset_64(struct qseecom_send_modfd_cmd_req *req, - struct qseecom_send_modfd_listener_resp *lstnr_resp, - struct qseecom_dev_handle *data, int i) -{ - - if ((data->type != QSEECOM_LISTENER_SERVICE) && - (req->ifd_data[i].fd > 0)) { - if ((req->cmd_req_len < sizeof(uint64_t)) || - (req->ifd_data[i].cmd_buf_offset > - req->cmd_req_len - sizeof(uint64_t))) { - pr_err("Invalid offset (req len) 0x%x\n", + curr_field = (char *) (req->cmd_req_buf + req->ifd_data[i].cmd_buf_offset); - return -EINVAL; + for (j = 0; j < MAX_ION_FD; j++) { + if ((req->ifd_data[j].fd > 0) && i != j) { + temp_field = (char *) (req->cmd_req_buf + + req->ifd_data[j].cmd_buf_offset); + if (temp_field >= curr_field && temp_field < + (curr_field + size)) { + pr_err("Invalid field offset 0x%x\n", + req->ifd_data[i].cmd_buf_offset); + return -EINVAL; + } + } } } else if ((data->type == QSEECOM_LISTENER_SERVICE) && (lstnr_resp->ifd_data[i].fd > 0)) { - if ((lstnr_resp->resp_len < sizeof(uint64_t)) || + if ((lstnr_resp->resp_len < size) || (lstnr_resp->ifd_data[i].cmd_buf_offset > - lstnr_resp->resp_len - sizeof(uint64_t))) { + lstnr_resp->resp_len - size)) { pr_err("Invalid offset (lstnr resp len) 0x%x\n", lstnr_resp->ifd_data[i].cmd_buf_offset); return -EINVAL; } + + curr_field = (char *) (lstnr_resp->resp_buf_ptr + + lstnr_resp->ifd_data[i].cmd_buf_offset); + for (j = 0; j < MAX_ION_FD; j++) { + if ((lstnr_resp->ifd_data[j].fd > 0) && i != j) { + temp_field = (char *) lstnr_resp->resp_buf_ptr + + lstnr_resp->ifd_data[j].cmd_buf_offset; + if (temp_field >= curr_field && temp_field < + (curr_field + size)) { + pr_err("Invalid lstnr field offset 0x%x\n", + lstnr_resp->ifd_data[i].cmd_buf_offset); + return -EINVAL; + } + } + } } return 0; } @@ -3671,8 +3678,10 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup, if (sg_ptr->nents == 1) { uint32_t *update; - if (__boundary_checks_offset(req, lstnr_resp, data, i)) + if (__boundary_checks_offset(req, lstnr_resp, data, i, + sizeof(uint32_t))) goto err; + if ((data->type == QSEECOM_CLIENT_APP && (data->client.app_arch == ELFCLASS32 || data->client.app_arch == ELFCLASS64)) || @@ -3703,30 +3712,10 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup, struct qseecom_sg_entry *update; int j = 0; - if ((data->type != QSEECOM_LISTENER_SERVICE) && - (req->ifd_data[i].fd > 0)) { - - 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); - goto err; - } - - } else if ((data->type == QSEECOM_LISTENER_SERVICE) && - (lstnr_resp->ifd_data[i].fd > 0)) { + if (__boundary_checks_offset(req, lstnr_resp, data, i, + (SG_ENTRY_SZ * sg_ptr->nents))) + goto err; - 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; - } - } if ((data->type == QSEECOM_CLIENT_APP && (data->client.app_arch == ELFCLASS32 || data->client.app_arch == ELFCLASS64)) || @@ -3952,9 +3941,10 @@ static int __qseecom_update_cmd_buf_64(void *msg, bool cleanup, if (sg_ptr->nents == 1) { uint64_t *update_64bit; - if (__boundary_checks_offset_64(req, lstnr_resp, - data, i)) + if (__boundary_checks_offset(req, lstnr_resp, data, i, + sizeof(uint64_t))) goto err; + /* 64bit app uses 64bit address */ update_64bit = (uint64_t *) field; *update_64bit = cleanup ? 0 : @@ -3964,30 +3954,9 @@ static int __qseecom_update_cmd_buf_64(void *msg, bool cleanup, struct qseecom_sg_entry_64bit *update_64bit; int j = 0; - if ((data->type != QSEECOM_LISTENER_SERVICE) && - (req->ifd_data[i].fd > 0)) { - - if ((req->cmd_req_len < - SG_ENTRY_SZ_64BIT * sg_ptr->nents) || - (req->ifd_data[i].cmd_buf_offset > - (req->cmd_req_len - - SG_ENTRY_SZ_64BIT * sg_ptr->nents))) { - pr_err("Invalid offset = 0x%x\n", - 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->resp_len < - SG_ENTRY_SZ_64BIT * sg_ptr->nents) || - (lstnr_resp->ifd_data[i].cmd_buf_offset > - (lstnr_resp->resp_len - - SG_ENTRY_SZ_64BIT * sg_ptr->nents))) { - goto err; - } - } + if (__boundary_checks_offset(req, lstnr_resp, data, i, + (SG_ENTRY_SZ_64BIT * sg_ptr->nents))) + goto err; /* 64bit app uses 64bit address */ update_64bit = (struct qseecom_sg_entry_64bit *)field; for (j = 0; j < sg_ptr->nents; j++) { |