mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 3/3] ARM: dma-mapping: fix array out of bound access
@ 2012-02-17 15:56 Ajeet Yadav
  2012-02-17 17:19 ` Russell King - ARM Linux
  0 siblings, 1 reply; 4+ messages in thread
From: Ajeet Yadav @ 2012-02-17 15:56 UTC (permalink / raw)
  To: Russell King, Jon Medhurst, Nicolas Pitre, Catalin Marinas,
	Sumit Bhattacharya, linux-arm-kernel, linux-kernel
  Cc: Ajeet Yadav, Naveen Yadav

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 <yad.naveen@gmail.com>
Signed-off-by: Ajeet Yadav <ajeet.yadav.77@gmail.com>
---
 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


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 3/3] ARM: dma-mapping: fix array out of bound access
  2012-02-17 15:56 [PATCH 3/3] ARM: dma-mapping: fix array out of bound access Ajeet Yadav
@ 2012-02-17 17:19 ` Russell King - ARM Linux
       [not found]   ` <CAB4K4y65c+UdPMpZNSKKhz3fQO1C6no5SnMAsirQ3LvrAk3gpA@mail.gmail.com>
       [not found]   ` <CAB4K4y7maT1ZQSPKXq6SAng+8fXOFV1kyzVC7AiJGCmgMu5MDg@mail.gmail.com>
  0 siblings, 2 replies; 4+ messages in thread
From: Russell King - ARM Linux @ 2012-02-17 17:19 UTC (permalink / raw)
  To: Ajeet Yadav
  Cc: Jon Medhurst, Nicolas Pitre, Catalin Marinas, Sumit Bhattacharya,
	linux-arm-kernel, linux-kernel, Naveen Yadav

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.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 3/3] ARM: dma-mapping: fix array out of bound access
       [not found]   ` <CAB4K4y65c+UdPMpZNSKKhz3fQO1C6no5SnMAsirQ3LvrAk3gpA@mail.gmail.com>
@ 2012-02-17 17:51     ` Russell King - ARM Linux
  0 siblings, 0 replies; 4+ messages in thread
From: Russell King - ARM Linux @ 2012-02-17 17:51 UTC (permalink / raw)
  To: Ajeet Yadav
  Cc: Nicolas Pitre, Sumit Bhattacharya, linux-kernel,
	linux-arm-kernel, Catalin Marinas, Jon Medhurst, Naveen Yadav

On Fri, Feb 17, 2012 at 11:06:10PM +0530, Ajeet Yadav wrote:
> ok lets consider case that we are accessing last page of last memory mapped
> region and now analyse the for loop we will hit this case

So, come on.  Where's your analysis?

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 3/3] ARM: dma-mapping: fix array out of bound access
       [not found]   ` <CAB4K4y7maT1ZQSPKXq6SAng+8fXOFV1kyzVC7AiJGCmgMu5MDg@mail.gmail.com>
@ 2012-02-22 11:21     ` Ajeet Yadav
  0 siblings, 0 replies; 4+ messages in thread
From: Ajeet Yadav @ 2012-02-22 11:21 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Jon Medhurst, Nicolas Pitre, Catalin Marinas, Sumit Bhattacharya,
	linux-arm-kernel, linux-kernel, Naveen Yadav

 My old replies were from mobile messenger, hence were short, would say sorry
 for the same.
 Please find my response below

 On Fri, Feb 17, 2012 at 10:49 PM, Russell King - ARM Linux
 <linux@arm.linux.org.uk> wrote:
> 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.

 True, so offset can be off = (PTRS_PER_PTE - 1);
 And say idx = CONSISTENT_PTE_INDEX(c->vm_start); provide us with last vaild
 element in consistent_pte[];
 Also __dma_alloc_remap() request 1 page, i.e size =  PAGE_SIZE.

 Because size, off, idx are vaild values with respect to consistent mapping
 region, and its a do{}while loop, so it will exit loop after first pass. All
 fine

 But their is a catch, we do off++, so
 do{
         do_all_important_stuff
         off++;        >>>>>>>>>>>>>>>>>>>>>>>>>>> now off = PTRS_PER_PTE
           if (off >= PTRS_PER_PTE) {                 >>>>>> condition TRUE
                off = 0;
                pte = consistent_pte[++idx];         >>>>> we did idx++ but
idx was already pointing to last element, so we are trying to access array
 out of bound
          }
 } while (size -= PAGE_SIZE);                      >>>>>>> conditon FALSE,
 but its too late

 The proposed solution, do off++ but move the rest i.e if body from last to
 begining of do{}while.
 In this case we will prevent out of bound acess, without effecting the flow
 on first entry and also exit from do{}while loop.
 Moving the if body to begining of do{}while ensured that on first entry to
 do{}while loop the if condition fails hence not effecting the first entry
 condition.
 on subsequent iternation of do{}while loop the while condition will be
 checked before we execute the if conditon.

 Given functions __dma_alloc_remap()/ __dma_free_remap() already haves
 necessary checks to ensure that size is valid, so again if we analyse from
 given example

 do{
           if (off >= PTRS_PER_PTE) {                 >>>>>> condition FALSE
                off = 0;
                pte = consistent_pte[++idx];           >>>>>> we avoid
 this
          }
         do_all_important_stuff
         off++;        >>>>>>>>>>>>>>>>>>>>>>>>>>> now off = PTRS_PER_PTE
 } while (size -= PAGE_SIZE);                       >>>>>>> condition FAILS,
 we exit the do{}while, effectively prevented the out of bound access of
 consistent_pte[]

  NOTE: size is valid so, in proposed solution while conditon is effectively
 preventing the out of bound array access to occur.
  If we review the code from normal access point of view, we are not changing
 any flow logic, also after the exit from do{}while no access to off, idx is
 performed
 So we do not need to worry about post do{}while statments.

>
> 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.
>
>

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2012-02-22 11:21 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-02-17 15:56 [PATCH 3/3] ARM: dma-mapping: fix array out of bound access Ajeet Yadav
2012-02-17 17:19 ` Russell King - ARM Linux
     [not found]   ` <CAB4K4y65c+UdPMpZNSKKhz3fQO1C6no5SnMAsirQ3LvrAk3gpA@mail.gmail.com>
2012-02-17 17:51     ` Russell King - ARM Linux
     [not found]   ` <CAB4K4y7maT1ZQSPKXq6SAng+8fXOFV1kyzVC7AiJGCmgMu5MDg@mail.gmail.com>
2012-02-22 11:21     ` Ajeet Yadav

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®