qseecom: Added boundary checks between two subsequent fields
Checking 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: Nitin LNU <nlakra@codeaurora.org>
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index d173fc7..e0386cbc 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -3569,53 +3569,60 @@
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) {
-
- if ((data->type != QSEECOM_LISTENER_SERVICE) &&
- (req->ifd_data[i].fd > 0)) {
- 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 -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)
+ 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(uint64_t)) ||
+ if ((req->cmd_req_len < size) ||
(req->ifd_data[i].cmd_buf_offset >
- req->cmd_req_len - sizeof(uint64_t))) {
+ req->cmd_req_len - size)) {
pr_err("Invalid offset (req len) 0x%x\n",
req->ifd_data[i].cmd_buf_offset);
return -EINVAL;
}
+
+ curr_field = (char *) (req->cmd_req_buf +
+ req->ifd_data[i].cmd_buf_offset);
+ 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;
}
@@ -3698,8 +3705,10 @@
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)) ||
@@ -3730,30 +3739,10 @@
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)) ||
@@ -3979,9 +3968,10 @@
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 :
@@ -3991,30 +3981,9 @@
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++) {