diff options
| author | Vignesh Viswanathan <viswanat@codeaurora.org> | 2017-09-28 14:49:00 +0530 |
|---|---|---|
| committer | snandini <snandini@codeaurora.org> | 2017-10-06 14:15:42 -0700 |
| commit | 9dfdd6d96e58c10b53db7c162dadcbf329270e24 (patch) | |
| tree | 0f3af07aa7b83645c73cddf5da96602e808f7270 | |
| parent | 9464a453629950474af92c36b1cf449f6f9094f8 (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.c | 51 |
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) |
