From e9e7b223232daf198204add4b90dd02dd5f3cfd9 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 25 Jun 2023 20:09:40 +0200 Subject: [PATCH] kernel: Separate a thread's page directory into two The self directory, and the active directory. The active directory is the one the thread is currently using, and the self directory is the one the thread owns. This lets us keep track of both, which fixes ext2 executables crashing the system. --- kernel/src/arch/x86_64/disk/ATA.cpp | 2 +- kernel/src/sys/exec.cpp | 8 ++++---- kernel/src/thread/Scheduler.cpp | 6 +++--- kernel/src/thread/Thread.h | 3 ++- kernel/src/thread/ThreadImage.cpp | 5 +++-- 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/kernel/src/arch/x86_64/disk/ATA.cpp b/kernel/src/arch/x86_64/disk/ATA.cpp index 7786b6a8..ecb69ce9 100644 --- a/kernel/src/arch/x86_64/disk/ATA.cpp +++ b/kernel/src/arch/x86_64/disk/ATA.cpp @@ -146,7 +146,7 @@ namespace ATA { if (drive == m_current_drive) return; - u8 value = (drive << 4) | 0xa0; + u8 value = (u8)(drive << 4) | 0xa0; write_register(Register::DriveSelect, value); delay_400ns(); diff --git a/kernel/src/sys/exec.cpp b/kernel/src/sys/exec.cpp index 1fdc13f5..9283a463 100644 --- a/kernel/src/sys/exec.cpp +++ b/kernel/src/sys/exec.cpp @@ -70,7 +70,7 @@ Result sys_execve(Registers* regs, SyscallArgs args) kdbgln("exec: attempting to replace current image with %s", path.chars()); #endif - auto guard = make_scope_guard([current] { MMU::switch_page_directory(current->directory); }); + auto guard = make_scope_guard([current] { MMU::switch_page_directory(current->self_directory); }); auto image = TRY(ThreadImage::try_load_from_elf(inode)); @@ -99,7 +99,7 @@ Result sys_execve(Registers* regs, SyscallArgs args) } } - MMU::delete_userspace_page_directory(current->directory); + MMU::delete_userspace_page_directory(current->self_directory); if (VFS::is_setuid(inode)) current->auth.euid = current->auth.suid = inode->uid(); if (VFS::is_setgid(inode)) current->auth.egid = current->auth.sgid = inode->gid(); @@ -108,7 +108,7 @@ Result sys_execve(Registers* regs, SyscallArgs args) image->apply(current); - MMU::switch_page_directory(current->directory); + MMU::switch_page_directory(current->self_directory); current->set_arguments(user_argc, user_argv, user_envc, user_envp); @@ -123,7 +123,7 @@ Result sys_fork(Registers* regs, SyscallArgs) { auto current = Scheduler::current(); - auto guard = make_scope_guard([current] { MMU::switch_page_directory(current->directory); }); + auto guard = make_scope_guard([current] { MMU::switch_page_directory(current->self_directory); }); memcpy(¤t->regs, regs, sizeof(*regs)); diff --git a/kernel/src/thread/Scheduler.cpp b/kernel/src/thread/Scheduler.cpp index e2ac9197..876069d0 100644 --- a/kernel/src/thread/Scheduler.cpp +++ b/kernel/src/thread/Scheduler.cpp @@ -191,7 +191,7 @@ namespace Scheduler } } - if (!thread->is_kernel) MMU::delete_userspace_page_directory(thread->directory); + if (!thread->is_kernel) MMU::delete_userspace_page_directory(thread->self_directory); delete thread; @@ -236,8 +236,8 @@ namespace Scheduler switch_context(old_thread, new_thread, regs); if (!old_thread->is_kernel) old_thread->fp_data.save(); if (MMU::get_page_directory() != MMU::kernel_page_directory()) - old_thread->directory = MMU::get_page_directory(); - if (new_thread->directory) MMU::switch_page_directory(new_thread->directory); + old_thread->active_directory = MMU::get_page_directory(); + if (new_thread->active_directory) MMU::switch_page_directory(new_thread->active_directory); if (!new_thread->is_kernel) { CPU::switch_kernel_stack(new_thread->kernel_stack.top()); diff --git a/kernel/src/thread/Thread.h b/kernel/src/thread/Thread.h index ad6903a6..7ac4f3b0 100644 --- a/kernel/src/thread/Thread.h +++ b/kernel/src/thread/Thread.h @@ -97,7 +97,8 @@ struct Thread : public LinkedListNode Thread* parent { nullptr }; Option child_being_waited_for = {}; - PageDirectory* directory; + PageDirectory* self_directory; + PageDirectory* active_directory { nullptr }; [[noreturn]] void exit_and_signal_parent(u8 status); diff --git a/kernel/src/thread/ThreadImage.cpp b/kernel/src/thread/ThreadImage.cpp index 63ed43a6..0c999bd8 100644 --- a/kernel/src/thread/ThreadImage.cpp +++ b/kernel/src/thread/ThreadImage.cpp @@ -69,7 +69,7 @@ Result> ThreadImage::clone_from_thread(Thread* parent) auto vm_allocator = TRY(parent->vm_allocator->clone()); - auto new_directory = TRY(MMU::clone_userspace_page_directory(parent->directory)); + auto new_directory = TRY(MMU::clone_userspace_page_directory(parent->self_directory)); const ELFData data = { .entry = parent->ip() }; @@ -124,7 +124,8 @@ void ThreadImage::apply(Thread* thread) thread->stack = m_user_stack; thread->set_sp(align_down<16>(m_sp)); - thread->directory = m_directory; + thread->self_directory = m_directory; + thread->active_directory = m_directory; thread->vm_allocator = move(m_vm_allocator); }