summaryrefslogtreecommitdiff
path: root/core/utils
diff options
context:
space:
mode:
authorPoddar, Siddarth <siddpodd@codeaurora.org>2017-07-25 19:58:25 +0530
committersnandini <snandini@codeaurora.org>2017-08-16 14:29:20 -0700
commit1e8593ccbfdb8e1f5004f28020dad0c2af8ef2a3 (patch)
treedb4515171aac7c5ce1191894dcbffaf73435a459 /core/utils
parentdfcae3db19ddcf5dd63a3a4b23361b70d5590dca (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/utils')
-rw-r--r--core/utils/pktlog/include/pktlog_ac.h8
-rw-r--r--core/utils/pktlog/linux_ac.c98
-rw-r--r--core/utils/pktlog/pktlog_ac.c2
3 files changed, 76 insertions, 32 deletions
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)
{