diff options
| author | Vignesh Viswanathan <viswanat@codeaurora.org> | 2017-09-26 15:21:07 +0530 |
|---|---|---|
| committer | snandini <snandini@codeaurora.org> | 2017-10-04 15:30:38 -0700 |
| commit | 1ebe1be210dbcd23782cd9a0c3bf2ba55fcef5b0 (patch) | |
| tree | e534f954dce3012af6a6dda07210f1965ab00a4d | |
| parent | eea5836e0b4be0d3c42d4c32389f08f85332a80b (diff) | |
qcacld-3.0: Fix integer overflow in wma_unified_link_peer_stats_event_handler
Currently in wma_unified_link_peer_stats_event_handler, the check to validate
if peer_stats->num_rates is less than WMA_SVC_MSG_MAX_SIZE is done only for
the first member of the peer_stats array. This can lead to integer overflow
as num_rates is calculated as sum of peer_stats->num_rates for each of the
peer_stats in the array.
Add code changes to loop and calculate total_num_rates for all the peer_stats
and then validate total_num_rates with WMA_SVC_MSG_MAX_SIZE.
Change-Id: Ic934934a990bd55fce70a0eaffa2812bc34b0ddd
CRs-Fixed: 2113758
| -rw-r--r-- | core/wma/src/wma_utils.c | 47 |
1 files changed, 25 insertions, 22 deletions
diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c index eb8130485755..80d02685cabc 100644 --- a/core/wma/src/wma_utils.c +++ b/core/wma/src/wma_utils.c @@ -1250,7 +1250,8 @@ static int wma_unified_link_peer_stats_event_handler(void *handle, wmi_rate_stats *rate_stats; tSirLLStatsResults *link_stats_results; uint8_t *results, *t_peer_stats, *t_rate_stats; - uint32_t count, num_rates = 0, rate_cnt; + uint32_t count, rate_cnt; + uint32_t total_num_rates = 0; uint32_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; @@ -1278,8 +1279,8 @@ static int wma_unified_link_peer_stats_event_handler(void *handle, * cmd_param_info contains * wmi_peer_stats_event_fixed_param fixed_param; * num_peers * size of(struct wmi_peer_link_stats) - * num_rates * size of(struct wmi_rate_stats) - * num_rates is the sum of the rates of all the peers. + * total_num_rates * size of(struct wmi_rate_stats) + * total_num_rates is the sum of the rates of all the peers. */ fixed_param = param_tlvs->fixed_param; peer_stats = param_tlvs->peer_stats; @@ -1292,22 +1293,33 @@ static int wma_unified_link_peer_stats_event_handler(void *handle, } do { - if (peer_stats->num_rates > - WMI_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 > WMI_SVC_MSG_MAX_SIZE/sizeof(wmi_peer_link_stats)) { excess_data = true; break; } else { - buf_len += fixed_param->num_peers * + buf_len = fixed_param->num_peers * sizeof(wmi_peer_link_stats); } + temp_peer_stats = (wmi_peer_link_stats *) peer_stats; + for (count = 0; count < fixed_param->num_peers; count++) { + if (temp_peer_stats->num_rates > + WMI_SVC_MSG_MAX_SIZE / sizeof(wmi_rate_stats)) { + excess_data = true; + break; + } else { + total_num_rates += temp_peer_stats->num_rates; + if (total_num_rates > + WMI_SVC_MSG_MAX_SIZE / + sizeof(wmi_rate_stats)) { + excess_data = true; + break; + } + buf_len += temp_peer_stats->num_rates * + sizeof(wmi_rate_stats); + } + temp_peer_stats++; + } } while (0); if (excess_data || @@ -1318,22 +1330,13 @@ static int wma_unified_link_peer_stats_event_handler(void *handle, return -EINVAL; } - /* - * num_rates - sum of the rates of all the peers - */ - temp_peer_stats = (wmi_peer_link_stats *) peer_stats; - for (count = 0; count < fixed_param->num_peers; count++) { - num_rates += temp_peer_stats->num_rates; - temp_peer_stats++; - } - peer_stats_size = sizeof(tSirWifiPeerStat); peer_info_size = sizeof(tSirWifiPeerInfo); rate_stats_size = sizeof(tSirWifiRateStat); link_stats_results_size = sizeof(*link_stats_results) + peer_stats_size + (fixed_param->num_peers * peer_info_size) + - (num_rates * rate_stats_size); + (total_num_rates * rate_stats_size); link_stats_results = qdf_mem_malloc(link_stats_results_size); if (NULL == link_stats_results) { |
