diff options
| author | Ashish Kumar Dhanotiya <adhanoti@codeaurora.org> | 2017-03-31 11:30:01 +0530 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2017-04-07 03:35:18 -0700 |
| commit | 029d2a0726e9ca170afc94c5291cdaf806f080cc (patch) | |
| tree | 0d5af6491ec36b7f87e52afc8ccc1375bc2d71cf | |
| parent | b56990a23edb953ef4333c26ae1fed4c5b0cdbe1 (diff) | |
qcacld-2.0: Race condition while memdump read
There can be a race condition if two threads tries to execute
memdump read which may lead to use-after-free case.
To address this issue implement the use and free of the memory into
the lock.
Change-Id: Ie4d15e9a6414f556a622869d561c331c6bc5d85e
CRs-Fixed: 2023313
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_memdump.c | 25 |
1 files changed, 15 insertions, 10 deletions
diff --git a/CORE/HDD/src/wlan_hdd_memdump.c b/CORE/HDD/src/wlan_hdd_memdump.c index 778ec0736b80..511c8b12f26c 100644 --- a/CORE/HDD/src/wlan_hdd_memdump.c +++ b/CORE/HDD/src/wlan_hdd_memdump.c @@ -423,30 +423,35 @@ static ssize_t memdump_read(struct file *file, char __user *buf, hddLog(LOGE, FL("ADF context is NULL")); return -EINVAL; } - + mutex_lock(&hdd_ctx->memdump_lock); if (!hdd_ctx->memdump_in_progress) { hddLog(LOGE, FL("Current mem dump request timed out/failed")); - return -EINVAL; + status = -EINVAL; + goto memdump_read_fail; } if (*pos < 0) { hddLog(LOGE, FL("Invalid start offset for memdump read")); - return -EINVAL; + status = -EINVAL; + goto memdump_read_fail; } else if (*pos >= FW_MEM_DUMP_SIZE || !count) { hddLog(LOGE, FL("No more data to copy")); - return 0; + status = 0; + goto memdump_read_fail; } else if (count > FW_MEM_DUMP_SIZE - *pos) { count = FW_MEM_DUMP_SIZE - *pos; } if (!hdd_ctx->fw_dump_loc) { hddLog(LOGE, FL("Invalid fw mem dump location")); - return -EINVAL; + status = -EINVAL; + goto memdump_read_fail; } if (copy_to_user(buf, hdd_ctx->fw_dump_loc + *pos, count)) { hddLog(LOGE, FL("copy to user space failed")); - return -EFAULT; + status = -EFAULT; + goto memdump_read_fail; } /* offset(pos) should be updated here based on the copy done */ @@ -455,7 +460,6 @@ static ssize_t memdump_read(struct file *file, char __user *buf, /* Entire FW memory dump copy completed */ if (*pos >= FW_MEM_DUMP_SIZE) { paddr = hdd_ctx->dump_loc_paddr; - mutex_lock(&hdd_ctx->memdump_lock); adf_os_mem_free_consistent(adf_ctx, FW_MEM_DUMP_SIZE, hdd_ctx->fw_dump_loc, paddr, dma_ctx); hdd_ctx->fw_dump_loc = NULL; @@ -464,10 +468,11 @@ static ssize_t memdump_read(struct file *file, char __user *buf, vos_timer_getCurrentState(&hdd_ctx->memdump_cleanup_timer)) { vos_timer_stop(&hdd_ctx->memdump_cleanup_timer); } - mutex_unlock(&hdd_ctx->memdump_lock); } - - return count; + status = count; +memdump_read_fail: + mutex_unlock(&hdd_ctx->memdump_lock); + return status; } /** |
