1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 07:37:46 +00:00

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.
This commit is contained in:
Andreas Kling 2022-04-03 18:46:27 +02:00
parent e89c9ed2ca
commit 858b196c59
9 changed files with 33 additions and 27 deletions

View file

@ -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 }));

View file

@ -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);

View file

@ -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;
}

View file

@ -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 {};

View file

@ -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);