summaryrefslogtreecommitdiff
path: root/Kernel/VM/MemoryManager.cpp
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2021-02-14 17:35:07 +0100
committerAndreas Kling <kling@serenityos.org>2021-02-14 18:11:32 +0100
commitd8013c60bb52756788e747183572067d6e3f204a (patch)
tree36406e6a97c1fdc74652900102b45630092c949f /Kernel/VM/MemoryManager.cpp
parent917f7d668c85541ddd754bdd1c5a94538f132ad4 (diff)
downloadserenity-d8013c60bb52756788e747183572067d6e3f204a.zip
Kernel: Add mechanism to make some memory read-only after init finishes
You can now use the READONLY_AFTER_INIT macro when declaring a variable and we will put it in a special ".ro_after_init" section in the kernel. Data in that section remains writable during the boot and init process, and is then marked read-only just before launching the SystemServer. This is based on an idea from the Linux kernel. :^)
Diffstat (limited to 'Kernel/VM/MemoryManager.cpp')
-rw-r--r--Kernel/VM/MemoryManager.cpp14
1 files changed, 14 insertions, 0 deletions
diff --git a/Kernel/VM/MemoryManager.cpp b/Kernel/VM/MemoryManager.cpp
index be32f030bf..ec3e570444 100644
--- a/Kernel/VM/MemoryManager.cpp
+++ b/Kernel/VM/MemoryManager.cpp
@@ -46,6 +46,8 @@ extern u8* end_of_kernel_image;
extern FlatPtr start_of_kernel_text;
extern FlatPtr start_of_kernel_data;
extern FlatPtr end_of_kernel_bss;
+extern FlatPtr start_of_ro_after_init;
+extern FlatPtr end_of_ro_after_init;
extern multiboot_module_entry_t multiboot_copy_boot_modules_array[16];
extern size_t multiboot_copy_boot_modules_count;
@@ -121,6 +123,18 @@ void MemoryManager::protect_kernel_image()
}
}
+void MemoryManager::protect_readonly_after_init_memory()
+{
+ ScopedSpinLock mm_lock(s_mm_lock);
+ ScopedSpinLock page_lock(kernel_page_directory().get_lock());
+ // Disable writing to the .ro_after_init section
+ for (auto i = (FlatPtr)&start_of_ro_after_init; i < (FlatPtr)&end_of_ro_after_init; i += PAGE_SIZE) {
+ auto& pte = *ensure_pte(kernel_page_directory(), VirtualAddress(i));
+ pte.set_writable(false);
+ flush_tlb(&kernel_page_directory(), VirtualAddress(i));
+ }
+}
+
void MemoryManager::register_reserved_ranges()
{
ASSERT(!m_physical_memory_ranges.is_empty());