From 7fc5a6b75304dbb7e46c5272ac943ecbc0ae3bfa Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 16 Nov 2022 20:02:04 +0100 Subject: [PATCH] Make kernel rodata and data not executable --- kernel/CMakeLists.txt | 2 +- kernel/moon.ld | 7 +++++-- kernel/src/Init.cpp | 2 ++ kernel/src/MemoryManager.cpp | 39 ++++++++++++++++++++++++++++++++++++ kernel/src/MemoryManager.h | 5 +++++ luna/Alignment.h | 22 ++++++++++++++++++++ luna/Result.h | 9 ++++++++- 7 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 luna/Alignment.h diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 25eca3cd..85aad645 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -31,7 +31,7 @@ target_compile_definitions(moon PRIVATE IN_MOON) target_compile_options(moon PRIVATE -Os) -target_compile_options(moon PRIVATE -pedantic -Wall -Wextra -Werror -Wvla) +target_compile_options(moon PRIVATE -Wall -Wextra -Werror -Wvla) target_compile_options(moon PRIVATE -Wdisabled-optimization -Wformat=2 -Winit-self) target_compile_options(moon PRIVATE -Wmissing-include-dirs -Wswitch-default -Wcast-qual -Wundef) target_compile_options(moon PRIVATE -Wcast-align -Wwrite-strings -Wlogical-op -Wredundant-decls -Wshadow -Wconversion) diff --git a/kernel/moon.ld b/kernel/moon.ld index 8445665d..5b99a57b 100644 --- a/kernel/moon.ld +++ b/kernel/moon.ld @@ -16,13 +16,16 @@ SECTIONS kernel_start = .; .text : { KEEP(*(.text.boot)) *(.text .text.*) /* code */ + . = ALIGN(0x1000); start_of_kernel_rodata = .; - *(.rodata .rodata.*) /* data */ + *(.rodata .rodata.*) /* read-only data */ end_of_kernel_rodata = .; + . = ALIGN(0x1000); - start_of_kernel_data = .; + start_of_kernel_data = .; /* data */ *(.data .data.*) + } :boot .bss (NOLOAD) : { /* bss */ *(.bss .bss.*) diff --git a/kernel/src/Init.cpp b/kernel/src/Init.cpp index 25018f87..781d1473 100644 --- a/kernel/src/Init.cpp +++ b/kernel/src/Init.cpp @@ -24,4 +24,6 @@ void Init::early_init() MemoryManager::init(); CPU::platform_init(); + + check(MemoryManager::protect_kernel_sections().has_value()); } \ No newline at end of file diff --git a/kernel/src/MemoryManager.cpp b/kernel/src/MemoryManager.cpp index 1223ffd8..f1ae9961 100644 --- a/kernel/src/MemoryManager.cpp +++ b/kernel/src/MemoryManager.cpp @@ -2,6 +2,7 @@ #include "arch/MMU.h" #include "arch/Serial.h" #include "bootboot.h" +#include #include #include @@ -40,6 +41,17 @@ static void page_bitmap_set(u64 index, bool value) namespace MemoryManager { + Result protect_kernel_sections() + { + u64 rodata_pages = get_blocks_from_size((u64)(end_of_kernel_rodata - start_of_kernel_rodata), MMU::page_size()); + TRY(remap((u64)start_of_kernel_rodata, rodata_pages, MMU::NoExecute)); + + u64 data_pages = get_blocks_from_size((u64)(end_of_kernel_data - start_of_kernel_data), MMU::page_size()); + TRY(remap((u64)start_of_kernel_data, data_pages, MMU::NoExecute | MMU::ReadWrite)); + + return {}; + } + void init_physical_allocator() { u64 total_mem = 0; @@ -145,6 +157,33 @@ namespace MemoryManager return {}; } + Result remap(u64 address, size_t count, int flags) + { + check(is_aligned(address, MMU::page_size())); + + while (count--) + { + TRY(MMU::remap(address, flags)); + address += MMU::page_size(); + } + + return {}; + } + + Result remap_unaligned(u64 address, size_t count, int flags) + { + if (!is_aligned(address, MMU::page_size())) count++; + address = align_down(address, MMU::page_size()); + + while (count--) + { + TRY(MMU::remap(address, flags)); + address += MMU::page_size(); + } + + return {}; + } + u64 free() { return free_mem; diff --git a/kernel/src/MemoryManager.h b/kernel/src/MemoryManager.h index 59621504..ab516b5b 100644 --- a/kernel/src/MemoryManager.h +++ b/kernel/src/MemoryManager.h @@ -6,12 +6,17 @@ namespace MemoryManager { void init(); + Result protect_kernel_sections(); + Result alloc_physical_page(); Result free_physical_page(u64 page); void lock_page(u64 page); void lock_pages(u64 pages, u64 count); + Result remap(u64 address, size_t count, int flags); + Result remap_unaligned(u64 address, size_t count, int flags); + u64 free(); u64 used(); u64 reserved(); diff --git a/luna/Alignment.h b/luna/Alignment.h new file mode 100644 index 00000000..0cb7ced3 --- /dev/null +++ b/luna/Alignment.h @@ -0,0 +1,22 @@ +#pragma once + +template constexpr T is_aligned(T value, T align_base) +{ + return (value % align_base == 0); +} + +template constexpr T align_down(T value, T align_base) +{ + return value - (value % align_base); +} + +template constexpr T align_up(T value, T align_base) +{ + if (is_aligned(value, align_base)) return value; + return align_down(value, align_base) + align_base; +} + +template constexpr T get_blocks_from_size(T value, T block_size) +{ + return (value + (block_size - 1)) / block_size; +} \ No newline at end of file diff --git a/luna/Result.h b/luna/Result.h index c5777205..e5e99ae0 100644 --- a/luna/Result.h +++ b/luna/Result.h @@ -236,4 +236,11 @@ template <> class Result // clang-format off #define err Error{0} -// clang-format on \ No newline at end of file +// clang-format on + +#define TRY(expr) \ + ({ \ + auto _expr_rc = (expr); \ + if (_expr_rc.has_error()) return _expr_rc.release_error(); \ + _expr_rc.release_value(); \ + })