diff options
author | Andreas Kling <kling@serenityos.org> | 2022-04-03 18:46:27 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-04-03 21:51:58 +0200 |
commit | 858b196c595720a29219ded650c8e20fa5503dd1 (patch) | |
tree | 390555f5e1ccdd1ddeead919e1ed449f9f288411 /Kernel/Memory | |
parent | e89c9ed2cac7f27a3a38e2cad944a7ce50dd00e9 (diff) | |
download | serenity-858b196c595720a29219ded650c8e20fa5503dd1.zip |
Kernel: Unbreak ASLR in the new RegionTree world
Functions that allocate and/or place a Region now take a parameter
that tells it whether to randomize unspecified addresses.
Diffstat (limited to 'Kernel/Memory')
-rw-r--r-- | Kernel/Memory/AddressSpace.cpp | 15 | ||||
-rw-r--r-- | Kernel/Memory/AddressSpace.h | 4 | ||||
-rw-r--r-- | Kernel/Memory/MemoryManager.cpp | 10 | ||||
-rw-r--r-- | Kernel/Memory/RegionTree.cpp | 6 | ||||
-rw-r--r-- | Kernel/Memory/RegionTree.h | 7 |
5 files changed, 24 insertions, 18 deletions
diff --git a/Kernel/Memory/AddressSpace.cpp b/Kernel/Memory/AddressSpace.cpp index 1df5e58e35..c27afa85c5 100644 --- a/Kernel/Memory/AddressSpace.cpp +++ b/Kernel/Memory/AddressSpace.cpp @@ -157,7 +157,7 @@ ErrorOr<Region*> AddressSpace::try_allocate_split_region(Region const& source_re return new_region.leak_ptr(); } -ErrorOr<Region*> AddressSpace::allocate_region(VirtualAddress requested_address, size_t requested_size, size_t requested_alignment, StringView name, int prot, AllocationStrategy strategy) +ErrorOr<Region*> AddressSpace::allocate_region(RandomizeVirtualAddress randomize_virtual_address, VirtualAddress requested_address, size_t requested_size, size_t requested_alignment, StringView name, int prot, AllocationStrategy strategy) { if (!requested_address.is_page_aligned()) return EINVAL; @@ -168,20 +168,21 @@ ErrorOr<Region*> AddressSpace::allocate_region(VirtualAddress requested_address, region_name = TRY(KString::try_create(name)); auto vmobject = TRY(AnonymousVMObject::try_create_with_size(size, strategy)); auto region = TRY(Region::create_unplaced(move(vmobject), 0, move(region_name), prot_to_region_access_flags(prot))); - if (requested_address.is_null()) - TRY(m_region_tree.place_anywhere(*region, size, alignment)); - else + if (requested_address.is_null()) { + TRY(m_region_tree.place_anywhere(*region, randomize_virtual_address, size, alignment)); + } else { TRY(m_region_tree.place_specifically(*region, VirtualRange { requested_address, size })); + } TRY(region->map(page_directory(), ShouldFlushTLB::No)); return region.leak_ptr(); } ErrorOr<Region*> AddressSpace::allocate_region_with_vmobject(VirtualRange requested_range, NonnullRefPtr<VMObject> vmobject, size_t offset_in_vmobject, StringView name, int prot, bool shared) { - return allocate_region_with_vmobject(requested_range.base(), requested_range.size(), PAGE_SIZE, move(vmobject), offset_in_vmobject, name, prot, shared); + return allocate_region_with_vmobject(RandomizeVirtualAddress::Yes, requested_range.base(), requested_range.size(), PAGE_SIZE, move(vmobject), offset_in_vmobject, name, prot, shared); } -ErrorOr<Region*> AddressSpace::allocate_region_with_vmobject(VirtualAddress requested_address, size_t requested_size, size_t requested_alignment, NonnullRefPtr<VMObject> vmobject, size_t offset_in_vmobject, StringView name, int prot, bool shared) +ErrorOr<Region*> AddressSpace::allocate_region_with_vmobject(RandomizeVirtualAddress randomize_virtual_address, VirtualAddress requested_address, size_t requested_size, size_t requested_alignment, NonnullRefPtr<VMObject> vmobject, size_t offset_in_vmobject, StringView name, int prot, bool shared) { if (!requested_address.is_page_aligned()) return EINVAL; @@ -210,7 +211,7 @@ ErrorOr<Region*> AddressSpace::allocate_region_with_vmobject(VirtualAddress requ SpinlockLocker locker(m_lock); if (requested_address.is_null()) - TRY(m_region_tree.place_anywhere(*region, size, alignment)); + TRY(m_region_tree.place_anywhere(*region, randomize_virtual_address, size, alignment)); else TRY(m_region_tree.place_specifically(*region, VirtualRange { VirtualAddress { requested_address }, size })); diff --git a/Kernel/Memory/AddressSpace.h b/Kernel/Memory/AddressSpace.h index 9d314a5869..664dbf36f0 100644 --- a/Kernel/Memory/AddressSpace.h +++ b/Kernel/Memory/AddressSpace.h @@ -36,8 +36,8 @@ public: ErrorOr<void> unmap_mmap_range(VirtualAddress, size_t); ErrorOr<Region*> allocate_region_with_vmobject(VirtualRange requested_range, NonnullRefPtr<VMObject>, size_t offset_in_vmobject, StringView name, int prot, bool shared); - ErrorOr<Region*> allocate_region_with_vmobject(VirtualAddress requested_address, size_t requested_size, size_t requested_alignment, NonnullRefPtr<VMObject>, size_t offset_in_vmobject, StringView name, int prot, bool shared); - ErrorOr<Region*> allocate_region(VirtualAddress requested_address, size_t requested_size, size_t requested_alignment, StringView name, int prot = PROT_READ | PROT_WRITE, AllocationStrategy strategy = AllocationStrategy::Reserve); + ErrorOr<Region*> allocate_region_with_vmobject(RandomizeVirtualAddress, VirtualAddress requested_address, size_t requested_size, size_t requested_alignment, NonnullRefPtr<VMObject>, size_t offset_in_vmobject, StringView name, int prot, bool shared); + ErrorOr<Region*> allocate_region(RandomizeVirtualAddress, VirtualAddress requested_address, size_t requested_size, size_t requested_alignment, StringView name, int prot = PROT_READ | PROT_WRITE, AllocationStrategy strategy = AllocationStrategy::Reserve); void deallocate_region(Region& region); NonnullOwnPtr<Region> take_region(Region& region); diff --git a/Kernel/Memory/MemoryManager.cpp b/Kernel/Memory/MemoryManager.cpp index a14c287d18..e6cc5b7d74 100644 --- a/Kernel/Memory/MemoryManager.cpp +++ b/Kernel/Memory/MemoryManager.cpp @@ -457,7 +457,7 @@ UNMAP_AFTER_INIT void MemoryManager::initialize_physical_pages() // Allocate a virtual address range for our array // This looks awkward, but it basically creates a dummy region to occupy the address range permanently. auto& region = *MUST(Region::create_unbacked()).leak_ptr(); - MUST(m_region_tree.place_anywhere(region, physical_page_array_pages * PAGE_SIZE)); + MUST(m_region_tree.place_anywhere(region, RandomizeVirtualAddress::No, physical_page_array_pages * PAGE_SIZE)); auto range = region.range(); // Now that we have our special m_physical_pages_region region with enough pages to hold the entire array @@ -773,7 +773,7 @@ ErrorOr<NonnullOwnPtr<Region>> MemoryManager::allocate_contiguous_kernel_region( name_kstring = TRY(KString::try_create(name)); auto vmobject = TRY(AnonymousVMObject::try_create_physically_contiguous_with_size(size)); auto region = TRY(Region::create_unplaced(move(vmobject), 0, move(name_kstring), access, cacheable)); - TRY(m_region_tree.place_anywhere(*region, size)); + TRY(m_region_tree.place_anywhere(*region, RandomizeVirtualAddress::No, size)); TRY(region->map(kernel_page_directory())); return region; } @@ -816,7 +816,7 @@ ErrorOr<NonnullOwnPtr<Region>> MemoryManager::allocate_kernel_region(size_t size name_kstring = TRY(KString::try_create(name)); auto vmobject = TRY(AnonymousVMObject::try_create_with_size(size, strategy)); auto region = TRY(Region::create_unplaced(move(vmobject), 0, move(name_kstring), access, cacheable)); - TRY(m_region_tree.place_anywhere(*region, size)); + TRY(m_region_tree.place_anywhere(*region, RandomizeVirtualAddress::No, size)); TRY(region->map(kernel_page_directory())); return region; } @@ -829,7 +829,7 @@ ErrorOr<NonnullOwnPtr<Region>> MemoryManager::allocate_kernel_region(PhysicalAdd if (!name.is_null()) name_kstring = TRY(KString::try_create(name)); auto region = TRY(Region::create_unplaced(move(vmobject), 0, move(name_kstring), access, cacheable)); - TRY(m_region_tree.place_anywhere(*region, size, PAGE_SIZE)); + TRY(m_region_tree.place_anywhere(*region, RandomizeVirtualAddress::No, size, PAGE_SIZE)); TRY(region->map(kernel_page_directory())); return region; } @@ -843,7 +843,7 @@ ErrorOr<NonnullOwnPtr<Region>> MemoryManager::allocate_kernel_region_with_vmobje name_kstring = TRY(KString::try_create(name)); auto region = TRY(Region::create_unplaced(vmobject, 0, move(name_kstring), access, cacheable)); - TRY(m_region_tree.place_anywhere(*region, size)); + TRY(m_region_tree.place_anywhere(*region, RandomizeVirtualAddress::No, size)); TRY(region->map(kernel_page_directory())); return region; } diff --git a/Kernel/Memory/RegionTree.cpp b/Kernel/Memory/RegionTree.cpp index 30f9661821..a32cbf991b 100644 --- a/Kernel/Memory/RegionTree.cpp +++ b/Kernel/Memory/RegionTree.cpp @@ -146,14 +146,14 @@ ErrorOr<VirtualRange> RegionTree::try_allocate_randomized(size_t size, size_t al ErrorOr<NonnullOwnPtr<Region>> RegionTree::allocate_unbacked_anywhere(size_t size, size_t alignment) { auto region = TRY(Region::create_unbacked()); - TRY(place_anywhere(*region, size, alignment)); + TRY(place_anywhere(*region, RandomizeVirtualAddress::No, size, alignment)); return region; } -ErrorOr<void> RegionTree::place_anywhere(Region& region, size_t size, size_t alignment) +ErrorOr<void> RegionTree::place_anywhere(Region& region, RandomizeVirtualAddress randomize_virtual_address, size_t size, size_t alignment) { SpinlockLocker locker(m_lock); - auto range = TRY(try_allocate_anywhere(size, alignment)); + auto range = TRY(randomize_virtual_address == RandomizeVirtualAddress::Yes ? try_allocate_randomized(size, alignment) : try_allocate_anywhere(size, alignment)); region.m_range = range; m_regions.insert(region.vaddr().get(), region); return {}; diff --git a/Kernel/Memory/RegionTree.h b/Kernel/Memory/RegionTree.h index 81b530aebc..19a719c2d7 100644 --- a/Kernel/Memory/RegionTree.h +++ b/Kernel/Memory/RegionTree.h @@ -15,6 +15,11 @@ namespace Kernel::Memory { +enum class RandomizeVirtualAddress { + No, + Yes, +}; + class RegionTree { AK_MAKE_NONCOPYABLE(RegionTree); AK_MAKE_NONMOVABLE(RegionTree); @@ -34,7 +39,7 @@ public: ErrorOr<NonnullOwnPtr<Region>> allocate_unbacked_anywhere(size_t size, size_t alignment = PAGE_SIZE); - ErrorOr<void> place_anywhere(Region&, size_t size, size_t alignment = PAGE_SIZE); + ErrorOr<void> place_anywhere(Region&, RandomizeVirtualAddress, size_t size, size_t alignment = PAGE_SIZE); ErrorOr<void> place_specifically(Region&, VirtualRange const&); ErrorOr<NonnullOwnPtr<Memory::Region>> create_identity_mapped_region(PhysicalAddress, size_t); |