Jelajahi Sumber

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
Ashish Kumar Dhanotiya 8 tahun lalu
induk
melakukan
1f75a53ecc
1 mengubah file dengan 17 tambahan dan 9 penghapusan
  1. 17 9
      core/hdd/src/wlan_hdd_memdump.c

+ 17 - 9
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;
 }
 
 /**