From e18632660f29ba9e69dfaed18465af95edcc32b9 Mon Sep 17 00:00:00 2001 From: Idan Horowitz Date: Tue, 22 Mar 2022 13:40:21 +0200 Subject: [PATCH] Kernel: Use the pre-image kernel memory range introduced by KASLR This ensures we don't just waste the memory range between the default base load address and the actual load address that was shifted by the KASLR offset. --- Kernel/BootInfo.h | 1 + Kernel/Memory/PageDirectory.cpp | 9 ++++++--- Kernel/Prekernel/Prekernel.h | 1 + Kernel/Prekernel/init.cpp | 1 + Kernel/init.cpp | 2 ++ 5 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Kernel/BootInfo.h b/Kernel/BootInfo.h index 48330cce7d..94bdbb3d1d 100644 --- a/Kernel/BootInfo.h +++ b/Kernel/BootInfo.h @@ -18,6 +18,7 @@ extern "C" PhysicalAddress start_of_prekernel_image; extern "C" PhysicalAddress end_of_prekernel_image; extern "C" size_t physical_to_virtual_offset; extern "C" FlatPtr kernel_mapping_base; +extern "C" FlatPtr default_kernel_load_base; extern "C" FlatPtr kernel_load_base; #if ARCH(X86_64) extern "C" u32 gdt64ptr; diff --git a/Kernel/Memory/PageDirectory.cpp b/Kernel/Memory/PageDirectory.cpp index faa21f8379..6da3d97434 100644 --- a/Kernel/Memory/PageDirectory.cpp +++ b/Kernel/Memory/PageDirectory.cpp @@ -13,6 +13,7 @@ #include #include +extern u8 start_of_kernel_image[]; extern u8 end_of_kernel_image[]; namespace Kernel::Memory { @@ -35,9 +36,11 @@ UNMAP_AFTER_INIT NonnullRefPtr PageDirectory::must_create_kernel_ { auto directory = adopt_ref_if_nonnull(new (nothrow) PageDirectory).release_nonnull(); - // make sure this starts in a new page directory to make MemoryManager::initialize_physical_pages() happy - FlatPtr start_of_range = ((FlatPtr)end_of_kernel_image & ~(FlatPtr)0x1fffff) + 0x200000; - MUST(directory->m_range_allocator.initialize_with_range(VirtualAddress(start_of_range), KERNEL_PD_END - start_of_range)); + MUST(directory->m_range_allocator.initialize_with_range(VirtualAddress(default_kernel_load_base), KERNEL_PD_END - default_kernel_load_base)); + // Carve out the whole page directory covering the kernel image to make MemoryManager::initialize_physical_pages() happy + FlatPtr start_of_range = ((FlatPtr)start_of_kernel_image & ~(FlatPtr)0x1fffff); + FlatPtr end_of_range = ((FlatPtr)end_of_kernel_image & ~(FlatPtr)0x1fffff) + 0x200000; + MUST(directory->m_range_allocator.try_allocate_specific(VirtualAddress(start_of_range), end_of_range - start_of_range)); return directory; } diff --git a/Kernel/Prekernel/Prekernel.h b/Kernel/Prekernel/Prekernel.h index 92d1239a71..b01f5eeb66 100644 --- a/Kernel/Prekernel/Prekernel.h +++ b/Kernel/Prekernel/Prekernel.h @@ -22,6 +22,7 @@ struct [[gnu::packed]] BootInfo { u32 end_of_prekernel_image; u64 physical_to_virtual_offset; u64 kernel_mapping_base; + u64 default_kernel_load_base; u64 kernel_load_base; # if ARCH(X86_64) u32 gdt64ptr; diff --git a/Kernel/Prekernel/init.cpp b/Kernel/Prekernel/init.cpp index 9fced041a2..3692998cfc 100644 --- a/Kernel/Prekernel/init.cpp +++ b/Kernel/Prekernel/init.cpp @@ -184,6 +184,7 @@ extern "C" [[noreturn]] void init() info.end_of_prekernel_image = (PhysicalPtr)end_of_prekernel_image; info.physical_to_virtual_offset = kernel_load_base - kernel_physical_base; info.kernel_mapping_base = kernel_mapping_base; + info.default_kernel_load_base = default_kernel_load_base; info.kernel_load_base = kernel_load_base; #if ARCH(X86_64) info.gdt64ptr = (PhysicalPtr)gdt64ptr; diff --git a/Kernel/init.cpp b/Kernel/init.cpp index 5c5f98fba0..d51d452956 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -116,6 +116,7 @@ READONLY_AFTER_INIT PhysicalAddress start_of_prekernel_image; READONLY_AFTER_INIT PhysicalAddress end_of_prekernel_image; READONLY_AFTER_INIT size_t physical_to_virtual_offset; READONLY_AFTER_INIT FlatPtr kernel_mapping_base; +READONLY_AFTER_INIT FlatPtr default_kernel_load_base; READONLY_AFTER_INIT FlatPtr kernel_load_base; #if ARCH(X86_64) READONLY_AFTER_INIT PhysicalAddress boot_pml4t; @@ -148,6 +149,7 @@ extern "C" [[noreturn]] UNMAP_AFTER_INIT void init(BootInfo const& boot_info) end_of_prekernel_image = PhysicalAddress { boot_info.end_of_prekernel_image }; physical_to_virtual_offset = boot_info.physical_to_virtual_offset; kernel_mapping_base = boot_info.kernel_mapping_base; + default_kernel_load_base = boot_info.default_kernel_load_base; kernel_load_base = boot_info.kernel_load_base; #if ARCH(X86_64) gdt64ptr = boot_info.gdt64ptr;