qcacmn: 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: I5ca4b304d0f4dc1af289daa167958d5b773d9a6e CRs-Fixed: 2578623
此提交包含在:
@@ -506,6 +506,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);
|
||||
|
||||
@@ -516,6 +522,7 @@ static void pktlog_detach(struct hif_opaque_softc *scn)
|
||||
pl_dev->tgt_pktlog_alloced = false;
|
||||
}
|
||||
qdf_spin_unlock_bh(&pl_info->log_lock);
|
||||
mutex_unlock(&pl_info->pktlog_mutex);
|
||||
pktlog_cleanup(pl_info);
|
||||
|
||||
if (pl_dev) {
|
||||
@@ -529,25 +536,12 @@ static int __pktlog_open(struct inode *i, struct file *f)
|
||||
struct hif_opaque_softc *scn;
|
||||
struct 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 = PDE_DATA(f->f_path.dentry->d_inode);
|
||||
if (!pl_info) {
|
||||
qdf_nofl_err("%s: pl_info NULL", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (pl_info->curr_pkt_state != PKTLOG_OPR_NOT_IN_PROGRESS) {
|
||||
qdf_nofl_info("%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;
|
||||
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", __func__);
|
||||
ASSERT(0);
|
||||
return -EINVAL;
|
||||
@@ -556,12 +550,38 @@ static int __pktlog_open(struct inode *i, struct file *f)
|
||||
pl_dev = get_pktlog_handle();
|
||||
|
||||
if (!pl_dev) {
|
||||
pl_info->curr_pkt_state = PKTLOG_OPR_NOT_IN_PROGRESS;
|
||||
qdf_print("%s: Invalid pktlog handle", __func__);
|
||||
ASSERT(0);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pl_info = pl_dev->pl_info;
|
||||
|
||||
if (!pl_info) {
|
||||
qdf_nofl_err("%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.
|
||||
@@ -569,6 +589,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. */
|
||||
@@ -576,6 +597,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;
|
||||
}
|
||||
|
||||
@@ -600,17 +622,12 @@ static int __pktlog_release(struct inode *i, struct file *f)
|
||||
struct hif_opaque_softc *scn;
|
||||
struct 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 = PDE_DATA(f->f_path.dentry->d_inode);
|
||||
if (!pl_info)
|
||||
return -EINVAL;
|
||||
|
||||
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", __func__);
|
||||
ASSERT(0);
|
||||
return -EINVAL;
|
||||
@@ -619,12 +636,30 @@ static int __pktlog_release(struct inode *i, struct file *f)
|
||||
pl_dev = get_pktlog_handle();
|
||||
|
||||
if (!pl_dev) {
|
||||
pl_info->curr_pkt_state = PKTLOG_OPR_NOT_IN_PROGRESS;
|
||||
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);
|
||||
@@ -632,15 +667,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);
|
||||
|
||||
if (ret != 0)
|
||||
qdf_nofl_warn("%s: pktlog cannot be enabled. ret value %d",
|
||||
__func__, ret);
|
||||
|
||||
pl_info->curr_pkt_state = PKTLOG_OPR_NOT_IN_PROGRESS;
|
||||
mutex_unlock(&pl_info->pktlog_mutex);
|
||||
if (ret != 0)
|
||||
qdf_print("%s: pktlog cannot be enabled. ret value %d",
|
||||
__func__, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
新增問題並參考
封鎖使用者