GPUCORE-32592 Fix userbuf imports to respect RO memory Fix the pinning stage of userbuf imports to correctly respect RO memory for both CPU and GPU write access, not just GPU access. Hence, a userbuf that is read-write at import time but then read-only at map time (by munmap() and then mmap() a different mapping at exactly the same address) will properly respect the read-only permissions. In addition, ensure we mark the pages as dirty for both CPU writes as well as GPU writes. Signed-off-by: Sean Callanan <spyffe@google.com> Change-Id: I3eb899277705b82aa344355cd1d2cd5f343ccfff
diff --git a/mali_kbase/mali_kbase_mem.c b/mali_kbase/mali_kbase_mem.c index 4b9721f..a2407a0 100644 --- a/mali_kbase/mali_kbase_mem.c +++ b/mali_kbase/mali_kbase_mem.c
@@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2010-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2010-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -1683,7 +1683,8 @@ /* The allocation could still have active mappings. */ if (user_buf->current_mapping_usage_count == 0) { kbase_jd_user_buf_unmap(kctx, reg->gpu_alloc, - (reg->flags & KBASE_REG_GPU_WR)); + (reg->flags & (KBASE_REG_CPU_WR | + KBASE_REG_GPU_WR))); } } } @@ -4561,6 +4562,7 @@ struct mm_struct *mm = alloc->imported.user_buf.mm; long pinned_pages; long i; + int write; if (WARN_ON(alloc->type != KBASE_MEM_TYPE_IMPORTED_USER_BUF)) return -EINVAL; @@ -4575,41 +4577,37 @@ if (WARN_ON(reg->gpu_alloc->imported.user_buf.mm != current->mm)) return -EINVAL; + write = reg->flags & (KBASE_REG_CPU_WR | KBASE_REG_GPU_WR); + #if KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE - pinned_pages = get_user_pages(NULL, mm, - address, - alloc->imported.user_buf.nr_pages, + pinned_pages = get_user_pages( + NULL, mm, address, + alloc->imported.user_buf.nr_pages, #if KERNEL_VERSION(4, 4, 168) <= LINUX_VERSION_CODE && \ KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE - reg->flags & KBASE_REG_GPU_WR ? FOLL_WRITE : 0, - pages, NULL); + write ? FOLL_WRITE : 0, pages, NULL); #else - reg->flags & KBASE_REG_GPU_WR, - 0, pages, NULL); + write, 0, pages, NULL); #endif #elif KERNEL_VERSION(4, 9, 0) > LINUX_VERSION_CODE - pinned_pages = get_user_pages_remote(NULL, mm, - address, - alloc->imported.user_buf.nr_pages, - reg->flags & KBASE_REG_GPU_WR, - 0, pages, NULL); + pinned_pages = get_user_pages_remote( + NULL, mm, + address, alloc->imported.user_buf.nr_pages, + write, 0, pages, NULL); #elif KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE - pinned_pages = get_user_pages_remote(NULL, mm, - address, - alloc->imported.user_buf.nr_pages, - reg->flags & KBASE_REG_GPU_WR ? FOLL_WRITE : 0, - pages, NULL); + pinned_pages = get_user_pages_remote( + NULL, mm, + address, alloc->imported.user_buf.nr_pages, + write ? FOLL_WRITE : 0, pages, NULL); #elif KERNEL_VERSION(5, 9, 0) > LINUX_VERSION_CODE - pinned_pages = get_user_pages_remote(NULL, mm, - address, - alloc->imported.user_buf.nr_pages, - reg->flags & KBASE_REG_GPU_WR ? FOLL_WRITE : 0, - pages, NULL, NULL); + pinned_pages = get_user_pages_remote( + NULL, mm, + address, alloc->imported.user_buf.nr_pages, + write ? FOLL_WRITE : 0, pages, NULL, NULL); #else pinned_pages = pin_user_pages_remote( mm, address, alloc->imported.user_buf.nr_pages, - reg->flags & KBASE_REG_GPU_WR ? FOLL_WRITE : 0, pages, NULL, - NULL); + write ? FOLL_WRITE : 0, pages, NULL, NULL); #endif if (pinned_pages <= 0) @@ -4843,7 +4841,7 @@ kbase_reg_current_backed_size(reg), kctx->as_nr); - if (reg && ((reg->flags & KBASE_REG_GPU_WR) == 0)) + if (reg && ((reg->flags & (KBASE_REG_CPU_WR | KBASE_REG_GPU_WR)) == 0)) writeable = false; kbase_jd_user_buf_unmap(kctx, alloc, writeable);