Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit edc0db63 authored by Nitin LNU's avatar Nitin LNU
Browse files

qseecom: Add boundary checks between two subsequent fields



Check if there is enough room in between the offset of the
two subsequent field so that data of field 2 will not overlap
the data of field 1.

Change-Id: I96f656bb25878a302e7de109dd8f981045ed52e7
Signed-off-by: default avatarNitin LNU <nlakra@codeaurora.org>
parent 6cb02c40
Loading
Loading
Loading
Loading
+47 −79
Original line number Original line Diff line number Diff line
@@ -3839,54 +3839,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,
int __boundary_checks_offset(struct qseecom_send_modfd_cmd_req *req,
			struct qseecom_send_modfd_listener_resp *lstnr_resp,
			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) &&
	if ((data->type != QSEECOM_LISTENER_SERVICE) &&
						(req->ifd_data[i].fd > 0)) {
						(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->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",
			pr_err("Invalid offset (req len) 0x%x\n",
				req->ifd_data[i].cmd_buf_offset);
				req->ifd_data[i].cmd_buf_offset);
			return -EINVAL;
			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,
		curr_field = (char *) (req->cmd_req_buf +
			struct qseecom_send_modfd_listener_resp *lstnr_resp,
				req->ifd_data[i].cmd_buf_offset);
			struct qseecom_dev_handle *data, int i)
		for (j = 0; j < MAX_ION_FD; j++) {
{
			if ((req->ifd_data[j].fd > 0) && i != j) {

				temp_field = (char *) (req->cmd_req_buf +
	if ((data->type != QSEECOM_LISTENER_SERVICE) &&
					req->ifd_data[j].cmd_buf_offset);
						(req->ifd_data[i].fd > 0)) {
				if (temp_field >= curr_field && temp_field <
		if ((req->cmd_req_len < sizeof(uint64_t)) ||
					(curr_field + size)) {
			(req->ifd_data[i].cmd_buf_offset >
					pr_err("Invalid field offset 0x%x\n",
			req->cmd_req_len - sizeof(uint64_t))) {
			pr_err("Invalid offset (req len) 0x%x\n",
					req->ifd_data[i].cmd_buf_offset);
					req->ifd_data[i].cmd_buf_offset);
					return -EINVAL;
					return -EINVAL;
				}
				}
			}
		}
	} else if ((data->type == QSEECOM_LISTENER_SERVICE) &&
	} else if ((data->type == QSEECOM_LISTENER_SERVICE) &&
					(lstnr_resp->ifd_data[i].fd > 0)) {
					(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->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",
			pr_err("Invalid offset (lstnr resp len) 0x%x\n",
				lstnr_resp->ifd_data[i].cmd_buf_offset);
				lstnr_resp->ifd_data[i].cmd_buf_offset);
			return -EINVAL;
			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;
	return 0;
}
}
@@ -3961,8 +3967,10 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup,
		if (sg_ptr->nents == 1) {
		if (sg_ptr->nents == 1) {
			uint32_t *update;
			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;
				goto err;

			if ((data->type == QSEECOM_CLIENT_APP &&
			if ((data->type == QSEECOM_CLIENT_APP &&
				(data->client.app_arch == ELFCLASS32 ||
				(data->client.app_arch == ELFCLASS32 ||
				data->client.app_arch == ELFCLASS64)) ||
				data->client.app_arch == ELFCLASS64)) ||
@@ -3993,30 +4001,10 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup,
			struct qseecom_sg_entry *update;
			struct qseecom_sg_entry *update;
			int j = 0;
			int j = 0;


			if ((data->type != QSEECOM_LISTENER_SERVICE) &&
			if (__boundary_checks_offset(req, lstnr_resp, data, i,
					(req->ifd_data[i].fd > 0)) {
				(SG_ENTRY_SZ * sg_ptr->nents)))

				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;
				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 &&
			if ((data->type == QSEECOM_CLIENT_APP &&
				(data->client.app_arch == ELFCLASS32 ||
				(data->client.app_arch == ELFCLASS32 ||
				data->client.app_arch == ELFCLASS64)) ||
				data->client.app_arch == ELFCLASS64)) ||
@@ -4236,9 +4224,10 @@ static int __qseecom_update_cmd_buf_64(void *msg, bool cleanup,
		if (sg_ptr->nents == 1) {
		if (sg_ptr->nents == 1) {
			uint64_t *update_64bit;
			uint64_t *update_64bit;


			if (__boundary_checks_offset_64(req, lstnr_resp,
			if (__boundary_checks_offset(req, lstnr_resp, data, i,
							data, i))
				sizeof(uint64_t)))
				goto err;
				goto err;

				/* 64bit app uses 64bit address */
				/* 64bit app uses 64bit address */
			update_64bit = (uint64_t *) field;
			update_64bit = (uint64_t *) field;
			*update_64bit = cleanup ? 0 :
			*update_64bit = cleanup ? 0 :
@@ -4248,30 +4237,9 @@ static int __qseecom_update_cmd_buf_64(void *msg, bool cleanup,
			struct qseecom_sg_entry_64bit *update_64bit;
			struct qseecom_sg_entry_64bit *update_64bit;
			int j = 0;
			int j = 0;


			if ((data->type != QSEECOM_LISTENER_SERVICE) &&
			if (__boundary_checks_offset(req, lstnr_resp, data, i,
					(req->ifd_data[i].fd > 0)) {
				(SG_ENTRY_SZ_64BIT * sg_ptr->nents)))

				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;
				goto err;
				}
			}
			/* 64bit app uses 64bit address */
			/* 64bit app uses 64bit address */
			update_64bit = (struct qseecom_sg_entry_64bit *)field;
			update_64bit = (struct qseecom_sg_entry_64bit *)field;
			for (j = 0; j < sg_ptr->nents; j++) {
			for (j = 0; j < sg_ptr->nents; j++) {