From 9fdad650b9c3ab2822e951818c1b7aff6bbb04fd Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 16 Nov 2022 16:04:09 +0200 Subject: [PATCH] Trying to fix user stack --- Execute/Spawn.cpp | 2 +- KThread.cpp | 34 ++-- Tasking/InterProcessCommunication.cpp | 4 +- Tasking/Task.cpp | 231 ++++++++++++++++---------- include/exec.hpp | 2 +- include/memory.hpp | 3 +- include/task.hpp | 6 +- 7 files changed, 172 insertions(+), 110 deletions(-) diff --git a/Execute/Spawn.cpp b/Execute/Spawn.cpp index f733120..6fc1080 100644 --- a/Execute/Spawn.cpp +++ b/Execute/Spawn.cpp @@ -14,7 +14,7 @@ using namespace Tasking; namespace Execute { - SpawnData Spawn(char *Path, Vector &argv, Vector &envp) + SpawnData Spawn(char *Path, const char **argv, const char **envp) { SpawnData ret = {.Status = ExStatus::Unknown, .Process = nullptr, diff --git a/KThread.cpp b/KThread.cpp index fe2bad2..db060fe 100644 --- a/KThread.cpp +++ b/KThread.cpp @@ -47,8 +47,6 @@ void FetchDisks() void KernelMainThread() { - Vector argv; - Vector envp; Vector auxv; Tasking::TCB *CurrentWorker = nullptr; @@ -56,36 +54,38 @@ void KernelMainThread() KPrint("C++ Language Version (__cplusplus): %ld", __cplusplus); TaskManager->GetCurrentThread()->SetPriority(1); - CurrentWorker = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)StartFilesystem, argv, envp, auxv); + CurrentWorker = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)StartFilesystem, nullptr, nullptr, auxv); CurrentWorker->Rename("Disk"); CurrentWorker->SetPriority(100); TaskManager->WaitForThread(CurrentWorker); - CurrentWorker = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)LoadDrivers, argv, envp, auxv); + CurrentWorker = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)LoadDrivers, nullptr, nullptr, auxv); CurrentWorker->Rename("Drivers"); CurrentWorker->SetPriority(100); TaskManager->WaitForThread(CurrentWorker); - CurrentWorker = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)FetchDisks, argv, envp, auxv); + CurrentWorker = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)FetchDisks, nullptr, nullptr, auxv); CurrentWorker->Rename("Fetch Disks"); CurrentWorker->SetPriority(100); TaskManager->WaitForThread(CurrentWorker); KPrint("Setting up userspace..."); - envp.clear(); - envp.push_back("PATH=/system:/system/bin"); - envp.push_back("TERM=tty"); - envp.push_back("HOME=/"); - envp.push_back("USER=root"); - envp.push_back("SHELL=/system/bin/sh"); - envp.push_back("PWD=/"); - envp.push_back("LANG=en_US.UTF-8"); - envp.push_back("TZ=UTC"); + const char *envp[] = { + "PATH=/system:/system/bin", + "TERM=tty", + "HOME=/", + "USER=root", + "SHELL=/system/bin/sh", + "PWD=/", + "LANG=en_US.UTF-8", + "TZ=UTC", + nullptr}; - argv.clear(); - argv.push_back("--init"); - argv.push_back("--critical"); + const char *argv[] = { + "--init", + "--critical", + nullptr}; // TODO: Untested! bool ien = CPU::Interrupts(CPU::Check); diff --git a/Tasking/InterProcessCommunication.cpp b/Tasking/InterProcessCommunication.cpp index c985cf3..0448f40 100644 --- a/Tasking/InterProcessCommunication.cpp +++ b/Tasking/InterProcessCommunication.cpp @@ -54,10 +54,8 @@ namespace InterProcessCommunication IPC::IPC() { trace("Starting IPC Service..."); - Vector argv; - Vector envp; Vector auxv; - TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)IPCServiceStub, argv, envp, auxv); + TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)IPCServiceStub, nullptr, nullptr, auxv); TaskManager->GetCurrentThread()->Rename("IPC Service"); } diff --git a/Tasking/Task.cpp b/Tasking/Task.cpp index 7ac517d..022f157 100644 --- a/Tasking/Task.cpp +++ b/Tasking/Task.cpp @@ -1,8 +1,9 @@ #include +#include +#include #include #include -#include #include #include "../kernel.h" @@ -91,7 +92,10 @@ namespace Tasking trace("Thread \"%s\"(%d) removed from process \"%s\"(%d)", Thread->Name, Thread->ID, Thread->Parent->Name, Thread->Parent->ID); // Free memory - KernelAllocator.FreePages((void *)((uint64_t)Thread->Stack - STACK_SIZE), TO_PAGES(STACK_SIZE)); + if (Thread->Security.TrustLevel == TaskTrustLevel::User) + KernelAllocator.FreePages((void *)((uint64_t)Thread->Stack - USER_STACK_SIZE), TO_PAGES(USER_STACK_SIZE) /* + 1*/); + else + KernelAllocator.FreePages((void *)((uint64_t)Thread->Stack - STACK_SIZE), TO_PAGES(STACK_SIZE) /* + 1*/); SecurityManager.DestroyToken(Thread->Security.UniqueToken); delete Thread->Parent->Threads[i]; // Remove from the list @@ -683,8 +687,8 @@ namespace Tasking TCB *Task::CreateThread(PCB *Parent, IP EntryPoint, - Vector &argv, - Vector &envp, + const char **argv, + const char **envp, Vector &auxv, IPOffset Offset, TaskArchitecture Architecture, @@ -709,7 +713,6 @@ namespace Tasking Thread->EntryPoint = EntryPoint; Thread->Offset = Offset; Thread->ExitCode = 0xdead; - Thread->Stack = (void *)((uint64_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE))); Thread->Status = TaskStatus::Ready; #if defined(__amd64__) @@ -726,6 +729,8 @@ namespace Tasking case TaskTrustLevel::Idle: case TaskTrustLevel::Kernel: { + Thread->Stack = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE) + 1); + memset(Thread->Stack, 0, STACK_SIZE); #if defined(__amd64__) SecurityManager.TrustToken(Thread->Security.UniqueToken, TokenTrustLevel::TrustedByKernel); Thread->GSBase = CPU::x64::rdmsr(CPU::x64::MSRID::MSR_GS_BASE); @@ -744,6 +749,8 @@ namespace Tasking } case TaskTrustLevel::User: { + Thread->Stack = KernelAllocator.RequestPages(TO_PAGES(USER_STACK_SIZE) + 1); + memset(Thread->Stack, 0, USER_STACK_SIZE); #if defined(__amd64__) SecurityManager.TrustToken(Thread->Security.UniqueToken, TokenTrustLevel::Untrusted); Thread->GSBase = 0; @@ -756,86 +763,143 @@ namespace Tasking // Thread->Registers.rflags.IOPL = 3; Thread->Registers.rflags.IF = 1; Thread->Registers.rflags.ID = 1; - Thread->Registers.rsp = ((uint64_t)Thread->Stack + STACK_SIZE); + Thread->Registers.rsp = ((uint64_t)Thread->Stack + USER_STACK_SIZE); - // https://refspecs.linuxbase.org/elf/x86_64-abi-0.99.pdf#figure.3.9 - // What is a "eightbyte"? unsigned long? 1 eightbyte = 8 bytes? 2 eightbyte each = 16 bytes? - uint64_t TmpStack = Thread->Registers.rsp; - uint64_t TmpStack2 = TmpStack; - uint64_t *TmpStackPtr = (uint64_t *)TmpStack; - - // TODO: argc, argv, envp, auxv not tested and probably not working - foreach (auto var in envp) + if (Compatibility == TaskCompatibility::Linux) { - TmpStack -= strlen(var) + 1; - strcpy((char *)TmpStack, var); - } + // https://refspecs.linuxbase.org/elf/x86_64-abi-0.99.pdf#figure.3.9 + // What is a "eightbyte"? unsigned long? 1 eightbyte = 8 bytes? 2 eightbyte each = 16 bytes? + uint64_t TmpStack = Thread->Registers.rsp; + uint64_t TmpStack2 = TmpStack; + uint64_t *TmpStackPtr = (uint64_t *)TmpStack; - foreach (auto var in argv) + // TODO: argc, argv, envp, auxv not tested and probably not working + // foreach (auto var in envp) + // { + // TmpStack -= strlen(var) + 1; + // strcpy((char *)TmpStack, var); + // } + + // foreach (auto var in argv) + // { + // TmpStack -= strlen(var) + 1; + // strcpy((char *)TmpStack, var); + // } + + /* align by 16 */ + TmpStack = (uint64_t)((uint64_t)TmpStack - ((uint64_t)TmpStack & 0x0F)); + + /* TODO: more alignment here? */ + + /* auxv null */ + TmpStack -= sizeof(uint64_t); + POKE(uint64_t, TmpStack) = (uint64_t)0; + /* This should be included too? */ + TmpStack -= sizeof(uint64_t); + POKE(uint64_t, TmpStack) = (uint64_t)0; + + /* auxv */ + foreach (auto var in auxv) + { + if (var.archaux.a_type == AT_ENTRY) + Thread->Registers.rdi = var.archaux.a_un.a_val; + + TmpStack -= sizeof(uint64_t) * 2; + POKE(uint64_t, TmpStack) = (uint64_t)var.archaux.a_type; + TmpStack -= sizeof(uint64_t) * 2; + POKE(uint64_t, TmpStack) = (uint64_t)var.archaux.a_un.a_val; + } + + /* empty */ + TmpStack -= sizeof(uint64_t); + POKE(uint64_t, TmpStack) = 0; + + /* envp pointers */ + // for (uint64_t i = 0; i < envp.size(); i++) + // { + // /* Not sure if this works */ + // TmpStack2 -= strlen(envp[i]) + 1; + // TmpStackPtr[i] = TmpStack2; + // } + + /* empty */ + TmpStack -= sizeof(uint64_t); + POKE(uint64_t, TmpStack) = 0; + + /* argv pointers */ + // for (uint64_t i = 0; i < argv.size(); i++) + // { + // /* Not sure if this works */ + // TmpStack2 -= strlen(argv[i]) + 1; + // TmpStackPtr[i] = TmpStack2; + // } + + /* argc */ + TmpStack -= sizeof(uint64_t); + // POKE(uint64_t, TmpStack) = argv.size() - 1; + + Thread->Registers.rsp -= (uint64_t)Thread->Stack + STACK_SIZE - TmpStack; + } + else // Native { - TmpStack -= strlen(var) + 1; - strcpy((char *)TmpStack, var); + uint64_t ArgvSize = 0; + uint64_t ArgvStrSize = 0; + if (argv) + { + while (argv[ArgvSize] != nullptr) + { + ArgvSize++; + ArgvStrSize += strlen(argv[ArgvSize]) + 1; + } + } + + uint64_t EnvpSize = 0; + uint64_t EnvpStrSize = 0; + if (envp) + { + while (envp[EnvpSize] != nullptr) + { + EnvpSize++; + EnvpStrSize += strlen(envp[EnvpSize]) + 1; + } + } + + uint8_t *_argv = 0; + uint8_t *_envp = 0; + + for (uint64_t i = 0; i < ArgvSize; i++) + { + void *Tmp = KernelAllocator.RequestPages(TO_PAGES(strlen(argv[i]) + 1)); + Memory::Virtual().Map(Tmp, Tmp, Memory::PTFlag::RW | Memory::PTFlag::US); + _argv = (uint8_t *)Tmp; + strcpy((char *)_argv, argv[i]); + argv[i] = (char *)_argv; + } + + for (uint64_t i = 0; i < EnvpSize; i++) + { + void *Tmp = KernelAllocator.RequestPages(TO_PAGES(strlen(argv[i]) + 1)); + Memory::Virtual().Map(Tmp, Tmp, Memory::PTFlag::RW | Memory::PTFlag::US); + _envp = (uint8_t *)Tmp; + strcpy((char *)_envp, envp[i]); + envp[i] = (char *)_envp; + } + + Thread->Registers.rdi = ArgvSize; + Thread->Registers.rsi = (uint64_t)_argv; + Thread->Registers.rdx = (uint64_t)_envp; + + for (uint64_t i = 0; i < ArgvSize; i++) + debug("argv[%d]: %s", i, _argv[i]); + for (uint64_t i = 0; i < EnvpSize; i++) + debug("envp[%d]: %s", i, _envp[i]); } - /* align by 16 */ - TmpStack = (uint64_t)((uint64_t)TmpStack - ((uint64_t)TmpStack & 0x0F)); - - /* TODO: more aligment here? */ - - /* auxv null */ - TmpStack -= sizeof(uint64_t); - POKE(uint64_t, TmpStack) = (uint64_t)0; - /* This should be included too? */ - TmpStack -= sizeof(uint64_t); - POKE(uint64_t, TmpStack) = (uint64_t)0; - - /* auxv */ - foreach (auto var in auxv) - { - if (var.archaux.a_type == AT_ENTRY) - Thread->Registers.rdi = var.archaux.a_un.a_val; - - TmpStack -= sizeof(uint64_t) * 2; - POKE(uint64_t, TmpStack) = (uint64_t)var.archaux.a_type; - TmpStack -= sizeof(uint64_t) * 2; - POKE(uint64_t, TmpStack) = (uint64_t)var.archaux.a_un.a_val; - } - - /* empty */ - TmpStack -= sizeof(uint64_t); - POKE(uint64_t, TmpStack) = 0; - - /* envp pointers */ - for (uint64_t i = 0; i < envp.size(); i++) - { - /* Not sure if this works */ - TmpStack2 -= strlen(envp[i]) + 1; - TmpStackPtr[i] = TmpStack2; - } - - /* empty */ - TmpStack -= sizeof(uint64_t); - POKE(uint64_t, TmpStack) = 0; - - /* argv pointers */ - for (uint64_t i = 0; i < argv.size(); i++) - { - /* Not sure if this works */ - TmpStack2 -= strlen(argv[i]) + 1; - TmpStackPtr[i] = TmpStack2; - } - - /* argc */ - TmpStack -= sizeof(uint64_t); - POKE(uint64_t, TmpStack) = argv.size() - 1; - - Thread->Registers.rsp -= (uint64_t)Thread->Stack + STACK_SIZE - TmpStack; - /* We need to leave the libc's crt to make a syscall when the Thread is exited or we are going to get GPF or PF exception. */ Memory::Virtual uva = Memory::Virtual(Parent->PageTable); - for (uint64_t i = 0; i < TO_PAGES(STACK_SIZE); i++) - uva.Map((void *)((uint64_t)Thread->Stack + (i * PAGE_SIZE)), (void *)((uint64_t)Thread->Stack + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US); + for (uint64_t i = 0; i < TO_PAGES(USER_STACK_SIZE); i++) + uva.Map((void *)((uint64_t)Thread->Stack + (i * USER_STACK_SIZE)), (void *)((uint64_t)Thread->Stack + (i * USER_STACK_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US); if (!uva.Check((void *)Offset, Memory::PTFlag::US)) { @@ -880,8 +944,11 @@ namespace Tasking Thread->Info.Architecture = Architecture; Thread->Info.Compatibility = Compatibility; - debug("Thread offset is %#lx (%#lx)", Thread->Offset, Thread->EntryPoint); - debug("Thread stack is %#lx-%#lx", Thread->Stack, (uint64_t)Thread->Stack + STACK_SIZE); + debug("Thread offset is %#lx (EntryPoint:%#lx)", Thread->Offset, Thread->EntryPoint); + if (Parent->Security.TrustLevel == TaskTrustLevel::User) + debug("Thread stack region is %#lx-%#lx (U) and rsp is %#lx", Thread->Stack, (uint64_t)Thread->Stack + USER_STACK_SIZE, Thread->Registers.rsp); + else + debug("Thread stack region is %#lx-%#lx (K) and rsp is %#lx", Thread->Stack, (uint64_t)Thread->Stack + STACK_SIZE, Thread->Registers.rsp); debug("Created thread \"%s\"(%d) in process \"%s\"(%d)", Thread->Name, Thread->ID, Thread->Parent->Name, Thread->Parent->ID); @@ -998,10 +1065,8 @@ namespace Tasking TaskArchitecture Arch = TaskArchitecture::ARM64; #endif PCB *kproc = CreateProcess(nullptr, "Kernel", TaskTrustLevel::Kernel); - Vector argv; - Vector envp; Vector auxv; - TCB *kthrd = CreateThread(kproc, EntryPoint, argv, envp, auxv, 0, Arch); + TCB *kthrd = CreateThread(kproc, EntryPoint, nullptr, nullptr, auxv, 0, Arch); kthrd->Rename("Main Thread"); debug("Created Kernel Process: %s and Thread: %s", kproc->Name, kthrd->Name); TaskingLock.Lock(__FUNCTION__); @@ -1025,10 +1090,8 @@ namespace Tasking IdleProcess = CreateProcess(nullptr, (char *)"Idle", TaskTrustLevel::Idle); for (int i = 0; i < SMP::CPUCores; i++) { - Vector argv; - Vector envp; Vector auxv; - IdleThread = CreateThread(IdleProcess, reinterpret_cast(IdleProcessLoop), argv, envp, auxv); + IdleThread = CreateThread(IdleProcess, reinterpret_cast(IdleProcessLoop), nullptr, nullptr, auxv); char IdleName[16]; sprintf_(IdleName, "Idle Thread %d", i); IdleThread->Rename(IdleName); diff --git a/include/exec.hpp b/include/exec.hpp index f6ffba3..9cd213b 100644 --- a/include/exec.hpp +++ b/include/exec.hpp @@ -40,7 +40,7 @@ namespace Execute }; BinaryType GetBinaryType(char *Path); - SpawnData Spawn(char *Path, Vector &argv, Vector &envp); + SpawnData Spawn(char *Path, const char **argv, const char **envp); void *ELFLoadRel(Elf64_Ehdr *Header); } diff --git a/include/memory.hpp b/include/memory.hpp index b92292c..71c76dc 100644 --- a/include/memory.hpp +++ b/include/memory.hpp @@ -35,7 +35,8 @@ extern uint64_t _kernel_text_end, _kernel_data_end, _kernel_rodata_end; #define TO_GPB(d) (d / 1024 / 1024 / 1024 / 1024 / 1024 / 1024 / 1024 / 1024 / 1024 / 1024) #define PAGE_SIZE 0x1000 -#define STACK_SIZE 0x10000 +#define STACK_SIZE 0x1000000 +#define USER_STACK_SIZE 0x1000000 // to pages #define TO_PAGES(d) (d / PAGE_SIZE + 1) diff --git a/include/task.hpp b/include/task.hpp index feeade5..b25a23e 100644 --- a/include/task.hpp +++ b/include/task.hpp @@ -85,7 +85,7 @@ namespace Tasking IP EntryPoint; IPOffset Offset; int ExitCode; - void *Stack; + void *Stack __attribute__((aligned(16))); TaskStatus Status; #if defined(__amd64__) CPU::x64::TrapFrame Registers; @@ -241,8 +241,8 @@ namespace Tasking TCB *CreateThread(PCB *Parent, IP EntryPoint, - Vector &argv, - Vector &envp, + const char **argv, + const char **envp, Vector &auxv, IPOffset Offset = 0, TaskArchitecture Architecture = TaskArchitecture::x64,