lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<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

Powered by Openwall GNU/*/Linux Powered by OpenVZ