diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c index 73dd992ae8cd0ac9c2bbfa32f8b975df38a8e7a2..d09aa073ec40b01c8bf2cd4b0dda599292808ff7 100644 --- a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c @@ -3052,6 +3052,13 @@ static int wma_link_status_event_handler(void *handle, u_int8_t *cmd_param_info, } event = param_buf->fixed_param; + if (event->num_vdev_stats > ((WMA_SVC_MSG_MAX_SIZE - + sizeof(*event)) / sizeof(wmi_vdev_rate_ht_info))) { + WMA_LOGE("%s: excess vdev_stats buffers:%d", __func__, + event->num_vdev_stats); + VOS_ASSERT(0); + return -EINVAL; + } buf_size = sizeof(wmi_vdev_rate_stats_event_fixed_param) + sizeof(wmi_vdev_rate_ht_info) * event->num_vdev_stats; buf = vos_mem_malloc(buf_size); @@ -3202,6 +3209,8 @@ static int wma_stats_event_handler(void *handle, u_int8_t *cmd_param_info, vos_msg_t vos_msg = {0}; u_int32_t buf_size, buf_data_size; u_int8_t *buf, *temp; + u_int32_t buf_len = 0; + bool excess_data = false; bool rssi_stats_support = FALSE; param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *)cmd_param_info; @@ -3210,6 +3219,58 @@ static int wma_stats_event_handler(void *handle, u_int8_t *cmd_param_info, return -EINVAL; } event = param_buf->fixed_param; + + do { + if (event->num_pdev_stats > ((WMA_SVC_MSG_MAX_SIZE - + sizeof(*event)) / sizeof(wmi_pdev_stats))) { + excess_data = true; + break; + } else { + buf_len += event->num_pdev_stats * sizeof(wmi_pdev_stats); + } + if (event->num_vdev_stats > ((WMA_SVC_MSG_MAX_SIZE - + sizeof(*event)) / sizeof(wmi_vdev_stats))) { + excess_data = true; + break; + } else { + buf_len += event->num_vdev_stats * sizeof(wmi_vdev_stats); + } + if (event->num_peer_stats > ((WMA_SVC_MSG_MAX_SIZE - + sizeof(*event)) / sizeof(wmi_peer_stats))) { + excess_data = true; + break; + } else { + buf_len += event->num_peer_stats * sizeof(wmi_peer_stats); + } + if (event->num_mib_stats > ((WMA_SVC_MSG_MAX_SIZE - + sizeof(*event)) / sizeof(wmi_mib_stats))) { + excess_data = true; + break; + } else { + buf_len += event->num_mib_stats * sizeof(wmi_mib_stats); + } + rssi_event = + (wmi_per_chain_rssi_stats *) param_buf->chain_stats; + if (rssi_event && (rssi_event->num_per_chain_rssi_stats > + ((WMA_SVC_MSG_MAX_SIZE - sizeof(*event)) / + sizeof(wmi_rssi_stats)))) { + excess_data = true; + break; + } else { + buf_len += rssi_event->num_per_chain_rssi_stats * + sizeof(wmi_rssi_stats); + } + } while (0); + + if (excess_data || + (sizeof(*event) > WMA_SVC_MSG_MAX_SIZE - buf_len)) { + WMA_LOGE("excess wmi buffer: stats pdev %d vdev %d peer %d", + event->num_pdev_stats, event->num_vdev_stats, + event->num_peer_stats); + VOS_ASSERT(0); + return -EINVAL; + } + buf_size = sizeof(*event) + (event->num_pdev_stats * sizeof(wmi_pdev_stats)) + (event->num_vdev_stats * sizeof(wmi_vdev_stats)) + @@ -4228,6 +4289,8 @@ static int wma_extscan_cached_results_event_handler(void *handle, wmi_extscan_rssi_info *src_rssi; int numap, i, moredata, scan_ids_cnt; int buf_len; + u_int32_t total_len; + bool excess_data = false; tpAniSirGlobal pMac = (tpAniSirGlobal )vos_get_context( VOS_MODULE_ID_PE, wma->vos_context); @@ -4276,6 +4339,43 @@ static int wma_extscan_cached_results_event_handler(void *handle, WMA_LOGI("scan_ids_cnt %d", scan_ids_cnt); dest_cachelist->num_scan_ids = scan_ids_cnt; + if (event->num_entries_in_page > + (WMA_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); + vos_mem_free(dest_cachelist); + VOS_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 > WMA_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 > + (WMA_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__); + vos_mem_free(dest_cachelist); + VOS_ASSERT(0); + return -EINVAL; + } + buf_len = sizeof(*dest_result) * scan_ids_cnt; dest_cachelist->result = vos_mem_malloc(buf_len); if (!dest_cachelist->result) { @@ -4328,6 +4428,8 @@ static int wma_extscan_change_results_event_handler(void *handle, int count = 0; int moredata; int rssi_num = 0; + u_int32_t buf_len; + bool excess_data = false; tpAniSirGlobal pMac = (tpAniSirGlobal )vos_get_context( VOS_MODULE_ID_PE, wma->vos_context); if (!pMac) { @@ -4362,6 +4464,30 @@ static int wma_extscan_change_results_event_handler(void *handle, else moredata = 0; + do { + if (event->num_entries_in_page > + (WMA_SVC_MSG_MAX_SIZE - sizeof(*event))/ + sizeof(*src_chglist)) { + excess_data = true; + break; + } else { + buf_len = sizeof(*event) + + (event->num_entries_in_page * + sizeof(*src_chglist)); + } + if (rssi_num > + (WMA_SVC_MSG_MAX_SIZE - buf_len)/sizeof(int32_t)) { + excess_data = true; + break; + } + } while (0); + + if (excess_data) { + WMA_LOGE("buffer len exceeds WMI payload,numap:%d, rssi_num:%d", + numap, rssi_num); + VOS_ASSERT(0); + return -EINVAL; + } dest_chglist = vos_mem_malloc(sizeof(*dest_chglist) + sizeof(*dest_ap) * numap + sizeof(tANI_S32) * rssi_num); @@ -4438,6 +4564,17 @@ static 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) > + WMA_SVC_MSG_MAX_SIZE) { + WMA_LOGE("IE Length: %d or ANQP Length: %d is huge", + event->ie_length, event->anqp_length); + VOS_ASSERT(0); + return -EINVAL; + } dest_match = vos_mem_malloc(sizeof(*dest_match) + event->ie_length + event->anqp_length); if (!dest_match) { @@ -4647,6 +4784,8 @@ static int wma_unified_link_peer_stats_event_handler(void *handle, u_int32_t next_res_offset, next_peer_offset, next_rate_offset; size_t peer_info_size, peer_stats_size, rate_stats_size; size_t link_stats_results_size; + bool excess_data = false; + u_int32_t buf_len; tpAniSirGlobal pMac = (tpAniSirGlobal )vos_get_context(VOS_MODULE_ID_PE, wma_handle->vos_context); @@ -4684,6 +4823,33 @@ static int wma_unified_link_peer_stats_event_handler(void *handle, return -EINVAL; } + do { + if (peer_stats->num_rates > + WMA_SVC_MSG_MAX_SIZE/sizeof(wmi_rate_stats)) { + excess_data = true; + break; + } else { + buf_len = peer_stats->num_rates * + sizeof(wmi_rate_stats); + } + if (fixed_param->num_peers > + WMA_SVC_MSG_MAX_SIZE/sizeof(wmi_peer_link_stats)) { + excess_data = true; + break; + } else { + buf_len += fixed_param->num_peers * + sizeof(wmi_peer_link_stats); + } + } while (0); + + if (excess_data || + (sizeof(*fixed_param) > WMA_SVC_MSG_MAX_SIZE - buf_len)) { + WMA_LOGE("excess wmi buffer: rates:%d, peers:%d", + peer_stats->num_rates, fixed_param->num_peers); + VOS_ASSERT(0); + return -EINVAL; + } + /* * num_rates - sum of the rates of all the peers */ @@ -4829,6 +4995,14 @@ static int wma_unified_radio_tx_power_level_stats_event_handler(void *handle, return -EINVAL; } + if (fixed_param->num_tx_power_levels > ((WMA_SVC_MSG_MAX_SIZE - + sizeof(*fixed_param)) / sizeof(uint32_t))) { + WMA_LOGE("%s: excess tx_power buffers:%d", __func__, + fixed_param->num_tx_power_levels); + VOS_ASSERT(0); + return -EINVAL; + } + rs_results = (tSirWifiRadioStat *) &link_stats_results->results[0]; tx_power_level_values = (uint8 *) param_tlvs->tx_time_per_power_level; @@ -6361,6 +6535,12 @@ static int wma_nan_rsp_event_handler(void *handle, u_int8_t *event_buf, buf_ptr = (u_int8_t *)nan_rsp_event_hdr; alloc_len = sizeof(tSirNanEvent); alloc_len += nan_rsp_event_hdr->data_len; + if (nan_rsp_event_hdr->data_len > ((WMA_SVC_MSG_MAX_SIZE - + sizeof(*nan_rsp_event_hdr)) / sizeof(u_int8_t))) { + WMA_LOGE("excess data length:%d", nan_rsp_event_hdr->data_len); + VOS_ASSERT(0); + return -EINVAL; + } nan_rsp_event = (tSirNanEvent *) vos_mem_malloc(alloc_len); if (NULL == nan_rsp_event) { WMA_LOGE("%s: Memory allocation failure", __func__); @@ -6708,6 +6888,22 @@ static int wma_roam_synch_event_handler(void *handle, u_int8_t *event, u_int32_t __func__); return -EINVAL; } + /* + * All below length fields are unsigned and hence positive numbers. + * 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 + + sizeof(wmi_channel) + sizeof(wmi_key_material) + + sizeof(uint32_t)) > WMA_SVC_MSG_MAX_SIZE) { + WMA_LOGE("excess synch payload: LEN bcn:%d, rsp:%d", + synch_event->bcn_probe_rsp_len, + synch_event->reassoc_rsp_len); + VOS_ASSERT(0); + return -EINVAL; + } + adf_os_spin_lock_bh(&wma->roam_synch_lock); wma->interfaces[synch_event->vdev_id].roam_synch_in_progress = VOS_TRUE; adf_os_spin_unlock_bh(&wma->roam_synch_lock); @@ -7017,6 +7213,13 @@ static int wma_stats_ext_event_handler(void *handle, u_int8_t *event_buf, alloc_len = sizeof(tSirStatsExtEvent); alloc_len += stats_ext_info->data_len; + if (stats_ext_info->data_len > (WMA_SVC_MSG_MAX_SIZE - + sizeof(*stats_ext_info))) { + WMA_LOGE("Excess data_len:%d", stats_ext_info->data_len); + VOS_ASSERT(0); + return -EINVAL; + } + stats_ext_event = (tSirStatsExtEvent *) vos_mem_malloc(alloc_len); if (NULL == stats_ext_event) { WMA_LOGE("%s: Memory allocation failure", __func__); @@ -20751,6 +20954,14 @@ static int wma_log_supported_evt_handler(void *handle, WMA_LOGD("%s: num_of_diag_events_logs=%d", __func__, num_of_diag_events_logs); + if (num_of_diag_events_logs > + (WMA_SVC_MSG_MAX_SIZE / sizeof(uint32_t))) { + WMA_LOGE("%s: excess num of logs:%d", __func__, + num_of_diag_events_logs); + VOS_ASSERT(0); + return -EINVAL; + } + /* Free any previous allocation */ if (wma->events_logs_list) vos_mem_free(wma->events_logs_list); diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.h index b8362c25078f04db5240c1823125d5f6d66ccf21..ce78c324d514c10292658b70b481dc290dd5f43c 100644 --- a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.h +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.h @@ -106,7 +106,7 @@ #define WMA_MAX_VDEV_SIZE 20 #define WMA_VDEV_TBL_ENTRY_ADD 1 #define WMA_VDEV_TBL_ENTRY_DEL 0 - +#define WMA_SVC_MSG_MAX_SIZE 1536 /* 11A/G channel boundary */ #define WMA_11A_CHANNEL_BEGIN 34 diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma_ocb.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma_ocb.c index 2bdfe5102fc7a07b6b75a6467f4dc5f05ca3b6c6..877d082e931ee9a47fff6978b96e410c4990a308 100644 --- a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma_ocb.c +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma_ocb.c @@ -806,6 +806,13 @@ int wma_dcc_get_stats_resp_event_handler(void *handle, uint8_t *event_buf, fix_param = param_tlvs->fixed_param; /* Allocate and populate the response */ + if (fix_param->num_channels > ((WMA_SVC_MSG_MAX_SIZE - + sizeof(*fix_param)) / sizeof(wmi_dcc_ndl_stats_per_channel))) { + WMA_LOGE("%s: too many channels:%d", __func__, + fix_param->num_channels); + VOS_ASSERT(0); + return -EINVAL; + } response = vos_mem_malloc(sizeof(*response) + fix_param->num_channels * sizeof(wmi_dcc_ndl_stats_per_channel)); if (response == NULL) @@ -1051,6 +1058,13 @@ int wma_dcc_stats_event_handler(void *handle, uint8_t *event_buf, param_tlvs = (WMI_DCC_STATS_EVENTID_param_tlvs *)event_buf; fix_param = param_tlvs->fixed_param; /* Allocate and populate the response */ + if (fix_param->num_channels > ((WMA_SVC_MSG_MAX_SIZE - + sizeof(*fix_param)) / sizeof(wmi_dcc_ndl_stats_per_channel))) { + WMA_LOGE("%s: too many channels:%d", __func__, + fix_param->num_channels); + VOS_ASSERT(0); + return -EINVAL; + } response = vos_mem_malloc(sizeof(*response) + fix_param->num_channels * sizeof(wmi_dcc_ndl_stats_per_channel)); if (response == NULL)