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 <ljonas@google.com>
This commit is contained in:
Jonas Larsson
2020-03-05 14:19:38 -08:00
committed by Leonid Lobachev
parent 0d361c0493
commit fa575cdad7

View File

@@ -508,6 +508,7 @@ static int gasket_perform_mapping(struct gasket_page_table *pg_tbl,
dma_addr_t dma_addr; dma_addr_t dma_addr;
ulong page_addr; ulong page_addr;
int i; int i;
enum dma_data_direction direction;
/* Must have a virtual host address or a sg iterator, but not both. */ /* Must have a virtual host address or a sg iterator, but not both. */
if(!((uintptr_t)host_addr ^ (uintptr_t)sg_iter)) { 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; 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", dev_err(pg_tbl->device, "invalid DMA direction flags=0x%lx\n",
(unsigned long)flags); (unsigned long)flags);
return -EINVAL; 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 + ptes[i].dma_addr = pg_tbl->coherent_pages[0].paddr +
off + i * PAGE_SIZE; off + i * PAGE_SIZE;
} else { } 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); &page);
if (ret <= 0) { if (ret <= 0) {