summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCNSS_WLAN Service <cnssbldsw@qualcomm.com>2017-10-03 11:42:17 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2017-10-03 11:42:17 -0700
commit4e3bdd1763a249ac38b634d28ae5b75e96f7f9f3 (patch)
treed8bd6ccc801fa53b98e0cecbee287b3958c613e2
parent411c3c0e28a25f92efda8dcaddee038783fcca0f (diff)
parent27077eff522a611ba85747c8a905bb9238d9ae02 (diff)
Merge "qcacld-3.0: Avoid integer overflow in wma_get_ll_stats_ext_buf" into wlan-cld3.driver.lnx.1.1
-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) {