From 2b8a2a0648adda9995212a9374c8b61feb9c5b85 Mon Sep 17 00:00:00 2001 From: Venkata Sharath Chandra Manchala Date: Wed, 26 Jun 2019 11:50:09 -0700 Subject: [PATCH] qcacmn: Avoid using freed pdev in dp_rx_bar_stats_cb dp_reo_cmdlist_destroy frees any pending reo_cmds. Each reo_cmd is associated with a handler which takes reo_cmd->data as an input. This reo_cmd->data is a pdev for dp_rx_bar_stats_cb. So validate pdev before accessing it further. Change-Id: I1c2d46d3e3f5ede4491500978153f501ebdeee87 CRs-Fixed: 2478910 --- dp/wifi3.0/dp_internal.h | 9 +++++++++ dp/wifi3.0/dp_main.c | 17 +++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h index cfbd311d551b..9fabf1821023 100644 --- a/dp/wifi3.0/dp_internal.h +++ b/dp/wifi3.0/dp_internal.h @@ -861,6 +861,15 @@ uint32_t dp_pdev_tid_stats_display(void *pdev_handle, enum _ol_ath_param_t param, uint32_t value, void *buff); #endif +/** + * dp_check_pdev_exists() - Validate pdev before use + * @soc - dp soc handle + * @data - pdev handle + * + * Return: 0 - success/invalid - failure + */ +bool dp_check_pdev_exists(struct dp_soc *soc, struct dp_pdev *data); + /** * dp_update_delay_stats() - Update delay statistics in structure * and fill min, max and avg delay diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 1559c85b67f6..5786285f0ff5 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -6625,6 +6625,18 @@ void dp_peer_set_mesh_rx_filter(struct cdp_vdev *vdev_hdl, uint32_t val) } #endif +bool dp_check_pdev_exists(struct dp_soc *soc, struct dp_pdev *data) +{ + uint8_t pdev_count; + + for (pdev_count = 0; pdev_count < MAX_PDEV_CNT; pdev_count++) { + if (soc->pdev_list[pdev_count] && + soc->pdev_list[pdev_count] == data) + return true; + } + return false; +} + /** * dp_rx_bar_stats_cb(): BAR received stats callback * @soc: SOC handle @@ -6639,6 +6651,11 @@ void dp_rx_bar_stats_cb(struct dp_soc *soc, void *cb_ctxt, struct dp_pdev *pdev = (struct dp_pdev *)cb_ctxt; struct hal_reo_queue_status *queue_status = &(reo_status->queue_status); + if (!dp_check_pdev_exists(soc, pdev)) { + dp_err_rl("pdev doesn't exist"); + return; + } + if (!qdf_atomic_read(&soc->cmn_init_done)) return;