summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVignesh Viswanathan <viswanat@codeaurora.org>2017-09-28 14:49:00 +0530
committersnandini <snandini@codeaurora.org>2017-10-06 14:15:42 -0700
commit9dfdd6d96e58c10b53db7c162dadcbf329270e24 (patch)
tree0f3af07aa7b83645c73cddf5da96602e808f7270
parent9464a453629950474af92c36b1cf449f6f9094f8 (diff)
qcacld-3.0: Fix potential buffer overwrite in wma_roam_synch_event_handler
In the function wma_roam_synch_event_handler, vdev_id is received from the fw and is used to access member of the array wma->interfaces without validating the max of the vdev_id received from the fw Add check to make sure vdev_id is less than max_bssid before using it Change-Id: I3b940e183ab66680891cb7351af4537b50afce1d CRs-Fixed: 2114187
-rw-r--r--core/wma/src/wma_scan_roam.c51
1 files changed, 36 insertions, 15 deletions
diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c
index b11c81d9a5fe..811afea2a449 100644
--- a/core/wma/src/wma_scan_roam.c
+++ b/core/wma/src/wma_scan_roam.c
@@ -2596,6 +2596,7 @@ int wma_roam_synch_event_handler(void *handle, uint8_t *event,
int status = -EINVAL;
tSirRoamOffloadScanReq *roam_req;
qdf_time_t roam_synch_received = qdf_get_system_timestamp();
+ uint32_t roam_synch_data_len;
WMA_LOGD("LFR3:%s", __func__);
if (!event) {
@@ -2615,6 +2616,12 @@ int wma_roam_synch_event_handler(void *handle, uint8_t *event,
goto cleanup_label;
}
+ if (synch_event->vdev_id > wma->max_bssid) {
+ WMA_LOGE("%s: received invalid vdev_id %d",
+ __func__, synch_event->vdev_id);
+ goto cleanup_label;
+ }
+
wma_peer_debug_log(synch_event->vdev_id, DEBUG_ROAM_SYNCH_IND,
DEBUG_INVALID_PEER_ID, NULL, NULL,
synch_event->bssid.mac_addr31to0,
@@ -2635,17 +2642,33 @@ int wma_roam_synch_event_handler(void *handle, uint8_t *event,
* Maximum number during the addition would be (3 * MAX_LIMIT(UINT32) +
* few fixed fields).
*/
- if (sizeof(*synch_event) + synch_event->bcn_probe_rsp_len +
- synch_event->reassoc_rsp_len +
- synch_event->reassoc_req_len +
- sizeof(wmi_channel) + sizeof(wmi_key_material) +
- sizeof(uint32_t) > WMI_SVC_MSG_MAX_SIZE) {
- WMA_LOGE("excess synch payload: LEN bcn:%d, req:%d, rsp:%d",
- synch_event->bcn_probe_rsp_len,
- synch_event->reassoc_req_len,
- synch_event->reassoc_rsp_len);
+ WMA_LOGD("synch payload: LEN bcn:%d, req:%d, rsp:%d",
+ synch_event->bcn_probe_rsp_len,
+ synch_event->reassoc_req_len,
+ synch_event->reassoc_rsp_len);
+ if (synch_event->bcn_probe_rsp_len > WMI_SVC_MSG_MAX_SIZE)
goto cleanup_label;
- }
+ if (synch_event->reassoc_rsp_len >
+ (WMI_SVC_MSG_MAX_SIZE - synch_event->bcn_probe_rsp_len))
+ goto cleanup_label;
+ if (synch_event->reassoc_req_len >
+ WMI_SVC_MSG_MAX_SIZE - (synch_event->bcn_probe_rsp_len +
+ synch_event->reassoc_rsp_len))
+ goto cleanup_label;
+ roam_synch_data_len = synch_event->bcn_probe_rsp_len +
+ synch_event->reassoc_rsp_len + synch_event->reassoc_req_len;
+ /*
+ * Below is the check for the entire size of the message received from'
+ * the firmware.
+ */
+ if (roam_synch_data_len > WMI_SVC_MSG_MAX_SIZE -
+ (sizeof(*synch_event) + sizeof(wmi_channel) +
+ sizeof(wmi_key_material) + sizeof(uint32_t)))
+ goto cleanup_label;
+ if (sizeof(roam_offload_synch_ind) >
+ (WMI_SVC_MSG_MAX_SIZE - roam_synch_data_len))
+ goto cleanup_label;
+ roam_synch_data_len += sizeof(roam_offload_synch_ind);
cds_host_diag_log_work(&wma->roam_ho_wl,
WMA_ROAM_HO_WAKE_LOCK_DURATION,
@@ -2654,10 +2677,8 @@ int wma_roam_synch_event_handler(void *handle, uint8_t *event,
WMA_ROAM_HO_WAKE_LOCK_DURATION);
wma->interfaces[synch_event->vdev_id].roam_synch_in_progress = true;
- len = sizeof(roam_offload_synch_ind) +
- synch_event->bcn_probe_rsp_len + synch_event->reassoc_rsp_len +
- synch_event->reassoc_req_len;
- roam_synch_ind_ptr = (roam_offload_synch_ind *)qdf_mem_malloc(len);
+ roam_synch_ind_ptr =
+ (roam_offload_synch_ind *)qdf_mem_malloc(roam_synch_data_len);
if (!roam_synch_ind_ptr) {
WMA_LOGE("%s: failed to allocate memory for roam_synch_event",
__func__);
@@ -2665,7 +2686,7 @@ int wma_roam_synch_event_handler(void *handle, uint8_t *event,
status = -ENOMEM;
goto cleanup_label;
}
- qdf_mem_zero(roam_synch_ind_ptr, len);
+ qdf_mem_zero(roam_synch_ind_ptr, roam_synch_data_len);
status = wma_fill_roam_synch_buffer(wma,
roam_synch_ind_ptr, param_buf);
if (status != 0)