From a03b6c4d11af3e8c0642d919b6b98b4fb28a2d5f Mon Sep 17 00:00:00 2001 From: Ismael Castro Date: Mon, 8 Jan 2024 00:38:32 +0000 Subject: Fix type confusion of dmabuf in aoc driver This change ensures that the struct dma_heap that is passed in the file descriptor via ioctl is created/maintained by aoc. Bug: 313424730 Test: researcher's PoC doesn't print handle Change-Id: I408872a66964bd4d03d3b09794b2eb626028b60b Signed-off-by: Ismael Castro (cherry picked from commit 7672a4aaa5bb92bc69337942e5fa047e4964ae62) --- aoc.c | 3 +++ aoc_v1.c | 27 +++++++++++++++++++++++++++ ion_physical_heap.c | 12 ------------ ion_physical_heap.h | 13 +++++++++++++ 4 files changed, 43 insertions(+), 12 deletions(-) diff --git a/aoc.c b/aoc.c index 654306b..5c17af0 100644 --- a/aoc.c +++ b/aoc.c @@ -1924,6 +1924,9 @@ static long aoc_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned lon case AOC_IOCTL_ION_FD_TO_HANDLE: { ret = aoc_unlocked_ioctl_handle_ion_fd(cmd, arg); + if (ret == -EINVAL) { + pr_err("invalid argument\n"); + } } break; diff --git a/aoc_v1.c b/aoc_v1.c index e67937f..93045b3 100644 --- a/aoc_v1.c +++ b/aoc_v1.c @@ -375,12 +375,26 @@ bool aoc_create_dma_buf_heaps(struct aoc_prvdata *prvdata) } EXPORT_SYMBOL_GPL(aoc_create_dma_buf_heaps); +/* Returns true if `base` is located within the aoc dram carveout */ +static bool is_aoc_dma_buf(struct aoc_prvdata *prvdata, phys_addr_t base) { + phys_addr_t dram_carveout_start; + phys_addr_t dram_carveout_end; + + dram_carveout_start = prvdata->dram_resource.start; + dram_carveout_end = dram_carveout_start + resource_size(&prvdata->dram_resource); + return (base <= dram_carveout_end && base >= dram_carveout_start); +} + long aoc_unlocked_ioctl_handle_ion_fd(unsigned int cmd, unsigned long arg) { struct aoc_ion_handle handle; struct dma_buf *dmabuf; struct samsung_dma_buffer *dma_heap_buf; + + struct ion_physical_heap *phys_heap; + phys_addr_t base; long ret = -EINVAL; + struct aoc_prvdata *prvdata = platform_get_drvdata(aoc_platform_device); BUILD_BUG_ON(sizeof(struct aoc_ion_handle) != _IOC_SIZE(AOC_IOCTL_ION_FD_TO_HANDLE)); @@ -398,6 +412,19 @@ long aoc_unlocked_ioctl_handle_ion_fd(unsigned int cmd, unsigned long arg) dma_heap_buf = dmabuf->priv; handle.handle = (u64)dma_heap_buf->priv; + /* + * Ensure base is in aoc dram carveout. Ensures that the dmabuf + * is created and maintained by AoC. + */ + base = 0; + if (dma_heap_buf->heap->priv) { + phys_heap = dma_heap_buf->heap->priv; + base = phys_heap->base; + } + + if (!(is_aoc_dma_buf(prvdata, base))) + return ret; + dma_buf_put(dmabuf); if (!copy_to_user((struct aoc_ion_handle *)arg, &handle, _IOC_SIZE(cmd))) diff --git a/ion_physical_heap.c b/ion_physical_heap.c index 30c8250..e4a0c2e 100644 --- a/ion_physical_heap.c +++ b/ion_physical_heap.c @@ -19,18 +19,6 @@ #define ION_PHYSICAL_ALLOCATE_FAIL -1 -struct ion_physical_heap { - struct gen_pool *pool; - phys_addr_t base; - size_t size; - - ion_physical_heap_allocate_callback *allocate_cb; - void *allocate_ctx; - - ion_physical_heap_free_callback *free_cb; - void *free_ctx; -}; - static int _clear_pages(struct page **pages, int num, pgprot_t pgprot) { void *addr = vmap(pages, num, VM_MAP, pgprot); diff --git a/ion_physical_heap.h b/ion_physical_heap.h index fa66671..f48ccd8 100644 --- a/ion_physical_heap.h +++ b/ion_physical_heap.h @@ -4,6 +4,7 @@ */ #include +#include typedef void(ion_physical_heap_allocate_callback)(struct samsung_dma_buffer *buffer, void *ctx); @@ -15,3 +16,15 @@ struct dma_heap *ion_physical_heap_create(phys_addr_t base, size_t size, ion_physical_heap_allocate_callback alloc_cb, ion_physical_heap_free_callback free_cb, void *ctx); + +struct ion_physical_heap { + struct gen_pool *pool; + phys_addr_t base; + size_t size; + + ion_physical_heap_allocate_callback *allocate_cb; + void *allocate_ctx; + + ion_physical_heap_free_callback *free_cb; + void *free_ctx; +}; -- cgit v1.2.3