Merge "qseecom: Added boundary checks between two subsequent fields"

This commit is contained in:
qctecmdr 2021-01-03 17:29:49 -08:00 • committed by Gerrit - the friendly Code Review server
commit 5f5ad727a8

View file

@ -3852,54 +3852,60 @@ static int qseecom_send_cmd(struct qseecom_dev_handle *data, void __user *argp)
static 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;
}
@ -3974,8 +3980,9 @@ 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)) ||
@ -4006,30 +4013,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 (__boundary_checks_offset(req, lstnr_resp, data, i,
(SG_ENTRY_SZ * sg_ptr->nents)))
goto err;
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 ((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)) ||
@ -4248,9 +4235,9 @@ 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 :
@ -4260,30 +4247,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++) {