summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVignesh Viswanathan <viswanat@codeaurora.org>2017-09-27 20:25:33 +0530
committersnandini <snandini@codeaurora.org>2017-10-03 08:27:45 -0700
commit27077eff522a611ba85747c8a905bb9238d9ae02 (patch)
tree00e370d9447a950f71fd86e546870928e193e90c
parent5bca4f1b0ca065db1552e1ce5707e0056ac9031e (diff)
qcacld-3.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: 2115112
-rw-r--r--core/wma/src/wma_utils.c108
1 files changed, 93 insertions, 15 deletions
diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c
index 2fa35ff09a5f..eb8130485755 100644
--- a/core/wma/src/wma_utils.c
+++ b/core/wma/src/wma_utils.c
@@ -631,6 +631,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."));
@@ -693,22 +695,98 @@ static tSirLLStatsResults *wma_get_ll_stats_ext_buf(uint32_t *len,
* | VO |
* ---------------------------------
*/
+
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 > (WMI_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 >
+ WMI_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 >
+ (WMI_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 >
+ (WMI_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 >
+ (WMI_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 >
+ (WMI_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 >
+ (WMI_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 > (WMI_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 > WMI_SVC_MSG_MAX_SIZE) {
+ excess_data = true;
+ break;
+ }
+ if (peer_num > (WMI_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 > WMI_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);
+ QDF_ASSERT(0);
+ return NULL;
+ }
buf = (tSirLLStatsResults *)qdf_mem_malloc(buf_len);
if (buf == NULL) {