Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bced4952 authored by Isaac J. Manjarres's avatar Isaac J. Manjarres
Browse files

iommu: iommu-debug: Fix race with respect to test buffer allocation



When the buffer pointed to by test_virt_addr is allocated, there
is no synchronization with respect to checking if it is necessary
to allocate the buffer. This can lead to various adversarial
scenarios, where multiple concurrent allocations of the same
buffer can occur, resulting in memory leaks.

To avoid these scenarios, make the check and allocation of the
buffer atomic with respect to other accesses to test_virt_addr.

Change-Id: Ie7e05930042b0bbf4bec0a4f1f5b325970023a5a
Signed-off-by: default avatarIsaac J. Manjarres <isaacm@codeaurora.org>
parent 1e976197
Loading
Loading
Loading
Loading
+11 −2
Original line number Diff line number Diff line
@@ -173,6 +173,7 @@ static LIST_HEAD(iommu_debug_devices);
static struct dentry *debugfs_tests_dir;
static u32 iters_per_op = 1;
static void *test_virt_addr;
static DEFINE_MUTEX(test_virt_addr_lock);

struct iommu_debug_device {
	struct device *dev;
@@ -1472,6 +1473,7 @@ static ssize_t iommu_debug_test_virt_addr_read(struct file *file,

	memset(buf, 0, buf_len);

	mutex_lock(&test_virt_addr_lock);
	if (IS_ERR_OR_NULL(test_virt_addr))
		test_virt_addr = kzalloc(SZ_1M, GFP_KERNEL);

@@ -1480,6 +1482,7 @@ static ssize_t iommu_debug_test_virt_addr_read(struct file *file,
		strlcpy(buf, "FAIL\n", buf_len);
	} else
		snprintf(buf, buf_len, "0x%pK\n", test_virt_addr);
	mutex_unlock(&test_virt_addr_lock);

	return simple_read_from_buffer(ubuf, count, offset, buf, strlen(buf));
}
@@ -1808,11 +1811,17 @@ static ssize_t iommu_debug_dma_map_write(struct file *file,
	if (kstrtouint(comma2 + 1, 0, &attr))
		goto invalid_format;

	if (IS_ERR(test_virt_addr))
	mutex_lock(&test_virt_addr_lock);
	if (IS_ERR(test_virt_addr)) {
		mutex_unlock(&test_virt_addr_lock);
		goto allocation_failure;
	}

	if (!test_virt_addr)
	if (!test_virt_addr) {
		mutex_unlock(&test_virt_addr_lock);
		goto missing_allocation;
	}
	mutex_unlock(&test_virt_addr_lock);

	if (v_addr < test_virt_addr || v_addr + size > test_virt_addr + SZ_1M)
		goto invalid_addr;