Merge "diag: dci: Validate pkt length before parsing for full header"

This commit is contained in:
Linux Build Service Account 2019-08-13 01:55:13 -07:00 committed by Gerrit - the friendly Code Review server
commit de6dd62c41
1 changed files with 87 additions and 43 deletions

View File

@ -726,29 +726,44 @@ int diag_dci_query_event_mask(struct diag_dci_client_tbl *entry,
return ((*event_mask_ptr & byte_mask) == byte_mask) ? 1 : 0; return ((*event_mask_ptr & byte_mask) == byte_mask) ? 1 : 0;
} }
static int diag_dci_filter_commands(struct diag_pkt_header_t *header) static int diag_dci_filter_commands(struct diag_pkt_header_t *header,
int header_len)
{ {
if (!header) if (!header)
return -ENOMEM; return -ENOMEM;
switch (header->cmd_code) { if (header_len <= 0)
case 0x7d: /* Msg Mask Configuration */ return -EIO;
case 0x73: /* Log Mask Configuration */
case 0x81: /* Event Mask Configuration */ if (header_len) {
case 0x82: /* Event Mask Change */ switch (header->cmd_code) {
case 0x60: /* Event Mask Toggle */ case 0x7d: /* Msg Mask Configuration */
return 1; case 0x73: /* Log Mask Configuration */
case 0x81: /* Event Mask Configuration */
case 0x82: /* Event Mask Change */
case 0x60: /* Event Mask Toggle */
DIAG_LOG(DIAG_DEBUG_DCI,
"diag: command not supported: %d\n",
header->cmd_code);
return 1;
}
} }
if (header->cmd_code == 0x4b && header->subsys_id == 0x12) { if (header_len >= (3*sizeof(uint8_t))) {
switch (header->subsys_cmd_code) { if (header->cmd_code == 0x4b && header->subsys_id == 0x12) {
case 0x60: /* Extended Event Mask Config */ switch (header->subsys_cmd_code) {
case 0x61: /* Extended Msg Mask Config */ case 0x60: /* Extended Event Mask Config */
case 0x62: /* Extended Log Mask Config */ case 0x61: /* Extended Msg Mask Config */
case 0x20C: /* Set current Preset ID */ case 0x62: /* Extended Log Mask Config */
case 0x20D: /* Get current Preset ID */ case 0x20C: /* Set current Preset ID */
case 0x218: /* HDLC Disabled Command */ case 0x20D: /* Get current Preset ID */
return 1; case 0x218: /* HDLC Disabled Command */
DIAG_LOG(DIAG_DEBUG_DCI,
"diag: command not supported %d %d %d\n",
header->cmd_code, header->subsys_id,
header->subsys_cmd_code);
return 1;
}
} }
} }
@ -1800,22 +1815,26 @@ int diag_dci_send_handshake_pkt(int index)
static int diag_dci_process_apps_pkt(struct diag_pkt_header_t *pkt_header, static int diag_dci_process_apps_pkt(struct diag_pkt_header_t *pkt_header,
unsigned char *req_buf, int req_len, unsigned char *req_buf, int req_len,
int tag) int tag, int pkt_header_len)
{ {
uint8_t cmd_code, subsys_id, i, goto_download = 0; uint8_t cmd_code = 0, subsys_id = 0, i, goto_download = 0;
uint8_t header_len = sizeof(struct diag_dci_pkt_header_t); uint8_t header_len = sizeof(struct diag_dci_pkt_header_t);
uint16_t ss_cmd_code; uint16_t ss_cmd_code = 0;
uint32_t write_len = 0; uint32_t write_len = 0;
unsigned char *dest_buf = driver->apps_dci_buf; unsigned char *dest_buf = driver->apps_dci_buf;
unsigned char *payload_ptr = driver->apps_dci_buf + header_len; unsigned char *payload_ptr = driver->apps_dci_buf + header_len;
struct diag_dci_pkt_header_t dci_header; struct diag_dci_pkt_header_t dci_header;
if (!pkt_header || !req_buf || req_len <= 0 || tag < 0) if (!pkt_header || !req_buf || req_len <= 0 || tag < 0 ||
pkt_header_len <= 0)
return -EIO; return -EIO;
cmd_code = pkt_header->cmd_code; if (pkt_header_len >= (sizeof(uint8_t)))
subsys_id = pkt_header->subsys_id; cmd_code = pkt_header->cmd_code;
ss_cmd_code = pkt_header->subsys_cmd_code; if (pkt_header_len >= (2 * sizeof(uint8_t)))
subsys_id = pkt_header->subsys_id;
if (pkt_header_len >= (3 * sizeof(uint8_t)))
ss_cmd_code = pkt_header->subsys_cmd_code;
if (cmd_code == DIAG_CMD_DOWNLOAD) { if (cmd_code == DIAG_CMD_DOWNLOAD) {
*payload_ptr = DIAG_CMD_DOWNLOAD; *payload_ptr = DIAG_CMD_DOWNLOAD;
@ -1935,7 +1954,7 @@ fill_buffer:
static int diag_process_dci_pkt_rsp(unsigned char *buf, int len) static int diag_process_dci_pkt_rsp(unsigned char *buf, int len)
{ {
int ret = DIAG_DCI_TABLE_ERR; int ret = DIAG_DCI_TABLE_ERR;
int common_cmd = 0; int common_cmd = 0, header_len = 0;
struct diag_pkt_header_t *header = NULL; struct diag_pkt_header_t *header = NULL;
unsigned char *temp = buf; unsigned char *temp = buf;
unsigned char *req_buf = NULL; unsigned char *req_buf = NULL;
@ -1951,8 +1970,7 @@ static int diag_process_dci_pkt_rsp(unsigned char *buf, int len)
if (!buf) if (!buf)
return -EIO; return -EIO;
if (len < (sizeof(struct dci_pkt_req_t) + if (len < sizeof(struct dci_pkt_req_t) ||
sizeof(struct diag_pkt_header_t)) ||
len > DCI_REQ_BUF_SIZE) { len > DCI_REQ_BUF_SIZE) {
pr_err("diag: dci: Invalid length %d len in %s", len, __func__); pr_err("diag: dci: Invalid length %d len in %s", len, __func__);
return -EIO; return -EIO;
@ -1963,13 +1981,6 @@ static int diag_process_dci_pkt_rsp(unsigned char *buf, int len)
read_len += sizeof(struct dci_pkt_req_t); read_len += sizeof(struct dci_pkt_req_t);
req_len -= sizeof(struct dci_pkt_req_t); req_len -= sizeof(struct dci_pkt_req_t);
req_buf = temp; /* Start of the Request */ req_buf = temp; /* Start of the Request */
header = (struct diag_pkt_header_t *)temp;
read_len += sizeof(struct diag_pkt_header_t);
if (read_len >= DCI_REQ_BUF_SIZE) {
pr_err("diag: dci: In %s, invalid read_len: %d\n", __func__,
read_len);
return -EIO;
}
mutex_lock(&driver->dci_mutex); mutex_lock(&driver->dci_mutex);
dci_entry = diag_dci_get_client_entry(req_hdr.client_id); dci_entry = diag_dci_get_client_entry(req_hdr.client_id);
@ -1980,11 +1991,40 @@ static int diag_process_dci_pkt_rsp(unsigned char *buf, int len)
return DIAG_DCI_NO_REG; return DIAG_DCI_NO_REG;
} }
header = (void *)temp;
header_len = len - sizeof(struct dci_pkt_req_t);
if (header_len <= 0) {
mutex_unlock(&driver->dci_mutex);
return -EIO;
}
if (header_len >= sizeof(uint8_t)) {
header->cmd_code = (uint16_t)(*(uint8_t *)temp);
read_len += sizeof(uint8_t);
}
if (header_len >= (2 * sizeof(uint8_t))) {
temp += sizeof(uint8_t);
header->subsys_id = (uint16_t)(*(uint8_t *)temp);
read_len += sizeof(uint8_t);
}
if (header_len == (3 * sizeof(uint8_t))) {
temp += sizeof(uint8_t);
header->subsys_cmd_code = (uint16_t)(*(uint8_t *)temp);
read_len += sizeof(uint8_t);
} else if (header_len >=
(2 * sizeof(uint8_t)) + sizeof(uint16_t)) {
temp += sizeof(uint8_t);
header->subsys_cmd_code = (uint16_t)(*(uint16_t *)temp);
read_len += sizeof(uint16_t);
}
if (read_len > DCI_REQ_BUF_SIZE) {
pr_err("diag: dci: In %s, invalid read_len: %d\n", __func__,
read_len);
mutex_unlock(&driver->dci_mutex);
return -EIO;
}
/* Check if the command is allowed on DCI */ /* Check if the command is allowed on DCI */
if (diag_dci_filter_commands(header)) { if (diag_dci_filter_commands(header, header_len)) {
pr_debug("diag: command not supported %d %d %d",
header->cmd_code, header->subsys_id,
header->subsys_cmd_code);
mutex_unlock(&driver->dci_mutex); mutex_unlock(&driver->dci_mutex);
return DIAG_DCI_SEND_DATA_FAIL; return DIAG_DCI_SEND_DATA_FAIL;
} }
@ -2038,14 +2078,18 @@ static int diag_process_dci_pkt_rsp(unsigned char *buf, int len)
/* Check if it is a dedicated Apps command */ /* Check if it is a dedicated Apps command */
ret = diag_dci_process_apps_pkt(header, req_buf, req_len, ret = diag_dci_process_apps_pkt(header, req_buf, req_len,
req_entry->tag); req_entry->tag, header_len);
if ((ret == DIAG_DCI_NO_ERROR && !common_cmd) || ret < 0) if ((ret == DIAG_DCI_NO_ERROR && !common_cmd) || ret < 0)
return ret; return ret;
reg_entry.cmd_code = header->cmd_code; if (header_len >= (sizeof(uint8_t)))
reg_entry.subsys_id = header->subsys_id; reg_entry.cmd_code = header->cmd_code;
reg_entry.cmd_code_hi = header->subsys_cmd_code; if (header_len >= (2 * sizeof(uint8_t)))
reg_entry.cmd_code_lo = header->subsys_cmd_code; reg_entry.subsys_id = header->subsys_id;
if (header_len >= (3 * sizeof(uint8_t))) {
reg_entry.cmd_code_hi = header->subsys_cmd_code;
reg_entry.cmd_code_lo = header->subsys_cmd_code;
}
mutex_lock(&driver->cmd_reg_mutex); mutex_lock(&driver->cmd_reg_mutex);
temp_entry = diag_cmd_search(&reg_entry, ALL_PROC); temp_entry = diag_cmd_search(&reg_entry, ALL_PROC);