From fa575cdad7a6e653f791531c990c1e768571fb2f Mon Sep 17 00:00:00 2001 From: Jonas Larsson Date: Thu, 5 Mar 2020 14:19:38 -0800 Subject: [PATCH] staging: gasket: don't require all pages to be writable Buffers to be mapped as DMA_TO_DEVICE must be writable due to the 'write' argument to get_user_pages_fast being hard coded to 1. This prevents userspace from passing in pointers returned from mmap(fd, PROT_READ), instead mmap(fd, PROT_READ | PROT_WRITE) must be used even if the buffer is supposed to be read only. Instead set writable to non zero iff direction != DMA_TO_DEVICE, ie only buffers with DMA_FROM_DEVICE or DMA_BIDIRECTIONAL are required to be writable. Change-Id: I21c97b2bb855e11ecaa6ae9e81cf8b463b4aedaa Signed-off-by: Jonas Larsson --- gasket_page_table.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/gasket_page_table.c b/gasket_page_table.c index 5ae2024..0740c72 100644 --- a/gasket_page_table.c +++ b/gasket_page_table.c @@ -508,6 +508,7 @@ static int gasket_perform_mapping(struct gasket_page_table *pg_tbl, dma_addr_t dma_addr; ulong page_addr; int i; + enum dma_data_direction direction; /* Must have a virtual host address or a sg iterator, but not both. */ if(!((uintptr_t)host_addr ^ (uintptr_t)sg_iter)) { @@ -515,7 +516,8 @@ static int gasket_perform_mapping(struct gasket_page_table *pg_tbl, return -EINVAL; } - if (GET(FLAGS_DMA_DIRECTION, flags) == DMA_NONE) { + direction = GET(FLAGS_DMA_DIRECTION, flags); + if (direction == DMA_NONE) { dev_err(pg_tbl->device, "invalid DMA direction flags=0x%lx\n", (unsigned long)flags); return -EINVAL; @@ -542,7 +544,8 @@ static int gasket_perform_mapping(struct gasket_page_table *pg_tbl, ptes[i].dma_addr = pg_tbl->coherent_pages[0].paddr + off + i * PAGE_SIZE; } else { - ret = get_user_pages_fast(page_addr - offset, 1, 1, + ret = get_user_pages_fast(page_addr - offset, 1, + direction != DMA_TO_DEVICE, &page); if (ret <= 0) {