summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArif Hussain <arifhussain@codeaurora.org>2019-01-15 16:51:37 -0800
committernshrivas <nshrivas@codeaurora.org>2019-04-18 01:00:33 -0700
commitd78646cee2913f2b036a3ffef37bae4ec02aa1ef (patch)
tree432a7ea9369043b1a1505e8c277458fc28fce6ae
parentf9439d5b2fd803423ac56059ccc0c277191ceff1 (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.c100
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);