summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2019-07-08 11:51:56 -0700
committerSasha Levin <sashal@kernel.org>2019-08-25 10:10:25 -0400
commit3d0ed0e4fafd9255fbb338c3cf22cdb123ef7645 (patch)
treecd69da88dbab91932c631f8c70d827d6b9d7346d /kernel
parent1c9de345f7dafbd9c211407c1483d08fc564b09d (diff)
downloadlinux-stable-3d0ed0e4fafd9255fbb338c3cf22cdb123ef7645.tar.gz
linux-stable-3d0ed0e4fafd9255fbb338c3cf22cdb123ef7645.tar.bz2
linux-stable-3d0ed0e4fafd9255fbb338c3cf22cdb123ef7645.zip
dma-mapping: check pfn validity in dma_common_{mmap,get_sgtable}
[ Upstream commit 66d7780f18eae0232827fcffeaded39a6a168236 ] Check that the pfn returned from arch_dma_coherent_to_pfn refers to a valid page and reject the mmap / get_sgtable requests otherwise. Based on the arm implementation of the mmap and get_sgtable methods. Signed-off-by: Christoph Hellwig <hch@lst.de> Tested-by: Vignesh Raghavendra <vigneshr@ti.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/dma/mapping.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c
index f7afdadb6770..3401382bbca2 100644
--- a/kernel/dma/mapping.c
+++ b/kernel/dma/mapping.c
@@ -116,11 +116,16 @@ int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt,
int ret;
if (!dev_is_dma_coherent(dev)) {
+ unsigned long pfn;
+
if (!IS_ENABLED(CONFIG_ARCH_HAS_DMA_COHERENT_TO_PFN))
return -ENXIO;
- page = pfn_to_page(arch_dma_coherent_to_pfn(dev, cpu_addr,
- dma_addr));
+ /* If the PFN is not valid, we do not have a struct page */
+ pfn = arch_dma_coherent_to_pfn(dev, cpu_addr, dma_addr);
+ if (!pfn_valid(pfn))
+ return -ENXIO;
+ page = pfn_to_page(pfn);
} else {
page = virt_to_page(cpu_addr);
}
@@ -170,7 +175,11 @@ int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
if (!dev_is_dma_coherent(dev)) {
if (!IS_ENABLED(CONFIG_ARCH_HAS_DMA_COHERENT_TO_PFN))
return -ENXIO;
+
+ /* If the PFN is not valid, we do not have a struct page */
pfn = arch_dma_coherent_to_pfn(dev, cpu_addr, dma_addr);
+ if (!pfn_valid(pfn))
+ return -ENXIO;
} else {
pfn = page_to_pfn(virt_to_page(cpu_addr));
}