This is a note to let you know that I've just added the patch titled ARM: dma-mapping: disallow dma_get_sgtable() for non-kernel managed memory to the 4.9-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: arm-dma-mapping-disallow-dma_get_sgtable-for-non-kernel-managed-memory.patch and it can be found in the queue-4.9 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. >From foo@baz Thu Dec 21 09:02:40 CET 2017 From: Russell King <rmk+kernel@xxxxxxxxxxxxxxx> Date: Wed, 29 Mar 2017 17:12:47 +0100 Subject: ARM: dma-mapping: disallow dma_get_sgtable() for non-kernel managed memory From: Russell King <rmk+kernel@xxxxxxxxxxxxxxx> [ Upstream commit 916a008b4b8ecc02fbd035cfb133773dba1ff3d7 ] dma_get_sgtable() tries to create a scatterlist table containing valid struct page pointers for the coherent memory allocation passed in to it. However, memory can be declared via dma_declare_coherent_memory(), or via other reservation schemes which means that coherent memory is not guaranteed to be backed by struct pages. In such cases, the resulting scatterlist table contains pointers to invalid pages, which causes kernel oops later. This patch adds detection of such memory, and refuses to create a scatterlist table for such memory. Reported-by: Shuah Khan <shuahkhan@xxxxxxxxx> Signed-off-by: Russell King <rmk+kernel@xxxxxxxxxxxxxxx> Signed-off-by: Sasha Levin <alexander.levin@xxxxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- arch/arm/mm/dma-mapping.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -930,13 +930,31 @@ static void arm_coherent_dma_free(struct __arm_dma_free(dev, size, cpu_addr, handle, attrs, true); } +/* + * The whole dma_get_sgtable() idea is fundamentally unsafe - it seems + * that the intention is to allow exporting memory allocated via the + * coherent DMA APIs through the dma_buf API, which only accepts a + * scattertable. This presents a couple of problems: + * 1. Not all memory allocated via the coherent DMA APIs is backed by + * a struct page + * 2. Passing coherent DMA memory into the streaming APIs is not allowed + * as we will try to flush the memory through a different alias to that + * actually being used (and the flushes are redundant.) + */ int arm_dma_get_sgtable(struct device *dev, struct sg_table *sgt, void *cpu_addr, dma_addr_t handle, size_t size, unsigned long attrs) { - struct page *page = pfn_to_page(dma_to_pfn(dev, handle)); + unsigned long pfn = dma_to_pfn(dev, handle); + struct page *page; int ret; + /* If the PFN is not valid, we do not have a struct page */ + if (!pfn_valid(pfn)) + return -ENXIO; + + page = pfn_to_page(pfn); + ret = sg_alloc_table(sgt, 1, GFP_KERNEL); if (unlikely(ret)) return ret; Patches currently in stable-queue which might be from rmk+kernel@xxxxxxxxxxxxxxx are queue-4.9/arm-dma-mapping-disallow-dma_get_sgtable-for-non-kernel-managed-memory.patch queue-4.9/rtc-pl031-make-interrupt-optional.patch