diff --git a/Kernel/Arch/i386/CPU.h b/Kernel/Arch/i386/CPU.h index 143d8560cf..cd8e4d9dba 100644 --- a/Kernel/Arch/i386/CPU.h +++ b/Kernel/Arch/i386/CPU.h @@ -34,6 +34,8 @@ #include #include +#define READONLY_AFTER_INIT __attribute__((section(".ro_after_init"))) + #define PAGE_SIZE 4096 #define GENERIC_INTERRUPT_HANDLERS_COUNT (256 - IRQ_VECTOR_BASE) #define PAGE_MASK ((FlatPtr)0xfffff000u) 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()); diff --git a/Kernel/VM/MemoryManager.h b/Kernel/VM/MemoryManager.h index b2eba06eae..4d307fee9e 100644 --- a/Kernel/VM/MemoryManager.h +++ b/Kernel/VM/MemoryManager.h @@ -141,6 +141,8 @@ public: PageFaultResponse handle_page_fault(const PageFault&); + void protect_readonly_after_init_memory(); + static void enter_process_paging_scope(Process&); static void enter_space(Space&); diff --git a/Kernel/init.cpp b/Kernel/init.cpp index 1b243d9bae..8fb4027079 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -296,6 +296,9 @@ void init_stage2(void*) load_kernel_symbol_table(); + // NOTE: Everything marked READONLY_AFTER_INIT becomes non-writable after this point. + MM.protect_readonly_after_init_memory(); + int error; // FIXME: It would be nicer to set the mode from userspace. diff --git a/Kernel/linker.ld b/Kernel/linker.ld index f3cf9c9bde..e357c29e66 100644 --- a/Kernel/linker.ld +++ b/Kernel/linker.ld @@ -43,6 +43,13 @@ SECTIONS end_of_kernel_data = .; } + .ro_after_init ALIGN(4K) (NOLOAD) : AT(ADDR(.ro_after_init) - 0xc0000000) + { + start_of_ro_after_init = .; + *(.ro_after_init); + end_of_ro_after_init = .; + } + .bss ALIGN(4K) (NOLOAD) : AT (ADDR(.bss) - 0xc0000000) { start_of_kernel_bss = .;