qcacmn: Race condition while using pkt log buffer

There can be a race condition if the pktlog_buf inside pktlog APIs,
is accessed simultanously from two threads.
To prevent this use mutex in the caller functions of pktlog APIs.

Change-Id: Iea6e3cd28a7a347c1753fe71d0646fb43ee184fa
CRs-Fixed: 2047150
This commit is contained in:
Ashish Kumar Dhanotiya
2017-05-15 14:52:40 +05:30
committed by snandini
父節點 b5621e7d20
當前提交 a55792d148
共有 3 個文件被更改,包括 108 次插入9 次删除

查看文件

@@ -128,6 +128,7 @@ int pktlog_alloc_buf(struct hif_opaque_softc *scn)
unsigned long vaddr;
struct page *vpg;
struct ath_pktlog_info *pl_info;
struct ath_pktlog_buf *buffer;
ol_txrx_pdev_handle pdev_txrx_handle;
pdev_txrx_handle = cds_get_context(QDF_MODULE_ID_TXRX);
@@ -143,25 +144,39 @@ int pktlog_alloc_buf(struct hif_opaque_softc *scn)
page_cnt = (sizeof(*(pl_info->buf)) + pl_info->buf_size) / PAGE_SIZE;
pl_info->buf = vmalloc((page_cnt + 2) * PAGE_SIZE);
if (pl_info->buf == NULL) {
spin_lock_bh(&pl_info->log_lock);
if (pl_info->buf != NULL) {
printk(PKTLOG_TAG "Buffer is already in use\n");
spin_unlock_bh(&pl_info->log_lock);
return -EINVAL;
}
spin_unlock_bh(&pl_info->log_lock);
buffer = vmalloc((page_cnt + 2) * PAGE_SIZE);
if (buffer == NULL) {
printk(PKTLOG_TAG
"%s: Unable to allocate buffer "
"(%d pages)\n", __func__, page_cnt);
return -ENOMEM;
}
pl_info->buf = (struct ath_pktlog_buf *)
(((unsigned long)(pl_info->buf) + PAGE_SIZE - 1)
buffer = (struct ath_pktlog_buf *)
(((unsigned long)(buffer) + PAGE_SIZE - 1)
& PAGE_MASK);
for (vaddr = (unsigned long)(pl_info->buf);
vaddr < ((unsigned long)(pl_info->buf) + (page_cnt * PAGE_SIZE));
for (vaddr = (unsigned long)(buffer);
vaddr < ((unsigned long)(buffer) + (page_cnt * PAGE_SIZE));
vaddr += PAGE_SIZE) {
vpg = vmalloc_to_page((const void *)vaddr);
SetPageReserved(vpg);
}
spin_lock_bh(&pl_info->log_lock);
if (pl_info->buf != NULL)
pktlog_release_buf(pdev_txrx_handle);
pl_info->buf = buffer;
spin_unlock_bh(&pl_info->log_lock);
return 0;
}
@@ -200,6 +215,7 @@ static void pktlog_cleanup(struct ath_pktlog_info *pl_info)
{
pl_info->log_state = 0;
PKTLOG_LOCK_DESTROY(pl_info);
mutex_destroy(&pl_info->pktlog_mutex);
}
/* sysctl procfs handler to enable pktlog */
@@ -802,7 +818,7 @@ rd_done:
}
static ssize_t
pktlog_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
__pktlog_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
{
size_t bufhdr_size;
size_t count = 0, ret_val = 0;
@@ -944,6 +960,22 @@ rd_done:
return ret_val;
}
static ssize_t
pktlog_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
{
size_t ret;
struct ath_pktlog_info *pl_info;
pl_info = (struct ath_pktlog_info *)
PDE_DATA(file->f_path.dentry->d_inode);
if (!pl_info)
return 0;
mutex_lock(&pl_info->pktlog_mutex);
ret = __pktlog_read(file, buf, nbytes, ppos);
mutex_unlock(&pl_info->pktlog_mutex);
return ret;
}
#ifndef VMALLOC_VMADDR
#define VMALLOC_VMADDR(x) ((unsigned long)(x))
#endif