diff options
-rw-r--r-- | Kernel/Syscalls/mmap.cpp | 17 |
1 files changed, 10 insertions, 7 deletions
diff --git a/Kernel/Syscalls/mmap.cpp b/Kernel/Syscalls/mmap.cpp index cfe775c20c..45527868ae 100644 --- a/Kernel/Syscalls/mmap.cpp +++ b/Kernel/Syscalls/mmap.cpp @@ -69,7 +69,7 @@ static bool should_make_executable_exception_for_dynamic_loader(bool make_readab return true; } -static bool validate_mmap_prot(int prot, bool map_stack, bool map_anonymous, Memory::Region const* region = nullptr) +static bool validate_mmap_prot(const Process& process, int prot, bool map_stack, bool map_anonymous, Memory::Region const* region = nullptr) { bool make_readable = prot & PROT_READ; bool make_writable = prot & PROT_WRITE; @@ -78,10 +78,13 @@ static bool validate_mmap_prot(int prot, bool map_stack, bool map_anonymous, Mem if (map_anonymous && make_executable) return false; - if (make_writable && make_executable) + if (map_stack && make_executable) return false; - if (map_stack && make_executable) + if (executable()->mount_flags() & MS_WXALLOWED) + return true; + + if (make_writable && make_executable) return false; if (region) { @@ -177,7 +180,7 @@ ErrorOr<FlatPtr> Process::sys$mmap(Userspace<const Syscall::SC_mmap_params*> use if ((map_fixed || map_fixed_noreplace) && map_randomized) return EINVAL; - if (!validate_mmap_prot(prot, map_stack, map_anonymous)) + if (!validate_mmap_prot(*this, prot, map_stack, map_anonymous)) return EINVAL; if (map_stack && (!map_private || !map_anonymous)) @@ -270,7 +273,7 @@ ErrorOr<FlatPtr> Process::sys$mprotect(Userspace<void*> addr, size_t size, int p if (auto* whole_region = address_space().find_region_from_range(range_to_mprotect)) { if (!whole_region->is_mmap()) return EPERM; - if (!validate_mmap_prot(prot, whole_region->is_stack(), whole_region->vmobject().is_anonymous(), whole_region)) + if (!validate_mmap_prot(*this, prot, whole_region->is_stack(), whole_region->vmobject().is_anonymous(), whole_region)) return EINVAL; if (whole_region->access() == Memory::prot_to_region_access_flags(prot)) return 0; @@ -290,7 +293,7 @@ ErrorOr<FlatPtr> Process::sys$mprotect(Userspace<void*> addr, size_t size, int p if (auto* old_region = address_space().find_region_containing(range_to_mprotect)) { if (!old_region->is_mmap()) return EPERM; - if (!validate_mmap_prot(prot, old_region->is_stack(), old_region->vmobject().is_anonymous(), old_region)) + if (!validate_mmap_prot(*this, prot, old_region->is_stack(), old_region->vmobject().is_anonymous(), old_region)) return EINVAL; if (old_region->access() == Memory::prot_to_region_access_flags(prot)) return 0; @@ -330,7 +333,7 @@ ErrorOr<FlatPtr> Process::sys$mprotect(Userspace<void*> addr, size_t size, int p for (const auto* region : regions) { if (!region->is_mmap()) return EPERM; - if (!validate_mmap_prot(prot, region->is_stack(), region->vmobject().is_anonymous(), region)) + if (!validate_mmap_prot(*this, prot, region->is_stack(), region->vmobject().is_anonymous(), region)) return EINVAL; if (region->vmobject().is_inode() && !validate_inode_mmap_prot(*this, prot, static_cast<Memory::InodeVMObject const&>(region->vmobject()).inode(), region->is_shared())) { |