ARM: 8546/1: dma-mapping: refactor to fix coherent+cma+gfp=0
authorRabin Vincent <rabin@rab.in>
Thu, 3 Mar 2016 14:58:01 +0000 (15:58 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Fri, 4 Mar 2016 23:35:17 +0000 (23:35 +0000)
commitb42686761219036ace45192476d8ab64d86a4ece
tree5334214ff670cb2e0f4e0832b1de4d063e56f2ea
parent19e6e5e5392bd646c93d9e2c7b2b58c8558cb041
ARM: 8546/1: dma-mapping: refactor to fix coherent+cma+gfp=0

Given a device which uses arm_coherent_dma_ops and on which
dev_get_cma_area(dev) returns non-NULL, the following usage of the DMA
API with gfp=0 results in memory corruption and a memory leak.

 p = dma_alloc_coherent(dev, sz, &dma, 0);
 if (p)
  dma_free_coherent(dev, sz, p, dma);

The memory leak is because the alloc allocates using
__alloc_simple_buffer() but the free attempts
dma_release_from_contiguous() which does not do free anything since the
page is not in the CMA area.

The memory corruption is because the free calls __dma_remap() on a page
which is backed by only first level page tables.  The
apply_to_page_range() + __dma_update_pte() loop ends up interpreting the
section mapping as an addresses to a second level page table and writing
the new PTE to memory which is not used by page tables.

We don't have access to the GFP flags used for allocation in the free
function.  Fix this by adding allocator backends and using this
information in the free function so that we always use the correct
release routine.

Fixes: 21caf3a7 ("ARM: 8398/1: arm DMA: Fix allocation from CMA for coherent DMA")
Signed-off-by: Rabin Vincent <rabin.vincent@axis.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/mm/dma-mapping.c