From 1f75a53ecc4214a52592c65edfa05cce6e8e4518 Mon Sep 17 00:00:00 2001 From: Ashish Kumar Dhanotiya Date: Fri, 7 Apr 2017 13:03:36 +0530 Subject: [PATCH] qcacld-3.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 --- core/hdd/src/wlan_hdd_memdump.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/core/hdd/src/wlan_hdd_memdump.c b/core/hdd/src/wlan_hdd_memdump.c index 59876107941f..b7261cb4b2be 100644 --- a/core/hdd/src/wlan_hdd_memdump.c +++ b/core/hdd/src/wlan_hdd_memdump.c @@ -404,29 +404,36 @@ static ssize_t memdump_read(struct file *file, char __user *buf, return -EINVAL; } + mutex_lock(&hdd_ctx->memdump_lock); + if (!hdd_ctx->memdump_in_progress) { hdd_err("Current mem dump request timed out/failed"); - return -EINVAL; + status = -EINVAL; + goto memdump_read_fail; } if (*pos < 0) { hdd_err("Invalid start offset for memdump read"); - return -EINVAL; + status = -EINVAL; + goto memdump_read_fail; } else if (*pos >= FW_MEM_DUMP_SIZE || !count) { hdd_debug("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) { hdd_err("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)) { hdd_err("copy to user space failed"); - return -EFAULT; + status = -EFAULT; + goto memdump_read_fail; } /* offset(pos) should be updated here based on the copy done*/ @@ -435,7 +442,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); qdf_mem_free_consistent(qdf_ctx, qdf_ctx->dev, FW_MEM_DUMP_SIZE, hdd_ctx->fw_dump_loc, paddr, dma_ctx); hdd_ctx->fw_dump_loc = NULL; @@ -445,10 +451,12 @@ static ssize_t memdump_read(struct file *file, char __user *buf, &hdd_ctx->memdump_cleanup_timer)) { qdf_mc_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; } /**