From 061363d85da15289f35f33de0a4ba725f6191076 Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 22 May 2023 00:43:45 +0300 Subject: [PATCH] Fix fork() syscall --- SystemCalls/Native.cpp | 54 ++++++++++++--------------- SystemCalls/Syscalls.cpp | 1 - Tasking/InterProcessCommunication.cpp | 2 +- Tasking/Task.cpp | 10 ----- include/task.hpp | 9 ++++- 5 files changed, 32 insertions(+), 44 deletions(-) diff --git a/SystemCalls/Native.cpp b/SystemCalls/Native.cpp index 3d19ddc..1164a36 100644 --- a/SystemCalls/Native.cpp +++ b/SystemCalls/Native.cpp @@ -40,7 +40,6 @@ using Tasking::TTL::Untrusted; static inline bool CheckTrust(int TrustLevel) { - // SmartTimeoutLock(SyscallsLock, 10000); - This is already done in the caller Token token = TaskManager->GetCurrentThread()->Security.UniqueToken; if (TaskManager->GetSecurityManager()->IsTokenTrusted(token, TrustLevel)) return true; @@ -340,17 +339,12 @@ static int sys_sleep(SyscallsFrame *Frame, uint64_t Milliseconds) return 0; } -static int _ChildPID = 0; - static int sys_fork(SyscallsFrame *Frame) { UNUSED(Frame); if (!CheckTrust(TrustedByKernel | Trusted | Untrusted)) return SYSCALL_ACCESS_DENIED; - fixme("sys_fork: %#lx", Frame); - return SYSCALL_NOT_IMPLEMENTED; - Tasking::PCB *Parent = TaskManager->GetCurrentThread()->Parent; Tasking::TCB *Thread = TaskManager->GetCurrentThread(); @@ -378,34 +372,19 @@ static int sys_fork(SyscallsFrame *Frame) Thread->Info.Compatibility, true); + strncpy(NewThread->Name, Thread->Name, sizeof(Thread->Name)); + if (!NewThread) { error("Failed to create thread for fork"); return SYSCALL_ERROR; } - _ChildPID = (int)NewThread->ID; - memcpy(NewThread->FPU, Thread->FPU, sizeof(CPU::x64::FXState)); - NewThread->Stack->Fork(Thread->Stack); - - strncpy(NewThread->Name, Thread->Name, sizeof(Thread->Name)); - NewThread->Info = Thread->Info; -#ifdef a86 - NewThread->ShadowGSBase = Thread->ShadowGSBase; - NewThread->GSBase = Thread->GSBase; - NewThread->FSBase = Thread->FSBase; -#endif - - CPU::Interrupts(CPU::Disable); static int RetChild = 0; static uint64_t ReturnAddress = 0; static uint64_t ChildStackPointer = 0; -#if defined(a86) - asmv("int $0x30"); /* This will trigger the IRQ16 instantly so we won't execute the next instruction */ -#elif defined(aa64) - asmv("svc #0x30"); /* This will trigger the IRQ16 instantly so we won't execute the next instruction */ -#endif + TaskManager->Schedule(); if (RetChild--) { @@ -413,28 +392,41 @@ static int sys_fork(SyscallsFrame *Frame) asmv("movq %0, %%rcx\n" : : "r"(ReturnAddress)); - asmv("movq $0, %rax\n"); // Return 0 to the child asmv("mov %0, %%rsp\n" : : "r"(ChildStackPointer)); asmv("mov %0, %%rbp\n" : : "r"(ChildStackPointer)); - asmv("swapgs\n"); // Swap GS back to the user GS - asmv("sti\n"); // Enable interrupts - asmv("sysretq\n"); // Return to rcx address in user mode + asmv("movq $0, %rax\n"); // Return 0 to the child + asmv("swapgs\n"); // Swap GS back to the user GS + asmv("sti\n"); // Enable interrupts + asmv("sysretq\n"); // Return to rcx address in user mode } RetChild = 1; ReturnAddress = Frame->ReturnAddress; ChildStackPointer = Frame->StackPointer; + memcpy(NewThread->FPU, Thread->FPU, sizeof(CPU::x64::FXState)); + NewThread->Stack->Fork(Thread->Stack); + NewThread->Info = Thread->Info; NewThread->Registers = Thread->Registers; + if (Thread->Security.IsCritical) + NewThread->SetCritical(true); + TaskManager->GetSecurityManager()->TrustToken(NewProcess->Security.UniqueToken, + (Tasking::TTL)TaskManager->GetSecurityManager()->GetTokenTrustLevel(Parent->Security.UniqueToken)); + TaskManager->GetSecurityManager()->TrustToken(NewThread->Security.UniqueToken, + (Tasking::TTL)TaskManager->GetSecurityManager()->GetTokenTrustLevel(Thread->Security.UniqueToken)); + +#ifdef a86 + NewThread->ShadowGSBase = Thread->ShadowGSBase; + NewThread->GSBase = Thread->GSBase; + NewThread->FSBase = Thread->FSBase; +#endif + debug("Forked thread \"%s\"(%d) to \"%s\"(%d)", Thread->Name, Thread->ID, NewThread->Name, NewThread->ID); NewThread->Status = Tasking::TaskStatus::Ready; - - if (_ChildPID == (int)TaskManager->GetCurrentThread()->ID) - return 0; return (int)NewThread->ID; } diff --git a/SystemCalls/Syscalls.cpp b/SystemCalls/Syscalls.cpp index c9740a0..069d642 100644 --- a/SystemCalls/Syscalls.cpp +++ b/SystemCalls/Syscalls.cpp @@ -25,7 +25,6 @@ NewLock(SyscallsLock); extern "C" uintptr_t SystemCallsHandler(SyscallsFrame *Frame) { - CPU::Interrupts(CPU::Enable); SmartLock(SyscallsLock); /* TODO: This should be replaced or moved somewhere else. */ Tasking::TaskInfo *Ptinfo = &TaskManager->GetCurrentProcess()->Info; diff --git a/Tasking/InterProcessCommunication.cpp b/Tasking/InterProcessCommunication.cpp index ac78fda..45b52cb 100644 --- a/Tasking/InterProcessCommunication.cpp +++ b/Tasking/InterProcessCommunication.cpp @@ -201,7 +201,7 @@ namespace InterProcessCommunication warn("Interrupts are disabled. This may cause a kernel hang."); debug("Waiting for IPC %d (now %s)", ID, Hnd->Listening ? "listening" : "ready"); while (Hnd->Listening) - CPU::Pause(); + TaskManager->Schedule(); debug("IPC %d is ready", ID); return IPCSuccess; } diff --git a/Tasking/Task.cpp b/Tasking/Task.cpp index ec079d3..2cef53b 100644 --- a/Tasking/Task.cpp +++ b/Tasking/Task.cpp @@ -48,16 +48,6 @@ NewLock(TaskingLock); namespace Tasking { - void Task::Schedule() - { - if (!StopScheduler) - TaskingScheduler_OneShot(1); - // APIC::InterruptCommandRegisterLow icr; - // icr.Vector = CPU::x86::IRQ16; - // icr.Level = APIC::APICLevel::Assert; - // ((APIC::APIC *)Interrupts::apic[0])->IPI(GetCurrentCPU()->ID, icr); - } - #if defined(a86) __naked __used __no_stack_protector NIF void IdleProcessLoop() { diff --git a/include/task.hpp b/include/task.hpp index eabe348..e20e436 100644 --- a/include/task.hpp +++ b/include/task.hpp @@ -289,7 +289,14 @@ namespace Tasking Security *GetSecurityManager() { return &SecurityManager; } void CleanupProcessesThread(); void Panic() { StopScheduler = true; } - void Schedule(); + __always_inline inline void Schedule() + { +#if defined(a86) + asmv("int $0x30"); /* This will trigger the IRQ16 instantly so we won't execute the next instruction */ +#elif defined(aa64) + asmv("svc #0x30"); /* This will trigger the IRQ16 instantly so we won't execute the next instruction */ +#endif + } void SignalShutdown(); void RevertProcessCreation(PCB *Process); void RevertThreadCreation(TCB *Thread);