1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-23 06:47:40 +00:00

Kernel: Add a random offset to the base of the per-process VM allocator

This is not ASLR, but it does de-trivialize exploiting the ELF loader
which would previously always parse executables at 0x01001000 in every
single exec(). I've taken advantage of this multiple times in my own
toy exploits and it's starting to feel cheesy. :^)
This commit is contained in:
Andreas Kling 2020-01-17 23:05:37 +01:00
parent 536c0ff3ee
commit a850a89c1b
3 changed files with 25 additions and 8 deletions

View file

@ -1,9 +1,11 @@
#include <Kernel/Process.h> #include <Kernel/Process.h>
#include <Kernel/Random.h>
#include <Kernel/Thread.h> #include <Kernel/Thread.h>
#include <Kernel/VM/MemoryManager.h> #include <Kernel/VM/MemoryManager.h>
#include <Kernel/VM/PageDirectory.h> #include <Kernel/VM/PageDirectory.h>
static const u32 userspace_range_base = 0x01000000; static const u32 userspace_range_base = 0x00800000;
static const u32 userspace_range_ceiling = 0xbe000000;
static const u32 kernelspace_range_base = 0xc0800000; static const u32 kernelspace_range_base = 0xc0800000;
static HashMap<u32, PageDirectory*>& cr3_map() static HashMap<u32, PageDirectory*>& cr3_map()
@ -26,8 +28,9 @@ extern "C" PageDirectoryEntry boot_pd0[1024];
extern "C" PageDirectoryEntry boot_pd3[1024]; extern "C" PageDirectoryEntry boot_pd3[1024];
PageDirectory::PageDirectory() PageDirectory::PageDirectory()
: m_range_allocator(VirtualAddress(0xc0c00000), 0x3f000000)
{ {
m_range_allocator.initialize_with_range(VirtualAddress(0xc0800000), 0x3f000000);
// Adopt the page tables already set up by boot.S // Adopt the page tables already set up by boot.S
PhysicalAddress boot_pdpt_paddr(virtual_to_low_physical((u32)boot_pdpt)); PhysicalAddress boot_pdpt_paddr(virtual_to_low_physical((u32)boot_pdpt));
PhysicalAddress boot_pd0_paddr(virtual_to_low_physical((u32)boot_pd0)); PhysicalAddress boot_pd0_paddr(virtual_to_low_physical((u32)boot_pd0));
@ -42,8 +45,15 @@ PageDirectory::PageDirectory()
PageDirectory::PageDirectory(Process& process, const RangeAllocator* parent_range_allocator) PageDirectory::PageDirectory(Process& process, const RangeAllocator* parent_range_allocator)
: m_process(&process) : m_process(&process)
, m_range_allocator(parent_range_allocator ? RangeAllocator(*parent_range_allocator) : RangeAllocator(VirtualAddress(userspace_range_base), kernelspace_range_base - userspace_range_base))
{ {
if (parent_range_allocator) {
m_range_allocator.initialize_from_parent(*parent_range_allocator);
} else {
size_t random_offset = (get_good_random<u32>() % 32 * MB) & PAGE_MASK;
u32 base = userspace_range_base + random_offset;
m_range_allocator.initialize_with_range(VirtualAddress(base), userspace_range_ceiling - base);
}
// Set up a userspace page directory // Set up a userspace page directory
m_directory_table = MM.allocate_user_physical_page(); m_directory_table = MM.allocate_user_physical_page();
m_directory_pages[0] = MM.allocate_user_physical_page(); m_directory_pages[0] = MM.allocate_user_physical_page();

View file

@ -1,11 +1,16 @@
#include <AK/QuickSort.h> #include <AK/QuickSort.h>
#include <Kernel/Random.h>
#include <Kernel/VM/RangeAllocator.h> #include <Kernel/VM/RangeAllocator.h>
#include <Kernel/kstdio.h> #include <Kernel/kstdio.h>
//#define VRA_DEBUG //#define VRA_DEBUG
#define VM_GUARD_PAGES #define VM_GUARD_PAGES
RangeAllocator::RangeAllocator(VirtualAddress base, size_t size) RangeAllocator::RangeAllocator()
{
}
void RangeAllocator::initialize_with_range(VirtualAddress base, size_t size)
{ {
m_available_ranges.append({ base, size }); m_available_ranges.append({ base, size });
#ifdef VRA_DEBUG #ifdef VRA_DEBUG
@ -13,9 +18,9 @@ RangeAllocator::RangeAllocator(VirtualAddress base, size_t size)
#endif #endif
} }
RangeAllocator::RangeAllocator(const RangeAllocator& parent_allocator) void RangeAllocator::initialize_from_parent(const RangeAllocator& parent_allocator)
: m_available_ranges(parent_allocator.m_available_ranges)
{ {
m_available_ranges = parent_allocator.m_available_ranges;
} }
RangeAllocator::~RangeAllocator() RangeAllocator::~RangeAllocator()

View file

@ -47,10 +47,12 @@ private:
class RangeAllocator { class RangeAllocator {
public: public:
RangeAllocator(VirtualAddress, size_t); RangeAllocator();
RangeAllocator(const RangeAllocator&);
~RangeAllocator(); ~RangeAllocator();
void initialize_with_range(VirtualAddress, size_t);
void initialize_from_parent(const RangeAllocator&);
Range allocate_anywhere(size_t); Range allocate_anywhere(size_t);
Range allocate_specific(VirtualAddress, size_t); Range allocate_specific(VirtualAddress, size_t);
void deallocate(Range); void deallocate(Range);