From ad7eded05e6aaae89864c5aa3d25055c42f41d02 Mon Sep 17 00:00:00 2001 From: Vignesh Viswanathan Date: Tue, 28 Nov 2017 16:58:24 +0530 Subject: [PATCH] qcacld-3.0: Fix buffer overflow in wma radio_tx_power_level_stats handler In function wma_unified_radio_tx_power_level_stats_event_handler, power_level_offset is received from the FW and is used to memcpy data from FW to local tx_time_per_power_level for num_tx_power_levels length. However tx_time_per_power_level is allocated only for total_num_tx_power_levels length. If the power_level_offset is greater than total_num_tx_power_levels, then a buffer overwrite would occur. Add sanity check to make sure power_level_offset does not exceed total_num_tx_power_levels Change-Id: Ia363512ee35bb0e30b137c20bf092238c2e356da CRs-Fixed: 2149501 --- core/wma/src/wma_utils.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c index 17389daedb9f..b2d42dfac3f1 100644 --- a/core/wma/src/wma_utils.c +++ b/core/wma/src/wma_utils.c @@ -1484,9 +1484,9 @@ static int wma_unified_radio_tx_power_level_stats_event_handler(void *handle, sizeof(*fixed_param)) / sizeof(uint32_t))) { WMA_LOGE("%s: excess tx_power buffers:%d", __func__, fixed_param->num_tx_power_levels); - QDF_ASSERT(0); return -EINVAL; } + rs_results = (tSirWifiRadioStat *) &link_stats_results->results[0] + fixed_param->radio_id; tx_power_level_values = (uint8_t *) param_tlvs->tx_time_per_power_level; @@ -1498,6 +1498,18 @@ static int wma_unified_radio_tx_power_level_stats_event_handler(void *handle, goto post_stats; } + if ((fixed_param->power_level_offset > + rs_results->total_num_tx_power_levels) || + (fixed_param->num_tx_power_levels > + rs_results->total_num_tx_power_levels - + fixed_param->power_level_offset)) { + WMA_LOGE("%s: Invalid offset %d total_num %d num %d", + __func__, fixed_param->power_level_offset, + rs_results->total_num_tx_power_levels, + fixed_param->num_tx_power_levels); + return -EINVAL; + } + if (!rs_results->tx_time_per_power_level) { rs_results->tx_time_per_power_level = qdf_mem_malloc( sizeof(uint32_t) *