diff options
-rw-r--r-- | Kernel/Syscalls/mmap.cpp | 22 | ||||
-rw-r--r-- | Kernel/UnixTypes.h | 1 | ||||
-rw-r--r-- | Kernel/VM/RangeAllocator.cpp | 25 | ||||
-rw-r--r-- | Kernel/VM/RangeAllocator.h | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibC/mman.h | 1 |
5 files changed, 43 insertions, 7 deletions
diff --git a/Kernel/Syscalls/mmap.cpp b/Kernel/Syscalls/mmap.cpp index aa555b71f3..be1ebdf818 100644 --- a/Kernel/Syscalls/mmap.cpp +++ b/Kernel/Syscalls/mmap.cpp @@ -119,6 +119,7 @@ void* Process::sys$mmap(Userspace<const Syscall::SC_mmap_params*> user_params) bool map_stack = flags & MAP_STACK; bool map_fixed = flags & MAP_FIXED; bool map_noreserve = flags & MAP_NORESERVE; + bool map_randomized = flags & MAP_RANDOMIZED; if (map_shared && map_private) return (void*)-EINVAL; @@ -133,16 +134,23 @@ void* Process::sys$mmap(Userspace<const Syscall::SC_mmap_params*> user_params) return (void*)-EINVAL; Region* region = nullptr; - auto range = allocate_range(VirtualAddress(addr), size, alignment); - if (!range.has_value()) { - if (addr && !map_fixed) { - // If there's an address but MAP_FIXED wasn't specified, the address is just a hint. - range = allocate_range({}, size, alignment); + Optional<Range> range; + + if (map_randomized) { + range = page_directory().range_allocator().allocate_randomized(size, alignment); + } else { + range = allocate_range(VirtualAddress(addr), size, alignment); + if (!range.has_value()) { + if (addr && !map_fixed) { + // If there's an address but MAP_FIXED wasn't specified, the address is just a hint. + range = allocate_range({}, size, alignment); + } } - if (!range.has_value()) - return (void*)-ENOMEM; } + if (!range.has_value()) + return (void*)-ENOMEM; + if (map_anonymous) { auto strategy = map_noreserve ? AllocationStrategy::None : AllocationStrategy::Reserve; auto region_or_error = allocate_region(range.value(), !name.is_null() ? name : "mmap", prot, strategy); diff --git a/Kernel/UnixTypes.h b/Kernel/UnixTypes.h index 09c19d0ef4..271d4a45f0 100644 --- a/Kernel/UnixTypes.h +++ b/Kernel/UnixTypes.h @@ -95,6 +95,7 @@ enum { #define MAP_ANON MAP_ANONYMOUS #define MAP_STACK 0x40 #define MAP_NORESERVE 0x80 +#define MAP_RANDOMIZED 0x100 #define PROT_READ 0x1 #define PROT_WRITE 0x2 diff --git a/Kernel/VM/RangeAllocator.cpp b/Kernel/VM/RangeAllocator.cpp index f092962ae8..a61b6d1512 100644 --- a/Kernel/VM/RangeAllocator.cpp +++ b/Kernel/VM/RangeAllocator.cpp @@ -106,6 +106,31 @@ void RangeAllocator::carve_at_index(int index, const Range& range) m_available_ranges.insert(index + 1, move(remaining_parts[1])); } +Optional<Range> RangeAllocator::allocate_randomized(size_t size, size_t alignment) +{ + if (!size) + return {}; + + ASSERT((size % PAGE_SIZE) == 0); + ASSERT((alignment % PAGE_SIZE) == 0); + + // FIXME: I'm sure there's a smarter way to do this. + static constexpr size_t maximum_randomization_attempts = 1000; + for (size_t i = 0; i < maximum_randomization_attempts; ++i) { + VirtualAddress random_address { get_good_random<FlatPtr>() }; + random_address.mask(PAGE_MASK); + + if (!m_total_range.contains(random_address)) + continue; + + auto range = allocate_specific(random_address, size); + if (range.has_value()) + return range; + } + + return allocate_anywhere(size, alignment); +} + Optional<Range> RangeAllocator::allocate_anywhere(size_t size, size_t alignment) { if (!size) diff --git a/Kernel/VM/RangeAllocator.h b/Kernel/VM/RangeAllocator.h index 0839e0bb57..97e58d02ec 100644 --- a/Kernel/VM/RangeAllocator.h +++ b/Kernel/VM/RangeAllocator.h @@ -87,6 +87,7 @@ public: Optional<Range> allocate_anywhere(size_t, size_t alignment = PAGE_SIZE); Optional<Range> allocate_specific(VirtualAddress, size_t); + Optional<Range> allocate_randomized(size_t, size_t alignment); void deallocate(const Range&); void dump() const; diff --git a/Userland/Libraries/LibC/mman.h b/Userland/Libraries/LibC/mman.h index 0d44ee2d9c..0786573785 100644 --- a/Userland/Libraries/LibC/mman.h +++ b/Userland/Libraries/LibC/mman.h @@ -37,6 +37,7 @@ #define MAP_ANON MAP_ANONYMOUS #define MAP_STACK 0x40 #define MAP_NORESERVE 0x80 +#define MAP_RANDOMIZED 0x100 #define PROT_READ 0x1 #define PROT_WRITE 0x2 |