gpu: ion: Fix bug in ion_system_heap map_user
authorRebecca Schultz Zavin <rebecca@android.com>
Tue, 23 Oct 2012 17:47:04 +0000 (10:47 -0700)
committerArve Hjønnevåg <arve@android.com>
Mon, 1 Jul 2013 21:16:12 +0000 (14:16 -0700)
When the requested mmap length was not an integer number of
chunks or the buffer, or if an offset was provided, a bug
would cause extra or incorrect pages of the buffer to be mapped.

Change-Id: I2766763d86048f026eeef0e0388b7de0e25c2093
Signed-off-by: Rebecca Schultz Zavin <rebecca@android.com>
drivers/gpu/ion/ion_system_heap.c

index 26e6bbcda7020a8b046bdc93e0f2139bc65b4907..dfa9543ab79a5d342057b571666b1103fcabb654 100644 (file)
@@ -292,18 +292,27 @@ int ion_system_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer,
 {
        struct sg_table *table = buffer->priv_virt;
        unsigned long addr = vma->vm_start;
-       unsigned long offset = vma->vm_pgoff;
+       unsigned long offset = vma->vm_pgoff * PAGE_SIZE;
        struct scatterlist *sg;
        int i;
 
        for_each_sg(table->sgl, sg, table->nents, i) {
-               if (offset) {
-                       offset--;
+               struct page *page = sg_page(sg);
+               unsigned long remainder = vma->vm_end - addr;
+               unsigned long len = sg_dma_len(sg);
+
+               if (offset >= sg_dma_len(sg)) {
+                       offset -= sg_dma_len(sg);
                        continue;
+               } else if (offset) {
+                       page += offset / PAGE_SIZE;
+                       len = sg_dma_len(sg) - offset;
+                       offset = 0;
                }
-               remap_pfn_range(vma, addr, page_to_pfn(sg_page(sg)),
-                               sg_dma_len(sg), vma->vm_page_prot);
-               addr += sg_dma_len(sg);
+               len = min(len, remainder);
+               remap_pfn_range(vma, addr, page_to_pfn(page), len,
+                               vma->vm_page_prot);
+               addr += len;
                if (addr >= vma->vm_end)
                        return 0;
        }