diff options
author | Sarada Prasanna Garnayak <sgarna@codeaurora.org> | 2017-06-08 15:34:13 +0530 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2017-06-22 00:35:59 -0700 |
commit | 470cbd2aeabd076d7278d25b15e130767e67dc44 (patch) | |
tree | e2b3db4c32b61817095b9f491a5005b6d7431db0 /drivers | |
parent | 560a996da5c0bf398d2fba51e9909cd7323afea8 (diff) |
icnss: fix the memory and kernel info leak due to the race condition
The icnss register read/write debugfs entry can be accessed by
multiple user space thread. Memory allocation and deallocation
in the register read/write file operation leads to potential memory
leak during concurrency access of debugfs device file.
Add protection to avoid the memory leak and kernel information
leak due to the race condition in the register read/write ops.
CRs-Fixed: 2012572
Change-Id: I22c6af9a396c0df4e68f75702fc68a5dff5af032
Signed-off-by: Sarada Prasanna Garnayak <sgarna@codeaurora.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/soc/qcom/icnss.c | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c index 28f89bfac7c6..9690d3c64560 100644 --- a/drivers/soc/qcom/icnss.c +++ b/drivers/soc/qcom/icnss.c @@ -434,6 +434,7 @@ static struct icnss_priv { bool is_wlan_mac_set; struct icnss_wlan_mac_addr wlan_mac_addr; bool bypass_s1_smmu; + struct mutex dev_lock; } *penv; #ifdef CONFIG_ICNSS_DEBUG @@ -3939,12 +3940,14 @@ static int icnss_regread_show(struct seq_file *s, void *data) { struct icnss_priv *priv = s->private; + mutex_lock(&priv->dev_lock); if (!priv->diag_reg_read_buf) { seq_puts(s, "Usage: echo <mem_type> <offset> <data_len> > <debugfs>/icnss/reg_read\n"); if (!test_bit(ICNSS_FW_READY, &priv->state)) seq_puts(s, "Firmware is not ready yet!, wait for FW READY\n"); + mutex_unlock(&priv->dev_lock); return 0; } @@ -3958,6 +3961,7 @@ static int icnss_regread_show(struct seq_file *s, void *data) priv->diag_reg_read_len = 0; kfree(priv->diag_reg_read_buf); priv->diag_reg_read_buf = NULL; + mutex_unlock(&priv->dev_lock); return 0; } @@ -4018,18 +4022,22 @@ static ssize_t icnss_regread_write(struct file *fp, const char __user *user_buf, data_len > QMI_WLFW_MAX_DATA_SIZE_V01) return -EINVAL; + mutex_lock(&priv->dev_lock); kfree(priv->diag_reg_read_buf); priv->diag_reg_read_buf = NULL; reg_buf = kzalloc(data_len, GFP_KERNEL); - if (!reg_buf) + if (!reg_buf) { + mutex_unlock(&priv->dev_lock); return -ENOMEM; + } ret = wlfw_athdiag_read_send_sync_msg(priv, reg_offset, mem_type, data_len, reg_buf); if (ret) { kfree(reg_buf); + mutex_unlock(&priv->dev_lock); return ret; } @@ -4037,6 +4045,7 @@ static ssize_t icnss_regread_write(struct file *fp, const char __user *user_buf, priv->diag_reg_read_mem_type = mem_type; priv->diag_reg_read_len = data_len; priv->diag_reg_read_buf = reg_buf; + mutex_unlock(&priv->dev_lock); return count; } @@ -4284,6 +4293,7 @@ static int icnss_probe(struct platform_device *pdev) spin_lock_init(&priv->event_lock); spin_lock_init(&priv->on_off_lock); + mutex_init(&priv->dev_lock); priv->event_wq = alloc_workqueue("icnss_driver_event", WQ_UNBOUND, 1); if (!priv->event_wq) { |