From be14a6c239ed1b1e613e390a0470f93048dde94f Mon Sep 17 00:00:00 2001 From: Bananymous Date: Fri, 21 Apr 2023 10:40:24 +0300 Subject: [PATCH] Kernel: Stack pointer is validated when updated This allows us not to fail stack pointer when in syscall since interrupts use their own stack --- kernel/arch/i386/linker.ld | 3 +-- kernel/arch/x86_64/linker.ld | 3 +-- kernel/include/kernel/Syscall.h | 4 ++-- kernel/include/kernel/Thread.h | 7 ++++++- kernel/kernel/Process.cpp | 3 ++- kernel/kernel/Scheduler.cpp | 2 -- kernel/kernel/Syscall.cpp | 22 +++++++++++++--------- kernel/kernel/kernel.cpp | 8 ++++---- kernel/userspace/userspace.cpp | 8 ++++++++ 9 files changed, 37 insertions(+), 23 deletions(-) diff --git a/kernel/arch/i386/linker.ld b/kernel/arch/i386/linker.ld index 75e730376..87d771499 100644 --- a/kernel/arch/i386/linker.ld +++ b/kernel/arch/i386/linker.ld @@ -4,6 +4,7 @@ SECTIONS { . = 0x00100000; + g_kernel_start = .; .text BLOCK(4K) : ALIGN(4K) { *(.multiboot) @@ -11,9 +12,7 @@ SECTIONS } .rodata BLOCK(4K) : ALIGN(4K) { - g_rodata_start = .; *(.rodata.*) - g_rodata_end = .; } .data BLOCK(4K) : ALIGN(4K) { diff --git a/kernel/arch/x86_64/linker.ld b/kernel/arch/x86_64/linker.ld index ad62aa8e2..f20c05d45 100644 --- a/kernel/arch/x86_64/linker.ld +++ b/kernel/arch/x86_64/linker.ld @@ -4,6 +4,7 @@ SECTIONS { . = 0x00100000; + g_kernel_start = .; .text BLOCK(4K) : ALIGN(4K) { *(.multiboot) @@ -11,9 +12,7 @@ SECTIONS } .rodata BLOCK(4K) : ALIGN(4K) { - g_rodata_start = .; *(.rodata.*) - g_rodata_end = .; } .data BLOCK(4K) : ALIGN(4K) { diff --git a/kernel/include/kernel/Syscall.h b/kernel/include/kernel/Syscall.h index 94e33f5e3..aa64d9dde 100644 --- a/kernel/include/kernel/Syscall.h +++ b/kernel/include/kernel/Syscall.h @@ -10,9 +10,9 @@ namespace Kernel { template - inline int syscall(int syscall, T1 arg1 = nullptr, T2 arg2 = nullptr, T3 arg3 = nullptr) + inline long syscall(int syscall, T1 arg1 = nullptr, T2 arg2 = nullptr, T3 arg3 = nullptr) { - int ret; + long ret; asm volatile("int $0x80" : "=a"(ret) : "a"(syscall), "b"((uintptr_t)arg1), "c"((uintptr_t)arg2), "d"((uintptr_t)arg3) : "memory"); return ret; } diff --git a/kernel/include/kernel/Thread.h b/kernel/include/kernel/Thread.h index a4746e417..e0886ac71 100644 --- a/kernel/include/kernel/Thread.h +++ b/kernel/include/kernel/Thread.h @@ -33,7 +33,7 @@ namespace Kernel pid_t tid() const { return m_tid; } - void set_rsp(uintptr_t rsp) { m_rsp = rsp; } + void set_rsp(uintptr_t rsp) { m_rsp = rsp; validate_stack(); } void set_rip(uintptr_t rip) { m_rip = rip; } uintptr_t rsp() const { return m_rsp; } uintptr_t rip() const { return m_rip; } @@ -49,9 +49,13 @@ namespace Kernel Process& process(); bool has_process() const { return m_process; } + void set_in_syscall(bool b) { m_in_syscall = b; } + private: Thread(pid_t tid, Process*); + void validate_stack() const { if (!m_in_syscall) ASSERT(stack_base() <= m_rsp && m_rsp <= stack_base() + stack_size()); } + BAN::ErrorOr initialize(entry_t, void*); void on_exit(); @@ -63,6 +67,7 @@ namespace Kernel const pid_t m_tid { 0 }; State m_state { State::NotStarted }; Process* m_process { nullptr }; + bool m_in_syscall { false }; friend class Scheduler; }; diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index fb413bf98..496ffb167 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -45,7 +45,8 @@ namespace Kernel [](void* entry_func) { Thread& current = Thread::current(); - Process::current().m_mmu->map_range(current.stack_base(), current.stack_size(), MMU::Flags::UserSupervisor | MMU::Flags::ReadWrite | MMU::Flags::Present); + current.process().m_mmu->map_range(current.stack_base(), current.stack_size(), MMU::Flags::UserSupervisor | MMU::Flags::ReadWrite | MMU::Flags::Present); + current.process().m_mmu->load(); current.jump_userspace((uintptr_t)entry_func); ASSERT_NOT_REACHED(); }, (void*)entry diff --git a/kernel/kernel/Scheduler.cpp b/kernel/kernel/Scheduler.cpp index 99d1f6ce0..675963cd3 100644 --- a/kernel/kernel/Scheduler.cpp +++ b/kernel/kernel/Scheduler.cpp @@ -158,8 +158,6 @@ namespace Kernel current.set_rip(rip); current.set_rsp(rsp); - ASSERT(current.stack_base() <= rsp && rsp <= current.stack_base() + current.stack_size()); - return false; } diff --git a/kernel/kernel/Syscall.cpp b/kernel/kernel/Syscall.cpp index 9d51146e1..efc8bfafe 100644 --- a/kernel/kernel/Syscall.cpp +++ b/kernel/kernel/Syscall.cpp @@ -10,29 +10,29 @@ namespace Kernel Process::current().exit(); } - int sys_read(int fd, void* buffer, size_t size) + long sys_read(int fd, void* buffer, size_t size) { auto res = Process::current().read(fd, buffer, size); if (res.is_error()) return res.error().get_error_code(); - return 0; + return res.value(); } - int sys_write(int fd, const void* buffer, size_t size) + long sys_write(int fd, const void* buffer, size_t size) { auto res = Process::current().write(fd, buffer, size); if (res.is_error()) return res.error().get_error_code(); - return 0; + return res.value(); } - extern "C" int cpp_syscall_handler(int syscall, void* arg1, void* arg2, void* arg3) + extern "C" long cpp_syscall_handler(int syscall, void* arg1, void* arg2, void* arg3) { - (void)arg1; - (void)arg2; - (void)arg3; + Thread::current().set_in_syscall(true); - int ret = 0; + asm volatile("sti"); + + long ret = 0; switch (syscall) { case SYS_EXIT: @@ -50,6 +50,10 @@ namespace Kernel break; } + asm volatile("cli"); + + Thread::current().set_in_syscall(false); + return ret; } diff --git a/kernel/kernel/kernel.cpp b/kernel/kernel/kernel.cpp index 851af4bad..79a360087 100644 --- a/kernel/kernel/kernel.cpp +++ b/kernel/kernel/kernel.cpp @@ -99,12 +99,12 @@ namespace BAN::Formatter } -extern "C" uintptr_t g_rodata_start; -extern "C" uintptr_t g_rodata_end; - extern "C" uintptr_t g_userspace_start; extern "C" uintptr_t g_userspace_end; +extern "C" uintptr_t g_kernel_start; +extern "C" uintptr_t g_kernel_end; + extern void userspace_entry(); static void jump_userspace(); @@ -213,7 +213,7 @@ static void jump_userspace() using namespace Kernel; MMU::get().map_range((uintptr_t)&g_userspace_start, (uintptr_t)&g_userspace_end - (uintptr_t)&g_userspace_start, MMU::Flags::UserSupervisor | MMU::Flags::Present); - MMU::get().map_range((uintptr_t)&g_rodata_start, (uintptr_t)&g_rodata_end - (uintptr_t)&g_rodata_start, MMU::Flags::UserSupervisor | MMU::Flags::Present); + MMU::get().map_range((uintptr_t)&g_kernel_start, (uintptr_t)&g_kernel_end - (uintptr_t)&g_kernel_start, MMU::Flags::UserSupervisor | MMU::Flags::Present); MUST(Process::create_userspace(userspace_entry)); } diff --git a/kernel/userspace/userspace.cpp b/kernel/userspace/userspace.cpp index e438640fa..8b585cee7 100644 --- a/kernel/userspace/userspace.cpp +++ b/kernel/userspace/userspace.cpp @@ -8,5 +8,13 @@ USERSPACE void userspace_entry() { Kernel::syscall(SYS_WRITE, STDOUT_FILENO, "Hello World!", 12); + + char buffer[128]; + while (true) + { + long n_read = Kernel::syscall(SYS_READ, STDIN_FILENO, buffer, sizeof(buffer)); + Kernel::syscall(SYS_WRITE, STDOUT_FILENO, buffer, n_read); + } + Kernel::syscall(SYS_EXIT); }