From fda1af6befa8bbb2fbfcc23d810a427cba4e1ffc Mon Sep 17 00:00:00 2001 From: Pragaspathi Thilagaraj Date: Fri, 9 Mar 2018 15:11:58 +0530 Subject: [PATCH] qcacld-3.0: Fix OOB write in wma_passpoint_match_event_handler In the function wma_passpoint_match_event_handler, fixed param event data from firmware is filled in the destination buffer and indication is sent to upper layers. The buffer allocation is done for the size (wmi_passpoint_event_hdr*) + event->ie_length + event->anqp_length. The maximum firmware event message size is WMI_SVC_MSG_MAX_SIZE. If either, ie_length and anqp_length combined is greater than WMI_SVC_MSG_MAX_SIZE or either of the two exceeds WMI_SVC_MSG_MAC_SIZE, an OOB write will occur in wma_passpoint_match_event_handler. Add check to ensure either of the values ie_length or anqp_lenth or (ie_length + anqp_length) doesnt exceed the WMI_SVC_MAX_SIZE. Return failure if it exceeds. Change-Id: I21f473ca0b99ebb8488f2cca3c0774817ea97c3a CRs-Fixed: 2201190 --- core/wma/src/wma_scan_roam.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index 3f4f97fdb0e0..1641c650d213 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/core/wma/src/wma_scan_roam.c @@ -4259,6 +4259,8 @@ int wma_passpoint_match_event_handler(void *handle, struct wifi_passpoint_match *dest_match; tSirWifiScanResult *dest_ap; uint8_t *buf_ptr; + uint32_t buf_len = 0; + bool excess_data = false; tpAniSirGlobal mac = cds_get_context(QDF_MODULE_ID_PE); if (!mac) { @@ -4278,13 +4280,26 @@ int wma_passpoint_match_event_handler(void *handle, event = param_buf->fixed_param; buf_ptr = (uint8_t *)param_buf->fixed_param; - /* - * All the below lengths are UINT32 and summing up and checking - * against a constant should not be an issue. - */ - if ((sizeof(*event) + event->ie_length + event->anqp_length) > - WMI_SVC_MSG_MAX_SIZE || - (event->ie_length + event->anqp_length) > param_buf->num_bufp) { + do { + if (event->ie_length > (WMI_SVC_MSG_MAX_SIZE)) { + excess_data = true; + break; + } else { + buf_len = event->ie_length; + } + + if (event->anqp_length > (WMI_SVC_MSG_MAX_SIZE)) { + excess_data = true; + break; + } else { + buf_len += event->anqp_length; + } + + } while (0); + + if (excess_data || buf_len > (WMI_SVC_MSG_MAX_SIZE - sizeof(*event)) || + buf_len > (WMI_SVC_MSG_MAX_SIZE - sizeof(*dest_match)) || + (event->ie_length + event->anqp_length) > param_buf->num_bufp) { WMA_LOGE("IE Length: %u or ANQP Length: %u is huge, num_bufp: %u", event->ie_length, event->anqp_length, param_buf->num_bufp); @@ -4297,8 +4312,8 @@ int wma_passpoint_match_event_handler(void *handle, event->ssid.ssid_len = SIR_MAC_MAX_SSID_LENGTH; } - dest_match = qdf_mem_malloc(sizeof(*dest_match) + - event->ie_length + event->anqp_length); + dest_match = qdf_mem_malloc(sizeof(*dest_match) + buf_len); + if (!dest_match) { WMA_LOGE("%s: qdf_mem_malloc failed", __func__); return -EINVAL;