summaryrefslogtreecommitdiff
path: root/drivers/char
diff options
context:
space:
mode:
authorManoj Prabhu B <bmanoj@codeaurora.org>2019-05-01 22:11:18 +0530
committerManoj Prabhu B <bmanoj@codeaurora.org>2019-05-08 14:12:28 +0530
commit061ce1d939fa47a9532035dab39d6ec5a6c90f58 (patch)
tree5138a435c2fe4508511a3cd8cbc54b310ce47894 /drivers/char
parentf175c863efb474a4b2908f0867fac6eb5ceaf589 (diff)
diag: Validate command length against size of command structure
While processing a packet containing command request, buffer size need to be checked against size of the command structures that is being parsed to prevent possible out of bound access. CRs-Fixed: 2432633 Change-Id: I048bdbd0c096a6d03501bdd5b1d2d4bb50d45dd6 Signed-off-by: Manoj Prabhu B <bmanoj@codeaurora.org>
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/diag/diagfwd.c79
1 files changed, 50 insertions, 29 deletions
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index ff024c2200c0..8e9a6d7acafa 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2019, 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
@@ -952,7 +952,7 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
struct diag_cmd_reg_t *reg_item = NULL;
struct diag_md_session_t *info = NULL;
- if (!buf)
+ if (!buf || len <= 0)
return -EIO;
/* Check if the command is a supported mask command */
@@ -963,18 +963,31 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
}
temp = buf;
- entry.cmd_code = (uint16_t)(*(uint8_t *)temp);
- temp += sizeof(uint8_t);
- entry.subsys_id = (uint16_t)(*(uint8_t *)temp);
- temp += sizeof(uint8_t);
- entry.cmd_code_hi = (uint16_t)(*(uint16_t *)temp);
- entry.cmd_code_lo = (uint16_t)(*(uint16_t *)temp);
- temp += sizeof(uint16_t);
-
- pr_debug("diag: In %s, received cmd %02x %02x %02x\n",
- __func__, entry.cmd_code, entry.subsys_id, entry.cmd_code_hi);
-
- if (*buf == DIAG_CMD_LOG_ON_DMND && driver->log_on_demand_support &&
+ if (len >= sizeof(uint8_t)) {
+ entry.cmd_code = (uint16_t)(*(uint8_t *)temp);
+ pr_debug("diag: received cmd_code %02x\n", entry.cmd_code);
+ }
+ if (len >= (2 * sizeof(uint8_t))) {
+ temp += sizeof(uint8_t);
+ entry.subsys_id = (uint16_t)(*(uint8_t *)temp);
+ pr_debug("diag: received subsys_id %02x\n", entry.subsys_id);
+ }
+ if (len == (3 * sizeof(uint8_t))) {
+ temp += sizeof(uint8_t);
+ entry.cmd_code_hi = (uint16_t)(*(uint8_t *)temp);
+ entry.cmd_code_lo = (uint16_t)(*(uint8_t *)temp);
+ pr_debug("diag: received cmd_code_hi %02x\n",
+ entry.cmd_code_hi);
+ } else if (len >= (2 * sizeof(uint8_t)) + sizeof(uint16_t)) {
+ temp += sizeof(uint8_t);
+ entry.cmd_code_hi = (uint16_t)(*(uint16_t *)temp);
+ entry.cmd_code_lo = (uint16_t)(*(uint16_t *)temp);
+ pr_debug("diag: received cmd_code_hi %02x\n",
+ entry.cmd_code_hi);
+ }
+
+ if ((len >= sizeof(uint8_t)) && *buf == DIAG_CMD_LOG_ON_DMND &&
+ driver->log_on_demand_support &&
driver->feature[PERIPHERAL_MODEM].rcvd_feature_mask) {
write_len = diag_cmd_log_on_demand(buf, len,
driver->apps_rsp_buf,
@@ -1014,14 +1027,16 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
#if defined(CONFIG_DIAG_OVER_USB)
/* Check for the command/respond msg for the maximum packet length */
- if ((*buf == 0x4b) && (*(buf+1) == 0x12) &&
+ if ((len >= (4 * sizeof(uint8_t))) &&
+ (*buf == 0x4b) && (*(buf+1) == 0x12) &&
(*(uint16_t *)(buf+2) == 0x0055)) {
for (i = 0; i < 4; i++)
*(driver->apps_rsp_buf+i) = *(buf+i);
*(uint32_t *)(driver->apps_rsp_buf+4) = DIAG_MAX_REQ_SIZE;
diag_send_rsp(driver->apps_rsp_buf, 8, pid);
return 0;
- } else if ((*buf == 0x4b) && (*(buf+1) == 0x12) &&
+ } else if ((len >= ((2 * sizeof(uint8_t)) + sizeof(uint16_t))) &&
+ (*buf == 0x4b) && (*(buf+1) == 0x12) &&
(*(uint16_t *)(buf+2) == DIAG_DIAG_STM)) {
len = diag_process_stm_cmd(buf, driver->apps_rsp_buf);
if (len > 0) {
@@ -1031,7 +1046,8 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
return len;
}
/* Check for time sync query command */
- else if ((*buf == DIAG_CMD_DIAG_SUBSYS) &&
+ else if ((len >= ((2 * sizeof(uint8_t)) + sizeof(uint16_t))) &&
+ (*buf == DIAG_CMD_DIAG_SUBSYS) &&
(*(buf+1) == DIAG_SS_DIAG) &&
(*(uint16_t *)(buf+2) == DIAG_GET_TIME_API)) {
write_len = diag_process_time_sync_query_cmd(buf, len,
@@ -1042,7 +1058,8 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
return 0;
}
/* Check for time sync switch command */
- else if ((*buf == DIAG_CMD_DIAG_SUBSYS) &&
+ else if ((len >= ((2 * sizeof(uint8_t)) + sizeof(uint16_t))) &&
+ (*buf == DIAG_CMD_DIAG_SUBSYS) &&
(*(buf+1) == DIAG_SS_DIAG) &&
(*(uint16_t *)(buf+2) == DIAG_SET_TIME_API)) {
write_len = diag_process_time_sync_switch_cmd(buf, len,
@@ -1053,7 +1070,8 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
return 0;
}
/* Check for download command */
- else if ((chk_apps_master()) && (*buf == 0x3A)) {
+ else if ((len >= sizeof(uint8_t)) && (chk_apps_master()) &&
+ (*buf == 0x3A)) {
/* send response back */
driver->apps_rsp_buf[0] = *buf;
diag_send_rsp(driver->apps_rsp_buf, 1, pid);
@@ -1066,8 +1084,8 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
return 0;
}
/* Check for polling for Apps only DIAG */
- else if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
- (*(buf+2) == 0x03)) {
+ else if ((len >= (3 * sizeof(uint8_t))) &&
+ (*buf == 0x4b) && (*(buf+1) == 0x32) && (*(buf+2) == 0x03)) {
/* If no one has registered for polling */
if (chk_polling_response()) {
/* Respond to polling for Apps only DIAG */
@@ -1081,7 +1099,8 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
}
}
/* Return the Delayed Response Wrap Status */
- else if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
+ else if ((len >= (4 * sizeof(uint8_t))) &&
+ (*buf == 0x4b) && (*(buf+1) == 0x32) &&
(*(buf+2) == 0x04) && (*(buf+3) == 0x0)) {
memcpy(driver->apps_rsp_buf, buf, 4);
driver->apps_rsp_buf[4] = wrap_enabled;
@@ -1089,7 +1108,8 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
return 0;
}
/* Wrap the Delayed Rsp ID */
- else if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
+ else if ((len >= (4 * sizeof(uint8_t))) &&
+ (*buf == 0x4b) && (*(buf+1) == 0x32) &&
(*(buf+2) == 0x05) && (*(buf+3) == 0x0)) {
wrap_enabled = true;
memcpy(driver->apps_rsp_buf, buf, 4);
@@ -1098,10 +1118,11 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
return 0;
}
/* Mobile ID Rsp */
- else if ((*buf == DIAG_CMD_DIAG_SUBSYS) &&
- (*(buf+1) == DIAG_SS_PARAMS) &&
- (*(buf+2) == DIAG_EXT_MOBILE_ID) && (*(buf+3) == 0x0)) {
- write_len = diag_cmd_get_mobile_id(buf, len,
+ else if ((len >= (4 * sizeof(uint8_t))) &&
+ (*buf == DIAG_CMD_DIAG_SUBSYS) &&
+ (*(buf+1) == DIAG_SS_PARAMS) &&
+ (*(buf+2) == DIAG_EXT_MOBILE_ID) && (*(buf+3) == 0x0)) {
+ write_len = diag_cmd_get_mobile_id(buf, len,
driver->apps_rsp_buf,
DIAG_MAX_RSP_SIZE);
if (write_len > 0) {
@@ -1121,7 +1142,7 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
!(driver->diagfwd_cntl[PERIPHERAL_MODEM]->ch_open) &&
!(driver->feature[PERIPHERAL_MODEM].rcvd_feature_mask)) {
/* respond to 0x0 command */
- if (*buf == 0x00) {
+ if ((len >= sizeof(uint8_t)) && *buf == 0x00) {
for (i = 0; i < 55; i++)
driver->apps_rsp_buf[i] = 0;
@@ -1129,7 +1150,7 @@ int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
return 0;
}
/* respond to 0x7c command */
- else if (*buf == 0x7c) {
+ else if ((len >= sizeof(uint8_t)) && *buf == 0x7c) {
driver->apps_rsp_buf[0] = 0x7c;
for (i = 1; i < 8; i++)
driver->apps_rsp_buf[i] = 0;