diff options
| author | Poddar, Siddarth <siddpodd@codeaurora.org> | 2017-07-25 19:58:25 +0530 |
|---|---|---|
| committer | snandini <snandini@codeaurora.org> | 2017-08-16 14:29:20 -0700 |
| commit | 1e8593ccbfdb8e1f5004f28020dad0c2af8ef2a3 (patch) | |
| tree | db4515171aac7c5ce1191894dcbffaf73435a459 /core | |
| parent | dfcae3db19ddcf5dd63a3a4b23361b70d5590dca (diff) | |
qcacld-3.0: Protect pktlog under mutex to avoid possible race conditions
Protect pktlog funcitonality under given mutex to avoid possible
race condition between pktlog_release/pktlog_open and pktlogmod_exit.
Also call pktlogmod_exit before calling wdi_event_detach to avoid
accessing freed memory in pktlog release.
Change-Id: I452af523338788447f5c2764e883165237083f7d
CRs-Fixed: 2087777
Diffstat (limited to 'core')
| -rw-r--r-- | core/dp/txrx/ol_txrx.c | 8 | ||||
| -rw-r--r-- | core/utils/pktlog/include/pktlog_ac.h | 8 | ||||
| -rw-r--r-- | core/utils/pktlog/linux_ac.c | 98 | ||||
| -rw-r--r-- | core/utils/pktlog/pktlog_ac.c | 2 |
4 files changed, 80 insertions, 36 deletions
diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c index 110e7ff257c7..4905e8fb597d 100644 --- a/core/dp/txrx/ol_txrx.c +++ b/core/dp/txrx/ol_txrx.c @@ -1834,6 +1834,8 @@ static void ol_tx_free_descs_inuse(ol_txrx_pdev_handle pdev) */ void ol_txrx_pdev_pre_detach(ol_txrx_pdev_handle pdev, int force) { + struct hif_opaque_softc *osc = cds_get_context(QDF_MODULE_ID_HIF); + /* preconditions */ TXRX_ASSERT2(pdev); @@ -1914,6 +1916,8 @@ void ol_txrx_pdev_pre_detach(ol_txrx_pdev_handle pdev, int force) OL_RX_REORDER_TRACE_DETACH(pdev); OL_RX_PN_TRACE_DETACH(pdev); + htt_pktlogmod_exit(pdev, osc); + /* * WDI event detach */ @@ -1939,8 +1943,6 @@ void ol_txrx_pdev_pre_detach(ol_txrx_pdev_handle pdev, int force) */ void ol_txrx_pdev_detach(ol_txrx_pdev_handle pdev) { - struct hif_opaque_softc *osc = cds_get_context(QDF_MODULE_ID_HIF); - /*checking to ensure txrx pdev structure is not NULL */ if (!pdev) { ol_txrx_err( @@ -1948,8 +1950,6 @@ void ol_txrx_pdev_detach(ol_txrx_pdev_handle pdev) return; } - htt_pktlogmod_exit(pdev, osc); - OL_RX_REORDER_TIMEOUT_CLEANUP(pdev); if (pdev->cfg.is_high_latency) diff --git a/core/utils/pktlog/include/pktlog_ac.h b/core/utils/pktlog/include/pktlog_ac.h index d4a074fd49f5..7ffc9582dbd2 100644 --- a/core/utils/pktlog/include/pktlog_ac.h +++ b/core/utils/pktlog/include/pktlog_ac.h @@ -134,6 +134,8 @@ void pktlog_callback(void *pdev, enum WDI_EVENT event, void *log_data); void pktlog_init(struct hif_opaque_softc *scn); int pktlog_enable(struct hif_opaque_softc *scn, int32_t log_state, bool, uint8_t, uint32_t); +int __pktlog_enable(struct hif_opaque_softc *scn, int32_t log_state, + bool, uint8_t, uint32_t); int pktlog_setsize(struct hif_opaque_softc *scn, int32_t log_state); int pktlog_clearbuff(struct hif_opaque_softc *scn, bool clear_buff); int pktlog_disable(struct hif_opaque_softc *scn); @@ -168,6 +170,12 @@ static int pktlog_enable(struct hif_opaque_softc *scn, int32_t log_state, { return 0; } +static int __pktlog_enable(struct hif_opaque_softc *scn, int32_t log_state, + bool ini, uint8_t user, uint32_t is_iwpriv_command) +{ + return 0; +} + static int pktlog_setsize(struct hif_opaque_softc *scn, int32_t log_state) { return 0; diff --git a/core/utils/pktlog/linux_ac.c b/core/utils/pktlog/linux_ac.c index e510d7547400..09630eea1c46 100644 --- a/core/utils/pktlog/linux_ac.c +++ b/core/utils/pktlog/linux_ac.c @@ -532,6 +532,12 @@ static void pktlog_detach(struct hif_opaque_softc *scn) } pl_info = pl_dev->pl_info; + if (!pl_info) { + qdf_print("%s: Invalid pktlog handle", __func__); + ASSERT(0); + return; + } + mutex_lock(&pl_info->pktlog_mutex); remove_proc_entry(WLANDEV_BASENAME, g_pktlog_pde); pktlog_sysctl_unregister(pl_dev); @@ -542,6 +548,7 @@ static void pktlog_detach(struct hif_opaque_softc *scn) pl_dev->tgt_pktlog_alloced = false; } spin_unlock_bh(&pl_info->log_lock); + mutex_unlock(&pl_info->pktlog_mutex); pktlog_cleanup(pl_info); if (pl_dev) { @@ -555,33 +562,19 @@ static int __pktlog_open(struct inode *i, struct file *f) struct hif_opaque_softc *scn; struct ol_pktlog_dev_t *pl_dev; struct ath_pktlog_info *pl_info; + struct ath_pktlog_info_lnx *pl_info_lnx; int ret = 0; PKTLOG_MOD_INC_USE_COUNT; - pl_info = (struct ath_pktlog_info *) - PDE_DATA(f->f_path.dentry->d_inode); - - if (!pl_info) { - pr_err("%s: pl_info NULL", __func__); - return -EINVAL; - } - - if (pl_info->curr_pkt_state != PKTLOG_OPR_NOT_IN_PROGRESS) { - pr_info("%s: plinfo state (%d) != PKTLOG_OPR_NOT_IN_PROGRESS", - __func__, pl_info->curr_pkt_state); - return -EBUSY; - } if (cds_is_module_state_transitioning()) { pr_info("%s: module transition in progress", __func__); return -EAGAIN; } - pl_info->curr_pkt_state = PKTLOG_OPR_IN_PROGRESS_READ_START; scn = cds_get_context(QDF_MODULE_ID_HIF); if (!scn) { - pl_info->curr_pkt_state = PKTLOG_OPR_NOT_IN_PROGRESS; - qdf_print("%s: Invalid scn context\n", __func__); + qdf_print("%s: Invalid scn context", __func__); ASSERT(0); return -EINVAL; } @@ -589,12 +582,38 @@ static int __pktlog_open(struct inode *i, struct file *f) pl_dev = get_pl_handle((struct hif_opaque_softc *)scn); if (!pl_dev) { - pl_info->curr_pkt_state = PKTLOG_OPR_NOT_IN_PROGRESS; - qdf_print("%s: Invalid pktlog handle\n", __func__); + qdf_print("%s: Invalid pktlog handle", __func__); ASSERT(0); return -ENODEV; } + pl_info = pl_dev->pl_info; + + if (!pl_info) { + qdf_print("%s: pl_info NULL", __func__); + return -EINVAL; + } + + mutex_lock(&pl_info->pktlog_mutex); + pl_info_lnx = (pl_dev) ? PL_INFO_LNX(pl_dev->pl_info) : + PL_INFO_LNX(g_pktlog_info); + + if (!pl_info_lnx->sysctl_header) { + mutex_unlock(&pl_info->pktlog_mutex); + qdf_print("%s: pktlog sysctl is unergistered.", __func__); + ASSERT(0); + return -EINVAL; + } + + if (pl_info->curr_pkt_state != PKTLOG_OPR_NOT_IN_PROGRESS) { + mutex_unlock(&pl_info->pktlog_mutex); + qdf_print("%s: plinfo state (%d) != PKTLOG_OPR_NOT_IN_PROGRESS", + __func__, pl_info->curr_pkt_state); + return -EBUSY; + } + + pl_info->curr_pkt_state = PKTLOG_OPR_IN_PROGRESS_READ_START; + pl_info->init_saved_state = pl_info->log_state; if (!pl_info->log_state) { /* Pktlog is already disabled. @@ -602,6 +621,7 @@ static int __pktlog_open(struct inode *i, struct file *f) */ pl_info->curr_pkt_state = PKTLOG_OPR_IN_PROGRESS_READ_START_PKTLOG_DISABLED; + mutex_unlock(&pl_info->pktlog_mutex); return ret; } /* Disbable the pktlog internally. */ @@ -609,6 +629,7 @@ static int __pktlog_open(struct inode *i, struct file *f) pl_info->log_state = 0; pl_info->curr_pkt_state = PKTLOG_OPR_IN_PROGRESS_READ_START_PKTLOG_DISABLED; + mutex_unlock(&pl_info->pktlog_mutex); return ret; } @@ -628,16 +649,11 @@ static int __pktlog_release(struct inode *i, struct file *f) struct hif_opaque_softc *scn; struct ol_pktlog_dev_t *pl_dev; struct ath_pktlog_info *pl_info; + struct ath_pktlog_info_lnx *pl_info_lnx; int ret = 0; PKTLOG_MOD_DEC_USE_COUNT; - pl_info = (struct ath_pktlog_info *) - PDE_DATA(f->f_path.dentry->d_inode); - - if (!pl_info) - return -EINVAL; - if (cds_is_module_state_transitioning()) { pr_info("%s: module transition in progress", __func__); return -EAGAIN; @@ -645,8 +661,7 @@ static int __pktlog_release(struct inode *i, struct file *f) scn = cds_get_context(QDF_MODULE_ID_HIF); if (!scn) { - pl_info->curr_pkt_state = PKTLOG_OPR_NOT_IN_PROGRESS; - qdf_print("%s: Invalid scn context\n", __func__); + qdf_print("%s: Invalid scn context", __func__); ASSERT(0); return -EINVAL; } @@ -654,12 +669,31 @@ static int __pktlog_release(struct inode *i, struct file *f) pl_dev = get_pl_handle((struct hif_opaque_softc *)scn); if (!pl_dev) { - pl_info->curr_pkt_state = PKTLOG_OPR_NOT_IN_PROGRESS; - qdf_print("%s: Invalid pktlog handle\n", __func__); + qdf_print("%s: Invalid pktlog handle", __func__); ASSERT(0); return -ENODEV; } + pl_info = pl_dev->pl_info; + + if (!pl_info) { + qdf_print("%s: Invalid pktlog info", __func__); + ASSERT(0); + return -EINVAL; + } + + mutex_lock(&pl_info->pktlog_mutex); + pl_info_lnx = (pl_dev) ? PL_INFO_LNX(pl_dev->pl_info) : + PL_INFO_LNX(g_pktlog_info); + + if (!pl_info_lnx->sysctl_header) { + pl_info->curr_pkt_state = PKTLOG_OPR_NOT_IN_PROGRESS; + mutex_unlock(&pl_info->pktlog_mutex); + qdf_print("%s: pktlog sysctl is unergistered.", __func__); + ASSERT(0); + return -EINVAL; + } + pl_info->curr_pkt_state = PKTLOG_OPR_IN_PROGRESS_READ_COMPLETE; /*clear pktlog buffer.*/ pktlog_clearbuff(scn, true); @@ -667,14 +701,16 @@ static int __pktlog_release(struct inode *i, struct file *f) pl_info->init_saved_state = 0; /*Enable pktlog again*/ - ret = pl_dev->pl_funcs->pktlog_enable( + ret = __pktlog_enable( (struct hif_opaque_softc *)scn, pl_info->log_state, cds_is_packet_log_enabled(), 0, 1); + + pl_info->curr_pkt_state = PKTLOG_OPR_NOT_IN_PROGRESS; + mutex_unlock(&pl_info->pktlog_mutex); if (ret != 0) - pr_warn("%s: pktlog cannot be enabled. ret value %d\n", + qdf_print("%s: pktlog cannot be enabled. ret value %d", __func__, ret); - pl_info->curr_pkt_state = PKTLOG_OPR_NOT_IN_PROGRESS; return ret; } diff --git a/core/utils/pktlog/pktlog_ac.c b/core/utils/pktlog/pktlog_ac.c index b8e5c3f7659d..f4fe6e10a849 100644 --- a/core/utils/pktlog/pktlog_ac.c +++ b/core/utils/pktlog/pktlog_ac.c @@ -388,7 +388,7 @@ void pktlog_init(struct hif_opaque_softc *scn) PKTLOG_SW_EVENT_SUBSCRIBER.callback = pktlog_callback; } -static int __pktlog_enable(struct hif_opaque_softc *scn, int32_t log_state, +int __pktlog_enable(struct hif_opaque_softc *scn, int32_t log_state, bool ini_triggered, uint8_t user_triggered, uint32_t is_iwpriv_command) { |
