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
This commit is contained in:

committed by
Sandeep Puligilla

parent
5591b487f4
commit
1f75a53ecc
@@ -404,29 +404,36 @@ static ssize_t memdump_read(struct file *file, char __user *buf,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex_lock(&hdd_ctx->memdump_lock);
|
||||||
|
|
||||||
if (!hdd_ctx->memdump_in_progress) {
|
if (!hdd_ctx->memdump_in_progress) {
|
||||||
hdd_err("Current mem dump request timed out/failed");
|
hdd_err("Current mem dump request timed out/failed");
|
||||||
return -EINVAL;
|
status = -EINVAL;
|
||||||
|
goto memdump_read_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*pos < 0) {
|
if (*pos < 0) {
|
||||||
hdd_err("Invalid start offset for memdump read");
|
hdd_err("Invalid start offset for memdump read");
|
||||||
return -EINVAL;
|
status = -EINVAL;
|
||||||
|
goto memdump_read_fail;
|
||||||
} else if (*pos >= FW_MEM_DUMP_SIZE || !count) {
|
} else if (*pos >= FW_MEM_DUMP_SIZE || !count) {
|
||||||
hdd_debug("No more data to copy");
|
hdd_debug("No more data to copy");
|
||||||
return 0;
|
status = 0;
|
||||||
|
goto memdump_read_fail;
|
||||||
} else if (count > FW_MEM_DUMP_SIZE - *pos) {
|
} else if (count > FW_MEM_DUMP_SIZE - *pos) {
|
||||||
count = FW_MEM_DUMP_SIZE - *pos;
|
count = FW_MEM_DUMP_SIZE - *pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hdd_ctx->fw_dump_loc) {
|
if (!hdd_ctx->fw_dump_loc) {
|
||||||
hdd_err("Invalid fw mem dump location");
|
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)) {
|
if (copy_to_user(buf, hdd_ctx->fw_dump_loc + *pos, count)) {
|
||||||
hdd_err("copy to user space failed");
|
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*/
|
/* 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 */
|
/* Entire FW memory dump copy completed */
|
||||||
if (*pos >= FW_MEM_DUMP_SIZE) {
|
if (*pos >= FW_MEM_DUMP_SIZE) {
|
||||||
paddr = hdd_ctx->dump_loc_paddr;
|
paddr = hdd_ctx->dump_loc_paddr;
|
||||||
mutex_lock(&hdd_ctx->memdump_lock);
|
|
||||||
qdf_mem_free_consistent(qdf_ctx, qdf_ctx->dev,
|
qdf_mem_free_consistent(qdf_ctx, qdf_ctx->dev,
|
||||||
FW_MEM_DUMP_SIZE, hdd_ctx->fw_dump_loc, paddr, dma_ctx);
|
FW_MEM_DUMP_SIZE, hdd_ctx->fw_dump_loc, paddr, dma_ctx);
|
||||||
hdd_ctx->fw_dump_loc = NULL;
|
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)) {
|
&hdd_ctx->memdump_cleanup_timer)) {
|
||||||
qdf_mc_timer_stop(&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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user