diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2018-09-27 22:27:41 -0700 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2018-09-27 22:27:40 -0700 |
commit | c89dfb7831a5967754ed1ad802cea7b1766b809b (patch) | |
tree | 9e9049180d40abf3250720ad23aa125008d0e608 | |
parent | 478951b2268a21b8d6b44b02e66a989ff9cbebb6 (diff) | |
parent | 5fabfc8cad1f02f9c3051c321ee21dae11a617ff (diff) |
Merge "diag: Prevent out of bound access while initializing msg mask"LE.UM.2.3.7-06300-sda845.0LE.UM.2.3.7-06200-sda845.0
-rw-r--r-- | drivers/char/diag/diag_masks.c | 107 | ||||
-rw-r--r-- | drivers/char/diag/diag_masks.h | 7 | ||||
-rw-r--r-- | drivers/char/diag/diagchar.h | 1 | ||||
-rw-r--r-- | drivers/char/diag/diagchar_core.c | 13 | ||||
-rw-r--r-- | drivers/char/diag/diagfwd_cntl.c | 4 |
5 files changed, 100 insertions, 32 deletions
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c index 44cf56cd8921..7be5a06f7f82 100644 --- a/drivers/char/diag/diag_masks.c +++ b/drivers/char/diag/diag_masks.c @@ -169,6 +169,9 @@ static void diag_send_log_mask_update(uint8_t peripheral, int equip_id) mutex_lock(&mask_info->lock); for (i = 0; i < MAX_EQUIP_ID; i++, mask++) { + if (!mask->ptr) + continue; + if (equip_id != i && equip_id != ALL_EQUIP_ID) continue; @@ -333,12 +336,13 @@ static void diag_send_msg_mask_update(uint8_t peripheral, int first, int last) int header_len = sizeof(struct diag_ctrl_msg_mask); uint8_t *buf = NULL, *temp = NULL; uint8_t upd = 0; - uint8_t msg_mask_tbl_count_local; + uint8_t msg_mask_tbl_count_local = 0; uint32_t mask_size = 0, pd_mask = 0; struct diag_mask_info *mask_info = NULL; struct diag_msg_mask_t *mask = NULL; struct diag_ctrl_msg_mask header; struct diagfwd_info *fwd_info = NULL; + struct diag_md_session_t *md_session_info = NULL; if (peripheral >= NUM_PERIPHERALS) return; @@ -354,14 +358,19 @@ static void diag_send_msg_mask_update(uint8_t peripheral, int first, int last) if (driver->md_session_mask != 0) { if (driver->md_session_mask & MD_PERIPHERAL_MASK(peripheral)) { - if (driver->md_session_map[peripheral]) + if (driver->md_session_map[peripheral]) { mask_info = driver->md_session_map[peripheral]->msg_mask; + md_session_info = + driver->md_session_map[peripheral]; + } } else if (driver->md_session_mask & pd_mask) { upd = diag_mask_to_pd_value(driver->md_session_mask); - if (upd && driver->md_session_map[upd]) + if (upd && driver->md_session_map[upd]) { mask_info = driver->md_session_map[upd]->msg_mask; + md_session_info = driver->md_session_map[upd]; + } } else { DIAG_LOG(DIAG_DEBUG_MASKS, "asking for mask update with unknown session mask\n"); @@ -380,7 +389,10 @@ static void diag_send_msg_mask_update(uint8_t peripheral, int first, int last) return; } buf = mask_info->update_buf; - msg_mask_tbl_count_local = driver->msg_mask_tbl_count; + if (md_session_info) + msg_mask_tbl_count_local = md_session_info->msg_mask_tbl_count; + else + msg_mask_tbl_count_local = driver->msg_mask_tbl_count; mutex_unlock(&driver->msg_mask_lock); mutex_lock(&mask_info->lock); switch (mask_info->status) { @@ -399,6 +411,8 @@ static void diag_send_msg_mask_update(uint8_t peripheral, int first, int last) } for (i = 0; i < msg_mask_tbl_count_local; i++, mask++) { + if (!mask->ptr) + continue; mutex_lock(&driver->msg_mask_lock); if (((mask->ssid_first > first) || (mask->ssid_last_tools < last)) && first != ALL_SSID) { @@ -560,6 +574,7 @@ static int diag_cmd_get_ssid_range(unsigned char *src_buf, int src_len, { int i; int write_len = 0; + uint8_t msg_mask_tbl_count = 0; struct diag_msg_mask_t *mask_ptr = NULL; struct diag_msg_ssid_query_t rsp; struct diag_ssid_range_t ssid_range; @@ -589,15 +604,17 @@ static int diag_cmd_get_ssid_range(unsigned char *src_buf, int src_len, return 0; } mutex_lock(&driver->msg_mask_lock); + msg_mask_tbl_count = (info) ? info->msg_mask_tbl_count : + driver->msg_mask_tbl_count; rsp.cmd_code = DIAG_CMD_MSG_CONFIG; rsp.sub_cmd = DIAG_CMD_OP_GET_SSID_RANGE; rsp.status = MSG_STATUS_SUCCESS; rsp.padding = 0; - rsp.count = driver->msg_mask_tbl_count; + rsp.count = msg_mask_tbl_count; memcpy(dest_buf, &rsp, sizeof(rsp)); write_len += sizeof(rsp); mask_ptr = (struct diag_msg_mask_t *)mask_info->ptr; - for (i = 0; i < driver->msg_mask_tbl_count; i++, mask_ptr++) { + for (i = 0; i < msg_mask_tbl_count; i++, mask_ptr++) { if (write_len + sizeof(ssid_range) > dest_len) { pr_err("diag: In %s, Truncating response due to size limitations of rsp buffer\n", __func__); @@ -642,6 +659,8 @@ static int diag_cmd_get_build_mask(unsigned char *src_buf, int src_len, rsp.padding = 0; build_mask = (struct diag_msg_mask_t *)msg_bt_mask.ptr; for (i = 0; i < driver->bt_msg_mask_tbl_count; i++, build_mask++) { + if (!build_mask->ptr) + continue; if (build_mask->ssid_first != req->ssid_first) continue; num_entries = req->ssid_last - req->ssid_first + 1; @@ -672,6 +691,7 @@ static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len, int i; int write_len = 0; uint32_t mask_size = 0; + uint8_t msg_mask_tbl_count = 0; struct diag_msg_mask_t *mask = NULL; struct diag_build_mask_req_t *req = NULL; struct diag_msg_build_mask_t rsp; @@ -702,6 +722,8 @@ static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len, } mutex_lock(&driver->msg_mask_lock); + msg_mask_tbl_count = (info) ? info->msg_mask_tbl_count : + driver->msg_mask_tbl_count; req = (struct diag_build_mask_req_t *)src_buf; rsp.cmd_code = DIAG_CMD_MSG_CONFIG; rsp.sub_cmd = DIAG_CMD_OP_GET_MSG_MASK; @@ -717,7 +739,9 @@ static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len, mutex_unlock(&driver->md_session_lock); return -EINVAL; } - for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) { + for (i = 0; i < msg_mask_tbl_count; i++, mask++) { + if (!mask->ptr) + continue; if ((req->ssid_first < mask->ssid_first) || (req->ssid_first > mask->ssid_last_tools)) { continue; @@ -751,6 +775,7 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len, struct diag_mask_info *mask_info = NULL; struct diag_msg_mask_t *mask_next = NULL; struct diag_md_session_t *info = NULL; + uint8_t msg_mask_tbl_count = 0; mutex_lock(&driver->md_session_lock); info = diag_md_session_get_pid(pid); @@ -783,8 +808,12 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len, mutex_unlock(&driver->md_session_lock); return -EINVAL; } - for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) { - if (i < (driver->msg_mask_tbl_count - 1)) { + msg_mask_tbl_count = (info) ? info->msg_mask_tbl_count : + driver->msg_mask_tbl_count; + for (i = 0; i < msg_mask_tbl_count; i++, mask++) { + if (!mask->ptr) + continue; + if (i < (msg_mask_tbl_count - 1)) { mask_next = mask; mask_next++; } else @@ -894,6 +923,7 @@ static int diag_cmd_set_all_msg_mask(unsigned char *src_buf, int src_len, struct diag_msg_mask_t *mask = NULL; struct diag_mask_info *mask_info = NULL; struct diag_md_session_t *info = NULL; + uint8_t msg_mask_tbl_count = 0; mutex_lock(&driver->md_session_lock); info = diag_md_session_get_pid(pid); @@ -928,9 +958,11 @@ static int diag_cmd_set_all_msg_mask(unsigned char *src_buf, int src_len, mutex_unlock(&driver->md_session_lock); return -EINVAL; } + msg_mask_tbl_count = (info) ? info->msg_mask_tbl_count : + driver->msg_mask_tbl_count; mask_info->status = (req->rt_mask) ? DIAG_CTRL_MASK_ALL_ENABLED : DIAG_CTRL_MASK_ALL_DISABLED; - for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) { + for (i = 0; i < msg_mask_tbl_count; i++, mask++) { if (mask && mask->ptr) { mutex_lock(&mask->lock); memset(mask->ptr, req->rt_mask, @@ -1551,7 +1583,8 @@ static int diag_create_msg_mask_table(void) mutex_lock(&msg_mask.lock); mutex_lock(&driver->msg_mask_lock); driver->msg_mask_tbl_count = MSG_MASK_TBL_CNT; - for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) { + for (i = 0; (i < driver->msg_mask_tbl_count) && mask; + i++, mask++) { range.ssid_first = msg_mask_tbl[i].ssid_first; range.ssid_last = msg_mask_tbl[i].ssid_last; err = diag_create_msg_mask_table_entry(mask, &range); @@ -1575,7 +1608,8 @@ static int diag_create_build_time_mask(void) mutex_lock(&driver->msg_mask_lock); driver->bt_msg_mask_tbl_count = MSG_MASK_TBL_CNT; build_mask = (struct diag_msg_mask_t *)msg_bt_mask.ptr; - for (i = 0; i < driver->bt_msg_mask_tbl_count; i++, build_mask++) { + for (i = 0; (i < driver->bt_msg_mask_tbl_count) && build_mask; + i++, build_mask++) { range.ssid_first = msg_mask_tbl[i].ssid_first; range.ssid_last = msg_mask_tbl[i].ssid_last; err = diag_create_msg_mask_table_entry(build_mask, &range); @@ -1698,7 +1732,7 @@ static int diag_create_log_mask_table(void) mutex_lock(&log_mask.lock); mask = (struct diag_log_mask_t *)(log_mask.ptr); - for (i = 0; i < MAX_EQUIP_ID; i++, mask++) { + for (i = 0; (i < MAX_EQUIP_ID) && mask; i++, mask++) { mask->equip_id = i; mask->num_items = LOG_GET_ITEM_NUM(log_code_last_tbl[i]); mask->num_items_tools = mask->num_items; @@ -1742,7 +1776,6 @@ static int __diag_mask_init(struct diag_mask_info *mask_info, int mask_len, } kmemleak_not_leak(mask_info->update_buf); } - mutex_init(&mask_info->lock); return 0; } @@ -1765,9 +1798,10 @@ int diag_log_mask_copy(struct diag_mask_info *dest, struct diag_mask_info *src) struct diag_log_mask_t *src_mask = NULL; struct diag_log_mask_t *dest_mask = NULL; - if (!src) + if (!src || !dest) return -EINVAL; + mutex_init(&dest->lock); err = __diag_mask_init(dest, LOG_MASK_SIZE, APPS_BUF_SIZE); if (err) return err; @@ -1829,9 +1863,11 @@ static int diag_msg_mask_init(void) { int err = 0, i; + mutex_init(&msg_mask.lock); err = __diag_mask_init(&msg_mask, MSG_MASK_SIZE, APPS_BUF_SIZE); if (err) return err; + err = diag_create_msg_mask_table(); if (err) { pr_err("diag: Unable to create msg masks, err: %d\n", err); @@ -1846,7 +1882,8 @@ static int diag_msg_mask_init(void) return 0; } -int diag_msg_mask_copy(struct diag_mask_info *dest, struct diag_mask_info *src) +int diag_msg_mask_copy(struct diag_md_session_t *new_session, + struct diag_mask_info *dest, struct diag_mask_info *src) { int i, err = 0, mask_size = 0; struct diag_msg_mask_t *src_mask = NULL; @@ -1856,17 +1893,25 @@ int diag_msg_mask_copy(struct diag_mask_info *dest, struct diag_mask_info *src) if (!src || !dest) return -EINVAL; - err = __diag_mask_init(dest, MSG_MASK_SIZE, APPS_BUF_SIZE); - if (err) - return err; + mutex_init(&dest->lock); mutex_lock(&dest->lock); mutex_lock(&driver->msg_mask_lock); + new_session->msg_mask_tbl_count = + driver->msg_mask_tbl_count; + err = __diag_mask_init(dest, + (new_session->msg_mask_tbl_count * + sizeof(struct diag_msg_mask_t)), APPS_BUF_SIZE); + if (err) { + mutex_unlock(&driver->msg_mask_lock); + mutex_unlock(&dest->lock); + return err; + } src_mask = (struct diag_msg_mask_t *)src->ptr; dest_mask = (struct diag_msg_mask_t *)dest->ptr; dest->mask_len = src->mask_len; dest->status = src->status; - for (i = 0; i < driver->msg_mask_tbl_count; i++) { + for (i = 0; i < new_session->msg_mask_tbl_count; i++) { range.ssid_first = src_mask->ssid_first; range.ssid_last = src_mask->ssid_last; err = diag_create_msg_mask_table_entry(dest_mask, &range); @@ -1885,10 +1930,12 @@ int diag_msg_mask_copy(struct diag_mask_info *dest, struct diag_mask_info *src) return err; } -void diag_msg_mask_free(struct diag_mask_info *mask_info) +void diag_msg_mask_free(struct diag_mask_info *mask_info, + struct diag_md_session_t *session_info) { int i; struct diag_msg_mask_t *mask = NULL; + uint8_t msg_mask_tbl_count = 0; if (!mask_info || !mask_info->ptr) return; @@ -1902,7 +1949,10 @@ void diag_msg_mask_free(struct diag_mask_info *mask_info) mutex_unlock(&mask_info->lock); return; } - for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) { + msg_mask_tbl_count = (session_info) ? + session_info->msg_mask_tbl_count : + driver->msg_mask_tbl_count; + for (i = 0; i < msg_mask_tbl_count; i++, mask++) { kfree(mask->ptr); mask->ptr = NULL; } @@ -1933,6 +1983,7 @@ static int diag_build_time_mask_init(void) int err = 0; /* There is no need for update buffer for Build Time masks */ + mutex_init(&msg_bt_mask.lock); err = __diag_mask_init(&msg_bt_mask, MSG_MASK_SIZE, 0); if (err) return err; @@ -1965,6 +2016,7 @@ static int diag_log_mask_init(void) { int err = 0, i; + mutex_init(&log_mask.lock); err = __diag_mask_init(&log_mask, LOG_MASK_SIZE, APPS_BUF_SIZE); if (err) return err; @@ -1998,6 +2050,7 @@ static int diag_event_mask_init(void) { int err = 0, i; + mutex_init(&event_mask.lock); err = __diag_mask_init(&event_mask, EVENT_MASK_SIZE, APPS_BUF_SIZE); if (err) return err; @@ -2019,6 +2072,7 @@ int diag_event_mask_copy(struct diag_mask_info *dest, if (!src || !dest) return -EINVAL; + mutex_init(&dest->lock); err = __diag_mask_init(dest, EVENT_MASK_SIZE, APPS_BUF_SIZE); if (err) return err; @@ -2055,6 +2109,7 @@ int diag_copy_to_user_msg_mask(char __user *buf, size_t count, struct diag_mask_info *mask_info = NULL; struct diag_msg_mask_t *mask = NULL; unsigned char *ptr = NULL; + uint8_t msg_mask_tbl_count = 0; if (!buf || count == 0) return -EINVAL; @@ -2079,7 +2134,11 @@ int diag_copy_to_user_msg_mask(char __user *buf, size_t count, mutex_unlock(&mask_info->lock); return -EINVAL; } - for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) { + msg_mask_tbl_count = (info) ? info->msg_mask_tbl_count : + driver->msg_mask_tbl_count; + for (i = 0; i < msg_mask_tbl_count; i++, mask++) { + if (!mask->ptr) + continue; ptr = mask_info->update_buf; len = 0; mutex_lock(&mask->lock); @@ -2151,6 +2210,8 @@ int diag_copy_to_user_log_mask(char __user *buf, size_t count, return -EINVAL; } for (i = 0; i < MAX_EQUIP_ID; i++, mask++) { + if (!mask->ptr) + continue; ptr = mask_info->update_buf; len = 0; mutex_lock(&mask->lock); diff --git a/drivers/char/diag/diag_masks.h b/drivers/char/diag/diag_masks.h index 6edeee954d74..a736ff269e8d 100644 --- a/drivers/char/diag/diag_masks.h +++ b/drivers/char/diag/diag_masks.h @@ -160,12 +160,13 @@ int diag_masks_init(void); void diag_masks_exit(void); int diag_log_mask_copy(struct diag_mask_info *dest, struct diag_mask_info *src); -int diag_msg_mask_copy(struct diag_mask_info *dest, - struct diag_mask_info *src); +int diag_msg_mask_copy(struct diag_md_session_t *new_session, + struct diag_mask_info *dest, struct diag_mask_info *src); int diag_event_mask_copy(struct diag_mask_info *dest, struct diag_mask_info *src); void diag_log_mask_free(struct diag_mask_info *mask_info); -void diag_msg_mask_free(struct diag_mask_info *mask_info); +void diag_msg_mask_free(struct diag_mask_info *mask_info, + struct diag_md_session_t *session_info); void diag_event_mask_free(struct diag_mask_info *mask_info); int diag_process_apps_masks(unsigned char *buf, int len, int pid); void diag_send_updates_peripheral(uint8_t peripheral); diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h index 9bbfb82fec13..f63d78c32b6e 100644 --- a/drivers/char/diag/diagchar.h +++ b/drivers/char/diag/diagchar.h @@ -483,6 +483,7 @@ struct diag_md_session_t { int pid; int peripheral_mask; uint8_t hdlc_disabled; + uint8_t msg_mask_tbl_count; struct timer_list hdlc_reset_timer; struct diag_mask_info *msg_mask; struct diag_mask_info *log_mask; diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c index a1692300b0f6..01732bed3095 100644 --- a/drivers/char/diag/diagchar_core.c +++ b/drivers/char/diag/diagchar_core.c @@ -1264,7 +1264,8 @@ static void diag_md_session_exit(void) diag_log_mask_free(session_info->log_mask); kfree(session_info->log_mask); session_info->log_mask = NULL; - diag_msg_mask_free(session_info->msg_mask); + diag_msg_mask_free(session_info->msg_mask, + session_info); kfree(session_info->msg_mask); session_info->msg_mask = NULL; diag_event_mask_free(session_info->event_mask); @@ -1335,7 +1336,9 @@ int diag_md_session_create(int mode, int peripheral_mask, int proc) "return value of event copy. err %d\n", err); goto fail_peripheral; } - err = diag_msg_mask_copy(new_session->msg_mask, &msg_mask); + new_session->msg_mask_tbl_count = 0; + err = diag_msg_mask_copy(new_session, new_session->msg_mask, + &msg_mask); if (err) { DIAG_LOG(DIAG_DEBUG_USERSPACE, "return value of msg copy. err %d\n", err); @@ -1371,7 +1374,8 @@ fail_peripheral: diag_event_mask_free(new_session->event_mask); kfree(new_session->event_mask); new_session->event_mask = NULL; - diag_msg_mask_free(new_session->msg_mask); + diag_msg_mask_free(new_session->msg_mask, + new_session); kfree(new_session->msg_mask); new_session->msg_mask = NULL; kfree(new_session); @@ -1399,7 +1403,8 @@ static void diag_md_session_close(int pid) diag_log_mask_free(session_info->log_mask); kfree(session_info->log_mask); session_info->log_mask = NULL; - diag_msg_mask_free(session_info->msg_mask); + diag_msg_mask_free(session_info->msg_mask, + session_info); kfree(session_info->msg_mask); session_info->msg_mask = NULL; diag_event_mask_free(session_info->event_mask); diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c index ac4394b308ba..a6d5ca8a952a 100644 --- a/drivers/char/diag/diagfwd_cntl.c +++ b/drivers/char/diag/diagfwd_cntl.c @@ -668,7 +668,7 @@ static void process_ssid_range_report(uint8_t *buf, uint32_t len, mask_ptr = (struct diag_msg_mask_t *)msg_mask.ptr; found = 0; for (j = 0; j < driver->msg_mask_tbl_count; j++, mask_ptr++) { - if (!mask_ptr || !ssid_range) { + if (!mask_ptr->ptr || !ssid_range) { found = 1; break; } @@ -747,7 +747,7 @@ static void diag_build_time_mask_update(uint8_t *buf, num_items = range->ssid_last - range->ssid_first + 1; for (i = 0; i < driver->bt_msg_mask_tbl_count; i++, build_mask++) { - if (!build_mask) { + if (!build_mask->ptr) { found = 1; break; } |