Fix fork() syscall

This commit is contained in:
Alex 2023-05-22 00:43:45 +03:00
parent 5cb799df89
commit 061363d85d
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
5 changed files with 32 additions and 44 deletions

View File

@ -40,7 +40,6 @@ using Tasking::TTL::Untrusted;
static inline bool CheckTrust(int TrustLevel) static inline bool CheckTrust(int TrustLevel)
{ {
// SmartTimeoutLock(SyscallsLock, 10000); - This is already done in the caller
Token token = TaskManager->GetCurrentThread()->Security.UniqueToken; Token token = TaskManager->GetCurrentThread()->Security.UniqueToken;
if (TaskManager->GetSecurityManager()->IsTokenTrusted(token, TrustLevel)) if (TaskManager->GetSecurityManager()->IsTokenTrusted(token, TrustLevel))
return true; return true;
@ -340,17 +339,12 @@ static int sys_sleep(SyscallsFrame *Frame, uint64_t Milliseconds)
return 0; return 0;
} }
static int _ChildPID = 0;
static int sys_fork(SyscallsFrame *Frame) static int sys_fork(SyscallsFrame *Frame)
{ {
UNUSED(Frame); UNUSED(Frame);
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted)) if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
return SYSCALL_ACCESS_DENIED; return SYSCALL_ACCESS_DENIED;
fixme("sys_fork: %#lx", Frame);
return SYSCALL_NOT_IMPLEMENTED;
Tasking::PCB *Parent = TaskManager->GetCurrentThread()->Parent; Tasking::PCB *Parent = TaskManager->GetCurrentThread()->Parent;
Tasking::TCB *Thread = TaskManager->GetCurrentThread(); Tasking::TCB *Thread = TaskManager->GetCurrentThread();
@ -378,34 +372,19 @@ static int sys_fork(SyscallsFrame *Frame)
Thread->Info.Compatibility, Thread->Info.Compatibility,
true); true);
strncpy(NewThread->Name, Thread->Name, sizeof(Thread->Name));
if (!NewThread) if (!NewThread)
{ {
error("Failed to create thread for fork"); error("Failed to create thread for fork");
return SYSCALL_ERROR; 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 int RetChild = 0;
static uint64_t ReturnAddress = 0; static uint64_t ReturnAddress = 0;
static uint64_t ChildStackPointer = 0; static uint64_t ChildStackPointer = 0;
#if defined(a86) TaskManager->Schedule();
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
if (RetChild--) if (RetChild--)
{ {
@ -413,28 +392,41 @@ static int sys_fork(SyscallsFrame *Frame)
asmv("movq %0, %%rcx\n" asmv("movq %0, %%rcx\n"
: :
: "r"(ReturnAddress)); : "r"(ReturnAddress));
asmv("movq $0, %rax\n"); // Return 0 to the child
asmv("mov %0, %%rsp\n" asmv("mov %0, %%rsp\n"
: :
: "r"(ChildStackPointer)); : "r"(ChildStackPointer));
asmv("mov %0, %%rbp\n" asmv("mov %0, %%rbp\n"
: :
: "r"(ChildStackPointer)); : "r"(ChildStackPointer));
asmv("swapgs\n"); // Swap GS back to the user GS asmv("movq $0, %rax\n"); // Return 0 to the child
asmv("sti\n"); // Enable interrupts asmv("swapgs\n"); // Swap GS back to the user GS
asmv("sysretq\n"); // Return to rcx address in user mode asmv("sti\n"); // Enable interrupts
asmv("sysretq\n"); // Return to rcx address in user mode
} }
RetChild = 1; RetChild = 1;
ReturnAddress = Frame->ReturnAddress; ReturnAddress = Frame->ReturnAddress;
ChildStackPointer = Frame->StackPointer; 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; 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); debug("Forked thread \"%s\"(%d) to \"%s\"(%d)", Thread->Name, Thread->ID, NewThread->Name, NewThread->ID);
NewThread->Status = Tasking::TaskStatus::Ready; NewThread->Status = Tasking::TaskStatus::Ready;
if (_ChildPID == (int)TaskManager->GetCurrentThread()->ID)
return 0;
return (int)NewThread->ID; return (int)NewThread->ID;
} }

View File

@ -25,7 +25,6 @@ NewLock(SyscallsLock);
extern "C" uintptr_t SystemCallsHandler(SyscallsFrame *Frame) extern "C" uintptr_t SystemCallsHandler(SyscallsFrame *Frame)
{ {
CPU::Interrupts(CPU::Enable);
SmartLock(SyscallsLock); /* TODO: This should be replaced or moved somewhere else. */ SmartLock(SyscallsLock); /* TODO: This should be replaced or moved somewhere else. */
Tasking::TaskInfo *Ptinfo = &TaskManager->GetCurrentProcess()->Info; Tasking::TaskInfo *Ptinfo = &TaskManager->GetCurrentProcess()->Info;

View File

@ -201,7 +201,7 @@ namespace InterProcessCommunication
warn("Interrupts are disabled. This may cause a kernel hang."); warn("Interrupts are disabled. This may cause a kernel hang.");
debug("Waiting for IPC %d (now %s)", ID, Hnd->Listening ? "listening" : "ready"); debug("Waiting for IPC %d (now %s)", ID, Hnd->Listening ? "listening" : "ready");
while (Hnd->Listening) while (Hnd->Listening)
CPU::Pause(); TaskManager->Schedule();
debug("IPC %d is ready", ID); debug("IPC %d is ready", ID);
return IPCSuccess; return IPCSuccess;
} }

View File

@ -48,16 +48,6 @@ NewLock(TaskingLock);
namespace Tasking 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) #if defined(a86)
__naked __used __no_stack_protector NIF void IdleProcessLoop() __naked __used __no_stack_protector NIF void IdleProcessLoop()
{ {

View File

@ -289,7 +289,14 @@ namespace Tasking
Security *GetSecurityManager() { return &SecurityManager; } Security *GetSecurityManager() { return &SecurityManager; }
void CleanupProcessesThread(); void CleanupProcessesThread();
void Panic() { StopScheduler = true; } 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 SignalShutdown();
void RevertProcessCreation(PCB *Process); void RevertProcessCreation(PCB *Process);
void RevertThreadCreation(TCB *Thread); void RevertThreadCreation(TCB *Thread);