From 4f75cf5ea51e1854c463f4525c5e22e0b86aae40 Mon Sep 17 00:00:00 2001 From: Vignesh Viswanathan Date: Wed, 29 Nov 2017 14:19:13 +0530 Subject: [PATCH] qcacld-3.0: Fix buffer overread in wma_extscan_cached_results_event_handler In function wma_extscan_cached_results_event_handler, event->num_entries_in_page is received from the FW and is used in the function wma_extscan_find_unique_scan_ids to calculate scan_ids_cnt from src_rssi buffer. If the value of num_entries_in_page is greater than the number of src_rssi buffers present, a buffer overread would occur in the function wma_extscan_find_unique_scan_ids. There is already a check in place to valudate num_entries_in_page in the function wma_extscan_cached_results_event_handler however it is done after the call of wma_extscan_find_unique_scan_ids. Move the checks on num_entries_in_page before using it in the function wma_extscan_cached_results_event_handler Change-Id: Ib5e803589deb6ca074cb70326b9ce846d0754a73 CRs-Fixed: 2149720 --- core/wma/src/wma_scan_roam.c | 86 ++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index d13f97f6c69e..fd9e53530ae0 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/core/wma/src/wma_scan_roam.c @@ -4516,7 +4516,7 @@ int wma_extscan_cached_results_event_handler(void *handle, struct extscan_cached_scan_results empty_cachelist; wmi_extscan_wlan_descriptor *src_hotlist; wmi_extscan_rssi_info *src_rssi; - int numap, i, moredata, scan_ids_cnt, buf_len; + int i, moredata, scan_ids_cnt, buf_len; tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE); uint32_t total_len; bool excess_data = false; @@ -4538,14 +4538,52 @@ int wma_extscan_cached_results_event_handler(void *handle, event = param_buf->fixed_param; src_hotlist = param_buf->bssid_list; src_rssi = param_buf->rssi_list; - numap = event->num_entries_in_page; WMA_LOGI("Total_entries: %u first_entry_index: %u num_entries_in_page: %d", event->total_entries, - event->first_entry_index, numap); - if (!src_hotlist || !src_rssi || !numap) { + event->first_entry_index, + event->num_entries_in_page); + + if (!src_hotlist || !src_rssi || !event->num_entries_in_page) { WMA_LOGW("%s: Cached results empty, send 0 results", __func__); goto noresults; } + + if (event->num_entries_in_page > + (WMI_SVC_MSG_MAX_SIZE - sizeof(*event))/sizeof(*src_hotlist)) { + WMA_LOGE("%s:excess num_entries_in_page %d in WMI event", + __func__, + event->num_entries_in_page); + return -EINVAL; + } else { + total_len = sizeof(*event) + + (event->num_entries_in_page * sizeof(*src_hotlist)); + } + for (i = 0; i < event->num_entries_in_page; i++) { + if (src_hotlist[i].ie_length > + WMI_SVC_MSG_MAX_SIZE - total_len) { + excess_data = true; + break; + } else { + total_len += src_hotlist[i].ie_length; + WMA_LOGD("total len IE: %d", total_len); + } + + if (src_hotlist[i].number_rssi_samples > + (WMI_SVC_MSG_MAX_SIZE - total_len) / sizeof(*src_rssi)) { + excess_data = true; + break; + } else { + total_len += (src_hotlist[i].number_rssi_samples * + sizeof(*src_rssi)); + WMA_LOGD("total len RSSI samples: %d", total_len); + } + } + if (excess_data) { + WMA_LOGE("%s:excess data in WMI event", + __func__); + return -EINVAL; + } + if (event->first_entry_index + event->num_entries_in_page < event->total_entries) moredata = 1; @@ -4562,47 +4600,9 @@ int wma_extscan_cached_results_event_handler(void *handle, dest_cachelist->more_data = moredata; scan_ids_cnt = wma_extscan_find_unique_scan_ids(cmd_param_info); - WMA_LOGI("%s: scan_ids_cnt %d", __func__, scan_ids_cnt); + WMA_LOGD("%s: scan_ids_cnt %d", __func__, scan_ids_cnt); dest_cachelist->num_scan_ids = scan_ids_cnt; - if (event->num_entries_in_page > - (WMI_SVC_MSG_MAX_SIZE - sizeof(*event))/sizeof(*src_hotlist)) { - WMA_LOGE("%s:excess num_entries_in_page %d in WMI event", - __func__, event->num_entries_in_page); - qdf_mem_free(dest_cachelist); - QDF_ASSERT(0); - return -EINVAL; - } else { - total_len = sizeof(*event) + - (event->num_entries_in_page * sizeof(*src_hotlist)); - } - for (i = 0; i < event->num_entries_in_page; i++) { - if (src_hotlist[i].ie_length > WMI_SVC_MSG_MAX_SIZE - - total_len) { - excess_data = true; - break; - } else { - total_len += src_hotlist[i].ie_length; - WMA_LOGD("total len IE: %d", total_len); - } - - if (src_hotlist[i].number_rssi_samples > - (WMI_SVC_MSG_MAX_SIZE - total_len)/sizeof(*src_rssi)) { - excess_data = true; - break; - } else { - total_len += (src_hotlist[i].number_rssi_samples * - sizeof(*src_rssi)); - WMA_LOGD("total len RSSI samples: %d", total_len); - } - } - if (excess_data) { - WMA_LOGE("%s:excess data in WMI event", - __func__); - qdf_mem_free(dest_cachelist); - QDF_ASSERT(0); - return -EINVAL; - } buf_len = sizeof(*dest_result) * scan_ids_cnt; dest_cachelist->result = qdf_mem_malloc(buf_len); if (!dest_cachelist->result) {