From 5d41b4b113c7faa98ba66c56052892177e131bb0 Mon Sep 17 00:00:00 2001 From: apio Date: Thu, 13 Oct 2022 22:13:04 +0200 Subject: [PATCH] Almost there... exec() is not working yet. But the rest are!! --- kernel/include/sys/Syscall.h | 2 ++ kernel/src/sys/Syscall.cpp | 8 ++++++++ kernel/src/sys/exec.cpp | 32 +++++++++++++++++++++++++++----- kernel/src/sys/stdio.cpp | 21 +++++++++++++++++---- 4 files changed, 54 insertions(+), 9 deletions(-) diff --git a/kernel/include/sys/Syscall.h b/kernel/include/sys/Syscall.h index 9d9a1ce8..a5928008 100644 --- a/kernel/include/sys/Syscall.h +++ b/kernel/include/sys/Syscall.h @@ -20,6 +20,8 @@ namespace Syscall { void entry(Context* context); + + char* strdup_from_user(const char* user_string); } void sys_exit(Context* context, int status); diff --git a/kernel/src/sys/Syscall.cpp b/kernel/src/sys/Syscall.cpp index f47dc227..df373bee 100644 --- a/kernel/src/sys/Syscall.cpp +++ b/kernel/src/sys/Syscall.cpp @@ -2,6 +2,7 @@ #include "errno.h" #include "io/Serial.h" #include "memory/VMM.h" +#include "std/string.h" #include "thread/Scheduler.h" void Syscall::entry(Context* context) @@ -27,4 +28,11 @@ void Syscall::entry(Context* context) default: context->rax = -ENOSYS; break; } VMM::exit_syscall_context(); +} + +char* Syscall::strdup_from_user(const char* user_string) +{ + uint64_t phys = VMM::get_physical((uint64_t)user_string); + if (phys == (uint64_t)-1) { return nullptr; } + return strdup((const char*)phys); } \ No newline at end of file diff --git a/kernel/src/sys/exec.cpp b/kernel/src/sys/exec.cpp index 666b287e..db19fbce 100644 --- a/kernel/src/sys/exec.cpp +++ b/kernel/src/sys/exec.cpp @@ -5,30 +5,35 @@ #include "interrupts/Interrupts.h" #include "memory/MemoryManager.h" #include "memory/PMM.h" +#include "memory/VMM.h" #include "std/stdlib.h" #include "std/string.h" +#include "sys/Syscall.h" #include "sys/elf/ELFLoader.h" #include "thread/Scheduler.h" void sys_exec(Context* context, const char* pathname) { - if (!pathname) + char* kpathname = Syscall::strdup_from_user(pathname); + if (!kpathname) { context->rax = -EFAULT; return; } - kinfoln("exec(): executing %s", pathname); + kinfoln("exec(): executing %s", kpathname); - VFS::Node* program = VFS::resolve_path(pathname); + VFS::Node* program = VFS::resolve_path(kpathname); if (!program) { + kfree(kpathname); context->rax = -ENOENT; return; } if (program->type == VFS_DIRECTORY) { + kfree(kpathname); context->rax = -EISDIR; return; } @@ -36,6 +41,7 @@ void sys_exec(Context* context, const char* pathname) long memusage; if ((memusage = ELFLoader::check_elf_image(program)) < 0) { + kfree(kpathname); context->rax = -ENOEXEC; return; } @@ -43,12 +49,16 @@ void sys_exec(Context* context, const char* pathname) uint64_t allocated_stack = (uint64_t)MemoryManager::get_pages(TASK_PAGES_IN_STACK, MAP_READ_WRITE | MAP_USER); if (!allocated_stack) { + kfree(kpathname); context->rax = -ENOMEM; return; } + uint64_t allocated_stack_phys = VMM::get_physical(allocated_stack); + if ((uint64_t)memusage > PMM::get_free()) { + kfree(kpathname); MemoryManager::release_pages((void*)allocated_stack, TASK_PAGES_IN_STACK); context->rax = -ENOMEM; return; @@ -64,17 +74,29 @@ void sys_exec(Context* context, const char* pathname) ELFLoader::release_elf_image(Scheduler::current_task()->image); + MemoryManager::release_pages((void*)task->allocated_stack, TASK_PAGES_IN_STACK); + + task->address_space.destroy(); + task->address_space = AddressSpace::create(); + + VMM::switch_to_user_address_space(task->address_space); + ELFImage* image = ELFLoader::load_elf_from_vfs(program); ASSERT(image); // If check_elf_image succeeded, load_elf_from_vfs MUST succeed, unless something has gone terribly // wrong. - MemoryManager::release_pages((void*)task->allocated_stack, TASK_PAGES_IN_STACK); - task->allocated_stack = allocated_stack; + for (uint64_t i = 0; i < TASK_PAGES_IN_STACK; i++) + { + VMM::map(allocated_stack + (i * PAGE_SIZE), allocated_stack_phys + (i * PAGE_SIZE), MAP_READ_WRITE | MAP_USER); + } + Scheduler::reset_task(task, image); set_context_from_task(*task, context); + kfree(kpathname); + return; } \ No newline at end of file diff --git a/kernel/src/sys/stdio.cpp b/kernel/src/sys/stdio.cpp index 8b6f1147..522aa3b4 100644 --- a/kernel/src/sys/stdio.cpp +++ b/kernel/src/sys/stdio.cpp @@ -4,7 +4,10 @@ #include "interrupts/Context.h" #include "io/Serial.h" #include "log/Log.h" +#include "memory/VMM.h" #include "render/TextRenderer.h" +#include "std/stdlib.h" +#include "sys/Syscall.h" #include "thread/Scheduler.h" #include "thread/Task.h" @@ -79,7 +82,7 @@ void sys_write(Context* context, int fd, size_t size, const char* addr) context->rax = -EBADF; return; } - ssize_t result = current_task->files[fd].write(size, addr); + ssize_t result = current_task->files[fd].write(size, (const char*)VMM::get_physical((uint64_t)addr)); context->rax = (size_t)result; return; } @@ -99,9 +102,17 @@ void sys_open(Context* context, const char* filename, int flags) return; } - VFS::Node* node = VFS::resolve_path(filename); + char* kernel_filename = Syscall::strdup_from_user(filename); + if (!kernel_filename) + { + context->rax = -EFAULT; + return; + } + + VFS::Node* node = VFS::resolve_path(kernel_filename); if (!node) { + kfree(kernel_filename); context->rax = -ENOENT; return; } @@ -110,16 +121,18 @@ void sys_open(Context* context, const char* filename, int flags) bool can_write = (flags & OPEN_WRITE) > 0; if (!can_read && !can_write) { + kfree(kernel_filename); context->rax = -EINVAL; return; } - kdbgln("open(): opening %s %s, allocated file descriptor %d", filename, + kdbgln("open(): opening %s %s, allocated file descriptor %d", kernel_filename, (can_read && can_write) ? "rw" : can_read ? "r-" : "-w", fd); + kfree(kernel_filename); current_task->files[fd].open(node, can_read, can_write); context->rax = fd; return; @@ -143,7 +156,7 @@ void sys_read(Context* context, int fd, size_t size, char* buffer) context->rax = -EBADF; return; } - ssize_t result = current_task->files[fd].read(size, buffer); + ssize_t result = current_task->files[fd].read(size, (char*)VMM::get_physical((uint64_t)buffer)); context->rax = (size_t)result; return; }