[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAEHp+Gasm2ZuYPusn1ZsMuePpjV0atutVGTr9n3-DT=tQODYkQ@mail.gmail.com>
Date: Sun, 26 Jan 2025 10:09:10 +0100
From: Dima Stepanov <dstepanov.src@...il.com>
To: Christoph Hellwig <hch@....de>, Marek Szyprowski <m.szyprowski@...sung.com>,
Robin Murphy <robin.murphy@....com>, iommu@...ts.linux.dev, linux-kernel@...r.kernel.org
Cc: Dima Stepanov <dstepanov.src@...il.com>
Subject: [PATCH] kernel/dma: dma_common_find_pages returns pages for requested address
Recently hit an issue on an attempt to mmap allocated DMA memory to the
user space. It isn't the case for any device, but only if dma_mmap_attrs
call will use the iommu_dma_mmap() function as a backend.
If the kernel address (cpu_addr) passed to the iommu_dma_mmap function
is the same as returned by allocator (dma_alloc_coherent) then memory
will be mapped correctly. But if the address passed is inside the
allocated region, then the mapping in the user space will still refer
to the start of the region and not to the middle of it.
The reason for it is the dma_common_find_pages() call, which returns the
very first page of the vm structure regardless of the cpu_addr passed.
The idea for the fix is to return not the first page in the vm
structure, but the page related to the requested cpu_addr.
Signed-off-by: Dima Stepanov <dstepanov.src@...il.com>
---
kernel/dma/remap.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/kernel/dma/remap.c b/kernel/dma/remap.c
index 9e2afad1c615..238fbf2821a6 100644
--- a/kernel/dma/remap.c
+++ b/kernel/dma/remap.c
@@ -9,12 +9,15 @@
struct page **dma_common_find_pages(void *cpu_addr)
{
struct vm_struct *area = find_vm_area(cpu_addr);
+ int i;
if (!area || !(area->flags & VM_DMA_COHERENT))
return NULL;
WARN(area->flags != VM_DMA_COHERENT,
"unexpected flags in area: %p\n", cpu_addr);
- return area->pages;
+ i = (PAGE_ALIGN((uintptr_t)cpu_addr) - (uintptr_t)area->addr) >>
PAGE_SHIFT;
+
+ return &area->pages[i];
}
/*
--
2.43.0
Powered by blists - more mailing lists