diff options
| author | Arif Hussain <arifhussain@codeaurora.org> | 2019-01-15 16:51:37 -0800 |
|---|---|---|
| committer | nshrivas <nshrivas@codeaurora.org> | 2019-04-18 01:00:33 -0700 |
| commit | d78646cee2913f2b036a3ffef37bae4ec02aa1ef (patch) | |
| tree | 432a7ea9369043b1a1505e8c277458fc28fce6ae | |
| parent | f9439d5b2fd803423ac56059ccc0c277191ceff1 (diff) | |
qcacld-3.0: Fix null pointer dereference stats event handler
Fix possible null pointer dereference while handling
the WMI_REPORT_STATS_EVENTID from firmware.
Change-Id: Id8b4f7c26bbae428cd7bc6f2f88b5bd72fd27284
CRs-Fixed: 2380746
| -rw-r--r-- | core/wma/src/wma_utils.c | 100 |
1 files changed, 64 insertions, 36 deletions
diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c index 26592fc260ab..dcb093dd7314 100644 --- a/core/wma/src/wma_utils.c +++ b/core/wma/src/wma_utils.c @@ -817,12 +817,13 @@ static tSirLLStatsResults *wma_get_ll_stats_ext_buf(uint32_t *len, * @param_buf: parameters without fixed length in WMI event * @buf: buffer for TLV parameters * - * Return: None + * Return: QDF_STATUS */ -static void wma_fill_tx_stats(struct sir_wifi_ll_ext_stats *ll_stats, - wmi_report_stats_event_fixed_param *fix_param, - WMI_REPORT_STATS_EVENTID_param_tlvs *param_buf, - uint8_t **buf, uint32_t *buf_length) +static QDF_STATUS +wma_fill_tx_stats(struct sir_wifi_ll_ext_stats *ll_stats, + wmi_report_stats_event_fixed_param *fix_param, + WMI_REPORT_STATS_EVENTID_param_tlvs *param_buf, + uint8_t **buf, uint32_t *buf_length) { uint8_t *result; uint32_t i, j, k; @@ -849,54 +850,59 @@ static void wma_fill_tx_stats(struct sir_wifi_ll_ext_stats *ll_stats, len = fix_param->num_peer_ac_tx_stats * WLAN_MAX_AC * tx_mpdu_aggr_array_len * sizeof(uint32_t); - if (len <= dst_len) { + if (len <= dst_len && param_buf->tx_mpdu_aggr) { tx_mpdu_aggr = (uint32_t *)result; qdf_mem_copy(tx_mpdu_aggr, param_buf->tx_mpdu_aggr, len); result += len; dst_len -= len; } else { - WMA_LOGE(FL("TX_MPDU_AGGR buffer length is wrong.")); - tx_mpdu_aggr = NULL; + WMA_LOGE(FL("TX_MPDU_AGGR invalid arg, %d, %d"), len, dst_len); + return QDF_STATUS_E_FAILURE; } len = fix_param->num_peer_ac_tx_stats * WLAN_MAX_AC * tx_succ_mcs_array_len * sizeof(uint32_t); - if (len <= dst_len) { + if (len <= dst_len && param_buf->tx_succ_mcs) { tx_succ_mcs = (uint32_t *)result; qdf_mem_copy(tx_succ_mcs, param_buf->tx_succ_mcs, len); result += len; dst_len -= len; } else { - WMA_LOGE(FL("TX_SUCC_MCS buffer length is wrong.")); - tx_succ_mcs = NULL; + WMA_LOGE(FL("TX_SUCC_MCS invalid arg, %d, %d"), len, dst_len); + return QDF_STATUS_E_FAILURE; } len = fix_param->num_peer_ac_tx_stats * WLAN_MAX_AC * tx_fail_mcs_array_len * sizeof(uint32_t); - if (len <= dst_len) { + if (len <= dst_len && param_buf->tx_fail_mcs) { tx_fail_mcs = (uint32_t *)result; qdf_mem_copy(tx_fail_mcs, param_buf->tx_fail_mcs, len); result += len; dst_len -= len; } else { - WMA_LOGE(FL("TX_FAIL_MCS buffer length is wrong.")); - tx_fail_mcs = NULL; + WMA_LOGE(FL("TX_FAIL_MCS invalid arg, %d, %d"), len, dst_len); + return QDF_STATUS_E_FAILURE; } len = fix_param->num_peer_ac_tx_stats * WLAN_MAX_AC * tx_delay_array_len * sizeof(uint32_t); - if (len <= dst_len) { + if (len <= dst_len && param_buf->tx_ppdu_delay) { tx_delay = (uint32_t *)result; qdf_mem_copy(tx_delay, param_buf->tx_ppdu_delay, len); result += len; dst_len -= len; } else { - WMA_LOGE(FL("TX_DELAY buffer length is wrong.")); - tx_delay = NULL; + WMA_LOGE(FL("TX_DELAY invalid arg, %d, %d"), len, dst_len); + return QDF_STATUS_E_FAILURE; } /* per peer tx stats */ peer_stats = ll_stats->peer_stats; + if (!wmi_peer_tx || !wmi_tx || !peer_stats) { + WMA_LOGE(FL("Invalid arg, peer_tx %pK, wmi_tx %pK stats %pK"), + wmi_peer_tx, wmi_tx, peer_stats); + return QDF_STATUS_E_FAILURE; + } for (i = 0; i < fix_param->num_peer_ac_tx_stats; i++) { uint32_t peer_id = wmi_peer_tx[i].peer_id; @@ -954,6 +960,8 @@ static void wma_fill_tx_stats(struct sir_wifi_ll_ext_stats *ll_stats, } *buf = result; *buf_length = dst_len; + + return QDF_STATUS_SUCCESS; } /** @@ -963,12 +971,13 @@ static void wma_fill_tx_stats(struct sir_wifi_ll_ext_stats *ll_stats, * @param_buf: parameters without fixed length in WMI event * @buf: buffer for TLV parameters * - * Return: None + * Return: QDF_STATUS */ -static void wma_fill_rx_stats(struct sir_wifi_ll_ext_stats *ll_stats, - wmi_report_stats_event_fixed_param *fix_param, - WMI_REPORT_STATS_EVENTID_param_tlvs *param_buf, - uint8_t **buf, uint32_t *buf_length) +static QDF_STATUS +wma_fill_rx_stats(struct sir_wifi_ll_ext_stats *ll_stats, + wmi_report_stats_event_fixed_param *fix_param, + WMI_REPORT_STATS_EVENTID_param_tlvs *param_buf, + uint8_t **buf, uint32_t *buf_length) { uint8_t *result; uint32_t i, j, k; @@ -990,30 +999,35 @@ static void wma_fill_rx_stats(struct sir_wifi_ll_ext_stats *ll_stats, dst_len = *buf_length; len = sizeof(uint32_t) * (fix_param->num_peer_ac_rx_stats * WLAN_MAX_AC * rx_mpdu_aggr_array_len); - if (len <= dst_len) { + if (len <= dst_len && param_buf->rx_mpdu_aggr) { rx_mpdu_aggr = (uint32_t *)result; qdf_mem_copy(rx_mpdu_aggr, param_buf->rx_mpdu_aggr, len); result += len; dst_len -= len; } else { - WMA_LOGE(FL("RX_MPDU_AGGR array length is wrong.")); - rx_mpdu_aggr = NULL; + WMA_LOGE(FL("RX_MPDU_AGGR invalid arg %d, %d"), len, dst_len); + return QDF_STATUS_E_FAILURE; } len = sizeof(uint32_t) * (fix_param->num_peer_ac_rx_stats * WLAN_MAX_AC * rx_mcs_array_len); - if (len <= dst_len) { + if (len <= dst_len && param_buf->rx_mcs) { rx_mcs = (uint32_t *)result; qdf_mem_copy(rx_mcs, param_buf->rx_mcs, len); result += len; dst_len -= len; } else { - WMA_LOGE(FL("RX_MCS array length is wrong.")); - rx_mcs = NULL; + WMA_LOGE(FL("RX_MCS invalid arg %d, %d"), len, dst_len); + return QDF_STATUS_E_FAILURE; } /* per peer rx stats */ peer_stats = ll_stats->peer_stats; + if (!wmi_peer_rx || !wmi_rx || !peer_stats) { + WMA_LOGE(FL("Invalid arg, peer_rx %pK, wmi_rx %pK stats %pK"), + wmi_peer_rx, wmi_rx, peer_stats); + return QDF_STATUS_E_FAILURE; + } for (i = 0; i < fix_param->num_peer_ac_rx_stats; i++) { uint32_t peer_id = wmi_peer_rx[i].peer_id; struct sir_wifi_rx *ac; @@ -1065,6 +1079,8 @@ static void wma_fill_rx_stats(struct sir_wifi_ll_ext_stats *ll_stats, } *buf = result; *buf_length = dst_len; + + return QDF_STATUS_SUCCESS; } /** @@ -1116,7 +1132,15 @@ static int wma_ll_stats_evt_handler(void *handle, u_int8_t *event, WMA_LOGD("%s: Posting MAC counters event to HDD", __func__); param_buf = (WMI_REPORT_STATS_EVENTID_param_tlvs *)event; + if (!param_buf) { + WMA_LOGD("%s: param_buf is null", __func__); + return -EINVAL; + } fixed_param = param_buf->fixed_param; + if (!fixed_param) { + WMA_LOGD("%s: fixed_param is null", __func__); + return -EINVAL; + } wmi_cca_stats = param_buf->chan_cca_stats; wmi_peer_signal = param_buf->peer_signal_stats; wmi_peer_rx = param_buf->peer_ac_rx_stats; @@ -1238,14 +1262,18 @@ static int wma_ll_stats_evt_handler(void *handle, u_int8_t *event, } result += i * sizeof(struct sir_wifi_chan_cca_stats); - wma_fill_tx_stats(ll_stats, fixed_param, param_buf, - &result, &result_size); - wma_fill_rx_stats(ll_stats, fixed_param, param_buf, - &result, &result_size); - sme_msg.type = eWMI_SME_LL_STATS_IND; - sme_msg.bodyptr = (void *)link_stats_results; - sme_msg.bodyval = 0; - qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg); + qdf_status = wma_fill_tx_stats(ll_stats, fixed_param, param_buf, + &result, &result_size); + if (QDF_IS_STATUS_SUCCESS(qdf_status)) + qdf_status = wma_fill_rx_stats(ll_stats, fixed_param, param_buf, + &result, &result_size); + if (QDF_IS_STATUS_SUCCESS(qdf_status)) { + sme_msg.type = eWMI_SME_LL_STATS_IND; + sme_msg.bodyptr = (void *)link_stats_results; + sme_msg.bodyval = 0; + qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg); + } + if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { WMA_LOGP(FL("Failed to post peer stat change msg!")); qdf_mem_free(link_stats_results); |
