diff options
author | Palmer Dabbelt <palmer@rivosinc.com> | 2022-10-13 22:49:12 +0300 |
---|---|---|
committer | Palmer Dabbelt <palmer@rivosinc.com> | 2022-10-13 22:49:12 +0300 |
commit | 8aeb7b17f04ef40f620c763502e2b644c5c73efd (patch) | |
tree | 41138155d3670d302192e9d8b3cf3f4aeeecac14 /arch/riscv | |
parent | c45fc916c2b2cc2a0587659c18d6ceef9b7299be (diff) | |
parent | 9e2e6042a7ec6504fe8e366717afa2f40cf16488 (diff) | |
download | linux-8aeb7b17f04ef40f620c763502e2b644c5c73efd.tar.xz |
RISC-V: Make mmap() with PROT_WRITE imply PROT_READ
Commit 2139619bcad7 ("riscv: mmap with PROT_WRITE but no PROT_READ is
invalid") made mmap() reject mappings with only PROT_WRITE set in an
attempt to fix an observed inconsistency in behavior when attempting
to read from a PROT_WRITE-only mapping. The root cause of this behavior
was actually that while RISC-V's protection_map maps VM_WRITE to
readable PTE permissions (since write-only PTEs are considered reserved
by the privileged spec), the page fault handler considered loads from
VM_WRITE-only VMAs illegal accesses. Fix the underlying cause by
handling faults in VM_WRITE-only VMAs (patch 1) and then re-enable
use of mmap(PROT_WRITE) (patch 2), making RISC-V's behavior consistent
with all other architectures that don't support write-only PTEs.
* remotes/palmer/riscv-wonly:
riscv: Allow PROT_WRITE-only mmap()
riscv: Make VM_WRITE imply VM_READ
Link: https://lore.kernel.org/r/20220915193702.2201018-1-abrestic@rivosinc.com/
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
Diffstat (limited to 'arch/riscv')
-rw-r--r-- | arch/riscv/kernel/sys_riscv.c | 3 | ||||
-rw-r--r-- | arch/riscv/mm/fault.c | 3 |
2 files changed, 2 insertions, 4 deletions
diff --git a/arch/riscv/kernel/sys_riscv.c b/arch/riscv/kernel/sys_riscv.c index 571556bb9261..5d3f2fbeb33c 100644 --- a/arch/riscv/kernel/sys_riscv.c +++ b/arch/riscv/kernel/sys_riscv.c @@ -18,9 +18,6 @@ static long riscv_sys_mmap(unsigned long addr, unsigned long len, if (unlikely(offset & (~PAGE_MASK >> page_shift_offset))) return -EINVAL; - if (unlikely((prot & PROT_WRITE) && !(prot & PROT_READ))) - return -EINVAL; - return ksys_mmap_pgoff(addr, len, prot, flags, fd, offset >> (PAGE_SHIFT - page_shift_offset)); } diff --git a/arch/riscv/mm/fault.c b/arch/riscv/mm/fault.c index f2fbd1400b7c..d86f7cebd4a7 100644 --- a/arch/riscv/mm/fault.c +++ b/arch/riscv/mm/fault.c @@ -184,7 +184,8 @@ static inline bool access_error(unsigned long cause, struct vm_area_struct *vma) } break; case EXC_LOAD_PAGE_FAULT: - if (!(vma->vm_flags & VM_READ)) { + /* Write implies read */ + if (!(vma->vm_flags & (VM_READ | VM_WRITE))) { return true; } break; |