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
This commit is contained in:
Vignesh Viswanathan 2017-11-29 14:19:13 +05:30 • committed by snandini
commit 4f75cf5ea5

View file

@ -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) {