[PATCH 3/3] ARM: dma-mapping: fix array out of bound access

Subsystems: arm port, the rest

STALE5286d

2 messages, 2 authors, 2012-02-17 · open the first message on its own page

[PATCH 3/3] ARM: dma-mapping: fix array out of bound access

From: Ajeet Yadav <hidden>
Date: 2012-02-17 15:55:07

In __dma_alloc_remap(*,size,*,*)/ __dma_free_remap(*,size) functions
if virtual address is in the last consistent mapping region
i.e idx == ((CONSISTENT_END - base) >> PMD_SHIFT) - 1
and off == PTRS_PER_PTE.
then we have array out of bound access condition.

On entry to while loop we ensure that off is always < PTRS_PER_PTE
via
u32 off = CONSISTENT_OFFSET(c->vm_start) & (PTRS_PER_PTE-1);

therefore we can safely move that condition to begining of while
loop, to ensure that we access consistent_pte[] only if
while condition is true.

Signed-off-by: Naveen Yadav <redacted>
Signed-off-by: Ajeet Yadav <redacted>
---
 arch/arm/mm/dma-mapping.c |   19 +++++++++----------
 1 files changed, 9 insertions(+), 10 deletions(-)
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 932d288..0e1a2a2 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -251,16 +251,16 @@ __dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot)
 		c->vm_pages = page;
 
 		do {
+			if (off >= PTRS_PER_PTE) {
+				off = 0;
+				pte = consistent_pte[++idx];
+			}
 			BUG_ON(!pte_none(*pte));
 
 			set_pte_ext(pte, mk_pte(page, prot), 0);
 			page++;
 			pte++;
 			off++;
-			if (off >= PTRS_PER_PTE) {
-				off = 0;
-				pte = consistent_pte[++idx];
-			}
 		} while (size -= PAGE_SIZE);
 
 		dsb();
@@ -275,6 +275,7 @@ static void __dma_free_remap(void *cpu_addr, size_t size)
 	struct arm_vmregion *c;
 	unsigned long addr;
 	pte_t *ptep;
+	pte_t pte;
 	int idx;
 	u32 off;
 
@@ -298,16 +299,14 @@ static void __dma_free_remap(void *cpu_addr, size_t size)
 	ptep = consistent_pte[idx] + off;
 	addr = c->vm_start;
 	do {
-		pte_t pte = ptep_get_and_clear(&init_mm, addr, ptep);
-
-		ptep++;
-		addr += PAGE_SIZE;
-		off++;
 		if (off >= PTRS_PER_PTE) {
 			off = 0;
 			ptep = consistent_pte[++idx];
 		}
-
+		pte = ptep_get_and_clear(&init_mm, addr, ptep);
+		ptep++;
+		addr += PAGE_SIZE;
+		off++;
 		if (pte_none(pte) || !pte_present(pte))
 			printk(KERN_CRIT "%s: bad page in kernel page table\n",
 			       __func__);
-- 
1.7.8.4

Re: [PATCH 3/3] ARM: dma-mapping: fix array out of bound access

From: Russell King - ARM Linux <hidden>
Date: 2012-02-17 17:19:47

On Fri, Feb 17, 2012 at 09:26:00PM +0530, Ajeet Yadav wrote:
In __dma_alloc_remap(*,size,*,*)/ __dma_free_remap(*,size) functions
if virtual address is in the last consistent mapping region
i.e idx == ((CONSISTENT_END - base) >> PMD_SHIFT) - 1
and off == PTRS_PER_PTE.
then we have array out of bound access condition.
How?  Where?

At the first loop, off will _never_ be PTRS_PER_PTE.

                u32 off = CONSISTENT_OFFSET(c->vm_start) & (PTRS_PER_PTE-1);

There is _absolutely_ _no_ _way_ that off could ever be PTRS_PER_PTE
here.

If 'base' is CONSISTENT_END, then we have far bigger problems, because
it means that we have a zero sized region - it certainly can't be any
larger than zero size because then we'd be overflowing the DMA region
into something else.

Plus, we know that 'end of region' allocations work fine, because the
code allocates from the top of the region downwards.

So, I don't think there's a problem here.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help