diff options
| author | Vignesh Viswanathan <viswanat@codeaurora.org> | 2017-11-14 14:58:54 +0530 |
|---|---|---|
| committer | snandini <snandini@codeaurora.org> | 2017-11-15 08:45:07 -0800 |
| commit | 6e9ed1d63d3bad802185c3be6342ee38d7df59f7 (patch) | |
| tree | e21a758238641cc0e34ca528520029b49079d4f8 | |
| parent | 6479dea25a024032018cd519c3aa1370fc9fcad7 (diff) | |
qcacld-2.0: Avoid integer overflow in __wma_get_ll_stats_ext_buf
Check multiple variables received from firmware used to calculate
buf_len to make sure that it does not exceed the max msg size, as
this buf_len is in turn used in malloc and can lead to less than
required memory allocated in case of integer overflow of buf_len
Change-Id: I2689873c2c5e63c83e5059563662c0c69dc659fc
CRs-Fixed: 2143080
| -rw-r--r-- | CORE/SERVICES/WMA/wma.c | 107 |
1 files changed, 92 insertions, 15 deletions
diff --git a/CORE/SERVICES/WMA/wma.c b/CORE/SERVICES/WMA/wma.c index 79ea86c1574d..1cc273552868 100644 --- a/CORE/SERVICES/WMA/wma.c +++ b/CORE/SERVICES/WMA/wma.c @@ -5532,6 +5532,8 @@ static tSirLLStatsResults *__wma_get_ll_stats_ext_buf(uint32_t *len, { tSirLLStatsResults *buf; uint32_t buf_len; + uint32_t total_array_len, total_peer_len; + bool excess_data = false; if (!len || !fixed_param) { WMA_LOGE(FL("Invalid input parameters.")); @@ -5595,21 +5597,96 @@ static tSirLLStatsResults *__wma_get_ll_stats_ext_buf(uint32_t *len, * --------------------------------- */ buf_len = sizeof(tSirLLStatsResults) + - sizeof(struct sir_wifi_ll_ext_stats) + - fixed_param->num_chan_cca_stats * - sizeof(struct sir_wifi_chan_cca_stats) + - peer_num * - (sizeof(struct sir_wifi_ll_ext_peer_stats) + - WLAN_MAX_AC * - (sizeof(struct sir_wifi_tx) + - sizeof(struct sir_wifi_rx)) + - sizeof(uint32_t) * WLAN_MAX_AC * - (fixed_param->tx_mpdu_aggr_array_len + - fixed_param->tx_succ_mcs_array_len + - fixed_param->tx_fail_mcs_array_len + - fixed_param->tx_ppdu_delay_array_len + - fixed_param->rx_mpdu_aggr_array_len + - fixed_param->rx_mcs_array_len)); + sizeof(struct sir_wifi_ll_ext_stats); + + do { + if (fixed_param->num_chan_cca_stats > (WMA_SVC_MSG_MAX_SIZE / + sizeof(struct sir_wifi_chan_cca_stats))) { + excess_data = true; + break; + } + buf_len += (fixed_param->num_chan_cca_stats * + sizeof(struct sir_wifi_chan_cca_stats)); + if (fixed_param->tx_mpdu_aggr_array_len > + WMA_SVC_MSG_MAX_SIZE) { + excess_data = true; + break; + } else { + total_array_len = fixed_param->tx_mpdu_aggr_array_len; + } + if (fixed_param->tx_succ_mcs_array_len > + (WMA_SVC_MSG_MAX_SIZE - total_array_len)) { + excess_data = true; + break; + } else { + total_array_len += fixed_param->tx_succ_mcs_array_len; + } + if (fixed_param->tx_fail_mcs_array_len > + (WMA_SVC_MSG_MAX_SIZE - total_array_len)) { + excess_data = true; + break; + } else { + total_array_len += fixed_param->tx_fail_mcs_array_len; + } + if (fixed_param->tx_ppdu_delay_array_len > + (WMA_SVC_MSG_MAX_SIZE - total_array_len)) { + excess_data = true; + break; + } else { + total_array_len += fixed_param->tx_ppdu_delay_array_len; + } + if (fixed_param->rx_mpdu_aggr_array_len > + (WMA_SVC_MSG_MAX_SIZE - total_array_len)) { + excess_data = true; + break; + } else { + total_array_len += fixed_param->rx_mpdu_aggr_array_len; + } + if (fixed_param->rx_mcs_array_len > + (WMA_SVC_MSG_MAX_SIZE - total_array_len)) { + excess_data = true; + break; + } else { + total_array_len += fixed_param->rx_mcs_array_len; + } + + if (total_array_len > (WMA_SVC_MSG_MAX_SIZE / + (sizeof(uint32_t) * WLAN_MAX_AC))) { + excess_data = true; + break; + } else { + total_peer_len = (sizeof(uint32_t) * WLAN_MAX_AC * + total_array_len) + + (WLAN_MAX_AC * + (sizeof(struct sir_wifi_tx) + + sizeof(struct sir_wifi_rx))); + } + if (total_peer_len > WMA_SVC_MSG_MAX_SIZE) { + excess_data = true; + break; + } + if (peer_num > WMA_SVC_MSG_MAX_SIZE / (total_peer_len + + sizeof(struct sir_wifi_ll_ext_peer_stats))) { + excess_data = true; + break; + } else { + buf_len += peer_num * + (sizeof(struct sir_wifi_ll_ext_peer_stats) + + total_peer_len); + } + } while (0); + + if (excess_data || (buf_len > WMA_SVC_MSG_MAX_SIZE)) { + WMA_LOGE("%s: excess wmi buffer: peer %d cca %d tx_mpdu %d tx_succ%d tx_fail %d tx_ppdu %d rx_mpdu %d rx_mcs %d", + __func__, peer_num, fixed_param->num_chan_cca_stats, + fixed_param->tx_mpdu_aggr_array_len, + fixed_param->tx_succ_mcs_array_len, + fixed_param->tx_fail_mcs_array_len, + fixed_param->tx_ppdu_delay_array_len, + fixed_param->rx_mpdu_aggr_array_len, + fixed_param->rx_mcs_array_len); + return NULL; + } buf = (tSirLLStatsResults *)vos_mem_malloc(buf_len); if (buf == NULL) { |
