From 3dc87be8917d9f4d16cc1f737b652ed2cf58c3fa Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 24 Nov 2019 12:24:16 +0100 Subject: [PATCH] Kernel: Mark mmap()-created regions with a special bit Then only allow regions with that bit to be manipulated via munmap() and mprotect(). This prevents messing with non-mmap()ed regions in a process's address space (stacks, shared buffers, ...) --- Kernel/Process.cpp | 10 ++++++++++ Kernel/VM/Region.h | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 802aa6c8b4..79127fa097 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -188,6 +188,8 @@ int Process::sys$set_mmap_name(void* addr, size_t size, const char* name) auto* region = region_from_range({ VirtualAddress((u32)addr), size }); if (!region) return -EINVAL; + if (!region->is_mmap()) + return -EPERM; region->set_name(String(name)); return 0; } @@ -225,6 +227,7 @@ void* Process::sys$mmap(const Syscall::SC_mmap_params* params) region->set_shared(true); if (flags & MAP_STACK) region->set_stack(true); + region->set_mmap(true); return region->vaddr().as_ptr(); } if (offset & ~PAGE_MASK) @@ -240,6 +243,7 @@ void* Process::sys$mmap(const Syscall::SC_mmap_params* params) region->set_shared(true); if (name) region->set_name(name); + region->set_mmap(true); return region->vaddr().as_ptr(); } @@ -247,12 +251,16 @@ int Process::sys$munmap(void* addr, size_t size) { Range range_to_unmap { VirtualAddress((u32)addr), size }; if (auto* whole_region = region_from_range(range_to_unmap)) { + if (!whole_region->is_mmap()) + return -EPERM; bool success = deallocate_region(*whole_region); ASSERT(success); return 0; } if (auto* old_region = region_containing(range_to_unmap)) { + if (!old_region->is_mmap()) + return -EPERM; Range old_region_range = old_region->range(); auto remaining_ranges_after_unmap = old_region_range.carve(range_to_unmap); ASSERT(!remaining_ranges_after_unmap.is_empty()); @@ -291,6 +299,8 @@ int Process::sys$mprotect(void* addr, size_t size, int prot) auto* region = region_from_range({ VirtualAddress((u32)addr), size }); if (!region) return -EINVAL; + if (!region->is_mmap()) + return -EPERM; region->set_writable(prot & PROT_WRITE); region->remap(); return 0; diff --git a/Kernel/VM/Region.h b/Kernel/VM/Region.h index 5501e6b2e3..4ea3c2f7fc 100644 --- a/Kernel/VM/Region.h +++ b/Kernel/VM/Region.h @@ -53,6 +53,9 @@ public: bool is_stack() const { return m_stack; } void set_stack(bool stack) { m_stack = stack; } + bool is_mmap() const { return m_mmap; } + void set_mmap(bool mmap) { m_mmap = mmap; } + bool is_user_accessible() const { return m_user_accessible; } PageFaultResponse handle_fault(const PageFault&); @@ -145,5 +148,6 @@ private: bool m_shared { false }; bool m_user_accessible { false }; bool m_stack { false }; + bool m_mmap { false }; mutable OwnPtr m_cow_map; };