Fix sleep syscall

This commit is contained in:
Alex 2023-06-11 01:36:39 +03:00
parent f552b8f6f0
commit 85c0de688d
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
14 changed files with 829 additions and 673 deletions

View File

@ -31,64 +31,69 @@ extern "C" void SystemCallHandlerStub();
extern "C" __naked __used __no_stack_protector __aligned(16) void SystemCallHandlerStub() extern "C" __naked __used __no_stack_protector __aligned(16) void SystemCallHandlerStub()
{ {
asmv("swapgs\n"); /* Swap GS to get the CPUData */ asmv("swapgs\n"); /* Swap GS to get the TCB */
asmv("mov %rsp, %gs:0x8\n"); /* We save the current rsp to CPUData->TempStack */ asmv("mov %rsp, %gs:0x8\n"); /* We save the current rsp to TCB->TempStack */
asmv("mov %gs:0x0, %rsp\n"); /* Get CPUData->SystemCallStack and set it as rsp */ asmv("mov %gs:0x0, %rsp\n"); /* Get TCB->SystemCallStack and set it as rsp */
asmv("push $0x1b\n"); /* Push user data segment for SyscallsFrame */ asmv("push $0x1b\n"); /* Push user data segment for SyscallsFrame */
asmv("push %gs:0x8\n"); /* Push CPUData->TempStack (old rsp) for SyscallsFrame */ asmv("push %gs:0x8\n"); /* Push TCB->TempStack (old rsp) for SyscallsFrame */
asmv("push %r11\n"); /* Push the flags for SyscallsFrame */ asmv("push %r11\n"); /* Push the flags for SyscallsFrame */
asmv("push $0x23\n"); /* Push user code segment for SyscallsFrame */ asmv("push $0x23\n"); /* Push user code segment for SyscallsFrame */
asmv("push %rcx\n"); /* Push the return address for SyscallsFrame + sysretq (https://www.felixcloutier.com/x86/sysret) */ asmv("push %rcx\n"); /* Push the return address for SyscallsFrame + sysretq (https://www.felixcloutier.com/x86/sysret) */
asmv("push %rax\n" /* Push registers */ /* Push registers */
"push %rbx\n" asmv("push %rax\n"
"push %rcx\n" "push %rbx\n"
"push %rdx\n" "push %rcx\n"
"push %rsi\n" "push %rdx\n"
"push %rdi\n" "push %rsi\n"
"push %rbp\n" "push %rdi\n"
"push %r8\n" "push %rbp\n"
"push %r9\n" "push %r8\n"
"push %r10\n" "push %r9\n"
"push %r11\n" "push %r10\n"
"push %r12\n" "push %r11\n"
"push %r13\n" "push %r12\n"
"push %r14\n" "push %r13\n"
"push %r15\n"); "push %r14\n"
"push %r15\n");
asmv("mov %rsp, %rdi\n"); /* Set the first argument to the SyscallsFrame pointer */ /* Set the first argument to the SyscallsFrame pointer */
asmv("mov $0, %rbp\n"); asmv("mov %rsp, %rdi\n");
asmv("call SystemCallsHandler\n"); asmv("mov $0, %rbp\n");
asmv("call SystemCallsHandler\n");
asmv("pop %r15\n" /* Pop registers except rax */ /* Pop registers except rax */
"pop %r14\n" asmv("pop %r15\n"
"pop %r13\n" "pop %r14\n"
"pop %r12\n" "pop %r13\n"
"pop %r11\n" "pop %r12\n"
"pop %r10\n" "pop %r11\n"
"pop %r9\n" "pop %r10\n"
"pop %r8\n" "pop %r9\n"
"pop %rbp\n" "pop %r8\n"
"pop %rdi\n" "pop %rbp\n"
"pop %rsi\n" "pop %rdi\n"
"pop %rdx\n" "pop %rsi\n"
"pop %rcx\n" "pop %rdx\n"
"pop %rbx\n"); "pop %rcx\n"
"pop %rbx\n");
asmv("mov %gs:0x8, %rsp\n"); // Restore rsp from CPUData->TempStack /* Restore rsp from TCB->TempStack */
asmv("mov %gs:0x8, %rsp\n");
#ifdef DEBUG #ifdef DEBUG
asmv("movq $0, %gs:0x8\n"); // Easier to debug stacks // FIXME: Can't use xor /* Easier to debug stacks */
asmv("movq $0, %gs:0x8\n");
#endif #endif
asmv("swapgs\n"); // Swap GS back to the user GS asmv("swapgs\n"); /* Swap GS back to the user GS */
asmv("sti\n"); // Enable interrupts asmv("sti\n"); /* Enable interrupts */
asmv("sysretq\n"); // Return to rcx address in user mode asmv("sysretq\n"); /* Return to rcx address in user mode */
} }
void InitializeSystemCalls() void InitializeSystemCalls()
{ {
wrmsr(MSR_EFER, rdmsr(MSR_EFER) | 1); wrmsr(MSR_EFER, rdmsr(MSR_EFER) | 1);
wrmsr(MSR_STAR, ((uint64_t)(GDT_KERNEL_CODE) << 32) | ((uint64_t)(GDT_KERNEL_DATA | 3) << 48)); wrmsr(MSR_STAR, ((uint64_t)(GDT_KERNEL_CODE) << 32) | ((uint64_t)(GDT_KERNEL_DATA | 3) << 48));
wrmsr(MSR_LSTAR, (uint64_t)SystemCallHandlerStub); wrmsr(MSR_LSTAR, (uint64_t)SystemCallHandlerStub);
wrmsr(MSR_SYSCALL_MASK, (uint64_t)(1 << 9)); wrmsr(MSR_SYSCALL_MASK, (uint64_t)(1 << 9));
} }

View File

@ -52,7 +52,6 @@ namespace CrashHandler
if (cpu) if (cpu)
{ {
EHPrint("\eE46CEBCPU Data Address: %#lx\n", cpu); EHPrint("\eE46CEBCPU Data Address: %#lx\n", cpu);
EHPrint("Syscalls Stack: %#lx, TempStack: %#lx\n", cpu->SystemCallStack, cpu->TempStack);
EHPrint("Core Stack: %#lx, Core ID: %ld, Error Code: %ld\n", cpu->Stack, cpu->ID, cpu->ErrorCode); EHPrint("Core Stack: %#lx, Core ID: %ld, Error Code: %ld\n", cpu->Stack, cpu->ID, cpu->ErrorCode);
EHPrint("Is Active: %s\n", cpu->IsActive ? "true" : "false"); EHPrint("Is Active: %s\n", cpu->IsActive ? "true" : "false");
EHPrint("Current Process: %#lx, Current Thread: %#lx\n", cpu->CurrentProcess, cpu->CurrentThread); EHPrint("Current Process: %#lx, Current Thread: %#lx\n", cpu->CurrentProcess, cpu->CurrentThread);

View File

@ -67,7 +67,6 @@ namespace Interrupts
CPU::x64::wrmsr(CPU::x64::MSR_SHADOW_GS_BASE, (uint64_t)CoreData); CPU::x64::wrmsr(CPU::x64::MSR_SHADOW_GS_BASE, (uint64_t)CoreData);
CoreData->ID = Core; CoreData->ID = Core;
CoreData->IsActive = true; CoreData->IsActive = true;
CoreData->SystemCallStack = (uint8_t *)((uintptr_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)) + STACK_SIZE);
CoreData->Stack = (uintptr_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)) + STACK_SIZE; CoreData->Stack = (uintptr_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)) + STACK_SIZE;
if (CoreData->Checksum != CPU_DATA_CHECKSUM) if (CoreData->Checksum != CPU_DATA_CHECKSUM)
{ {
@ -85,7 +84,6 @@ namespace Interrupts
CPU::x32::wrmsr(CPU::x32::MSR_SHADOW_GS_BASE, (uint64_t)CoreData); CPU::x32::wrmsr(CPU::x32::MSR_SHADOW_GS_BASE, (uint64_t)CoreData);
CoreData->ID = Core; CoreData->ID = Core;
CoreData->IsActive = true; CoreData->IsActive = true;
CoreData->SystemCallStack = (uint8_t *)((uintptr_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)) + STACK_SIZE);
CoreData->Stack = (uintptr_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)) + STACK_SIZE; CoreData->Stack = (uintptr_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)) + STACK_SIZE;
if (CoreData->Checksum != CPU_DATA_CHECKSUM) if (CoreData->Checksum != CPU_DATA_CHECKSUM)
{ {

View File

@ -60,6 +60,7 @@ namespace Memory
uint64_t MemMgr::GetAllocatedMemorySize() uint64_t MemMgr::GetAllocatedMemorySize()
{ {
SmartLock(MgrLock);
uint64_t Size = 0; uint64_t Size = 0;
foreach (auto ap in AllocatedPagesList) foreach (auto ap in AllocatedPagesList)
Size += ap.PageCount; Size += ap.PageCount;
@ -68,6 +69,7 @@ namespace Memory
bool MemMgr::Add(void *Address, size_t Count) bool MemMgr::Add(void *Address, size_t Count)
{ {
SmartLock(MgrLock);
if (Address == nullptr) if (Address == nullptr)
{ {
error("Address is null!"); error("Address is null!");
@ -124,6 +126,7 @@ namespace Memory
void *MemMgr::RequestPages(size_t Count, bool User) void *MemMgr::RequestPages(size_t Count, bool User)
{ {
SmartLock(MgrLock);
void *Address = KernelAllocator.RequestPages(Count); void *Address = KernelAllocator.RequestPages(Count);
for (size_t i = 0; i < Count; i++) for (size_t i = 0; i < Count; i++)
{ {
@ -162,6 +165,7 @@ namespace Memory
void MemMgr::FreePages(void *Address, size_t Count) void MemMgr::FreePages(void *Address, size_t Count)
{ {
SmartLock(MgrLock);
for (size_t i = 0; i < AllocatedPagesList.size(); i++) for (size_t i = 0; i < AllocatedPagesList.size(); i++)
{ {
if (AllocatedPagesList[i].Address == Address) if (AllocatedPagesList[i].Address == Address)
@ -205,6 +209,7 @@ namespace Memory
void MemMgr::DetachAddress(void *Address) void MemMgr::DetachAddress(void *Address)
{ {
SmartLock(MgrLock);
for (size_t i = 0; i < AllocatedPagesList.size(); i++) for (size_t i = 0; i < AllocatedPagesList.size(); i++)
{ {
if (AllocatedPagesList[i].Address == Address) if (AllocatedPagesList[i].Address == Address)
@ -226,6 +231,7 @@ namespace Memory
MemMgr::MemMgr(PageTable *Table, VirtualFileSystem::Node *Directory) MemMgr::MemMgr(PageTable *Table, VirtualFileSystem::Node *Directory)
{ {
SmartLock(MgrLock);
if (Table) if (Table)
this->Table = Table; this->Table = Table;
else else
@ -243,6 +249,7 @@ namespace Memory
MemMgr::~MemMgr() MemMgr::~MemMgr()
{ {
SmartLock(MgrLock);
foreach (auto ap in AllocatedPagesList) foreach (auto ap in AllocatedPagesList)
{ {
KernelAllocator.FreePages(ap.Address, ap.PageCount); KernelAllocator.FreePages(ap.Address, ap.PageCount);

View File

@ -60,22 +60,32 @@ EXTERNC __weak __noreturn __no_stack_protector void __stack_chk_fail(void)
debug("Current stack check guard value: %#lx", __stack_chk_guard); debug("Current stack check guard value: %#lx", __stack_chk_guard);
KPrint("\eFF0000Stack smashing detected!"); KPrint("\eFF0000Stack smashing detected!");
#if defined(a86)
void *Stack = nullptr; void *Stack = nullptr;
#if defined(a86)
#if defined(a64) #if defined(a64)
asmv("movq %%rsp, %0" asmv("movq %%rsp, %0"
: "=r"(Stack)); : "=r"(Stack));
#elif defined(a32) #elif defined(a32)
asmv("movl %%esp, %0" asmv("movl %%esp, %0"
: "=r"(Stack)); : "=r"(Stack));
#endif
#elif defined(aa64)
asmv("mov %%sp, %0"
: "=r"(Stack));
#endif #endif
error("Stack address: %#lx", Stack); error("Stack address: %#lx", Stack);
while (1) if (DebuggerIsAttached)
asmv("cli; hlt"); #ifdef a86
asmv("int $0x3");
#elif defined(aa64) #elif defined(aa64)
asmv("wfe"); asmv("brk #0");
#endif #endif
CPU::Stop(); CPU::Stop();
} }

View File

@ -497,21 +497,20 @@ void KernelMainThread()
TaskManager->WaitForThread(ret.Thread); TaskManager->WaitForThread(ret.Thread);
ExitCode = ret.Thread->GetExitCode(); ExitCode = ret.Thread->GetExitCode();
Exit: Exit:
if (ExitCode != 0) if (ExitCode == 0)
{
KPrint("\eE85230Userspace process exited with code %d (%#x)", ExitCode,
ExitCode < 0 ? ExitCode * -1 : ExitCode);
KPrint("Dropping to recovery screen...");
TaskManager->Sleep(2500);
TaskManager->WaitForThread(blaThread);
RecoveryScreen = new Recovery::KernelRecovery;
}
else
{ {
KPrint("\eFF7900%s process exited with code %d and it didn't invoked the shutdown function.", KPrint("\eFF7900%s process exited with code %d and it didn't invoked the shutdown function.",
Config.InitPath, ExitCode); Config.InitPath, ExitCode);
KPrint("System Halted"); KPrint("System Halted");
CPU::Halt(true);
} }
KPrint("\eE85230Userspace process exited with code %d (%#x)", ExitCode,
ExitCode < 0 ? -ExitCode : ExitCode);
KPrint("Dropping to recovery screen...");
TaskManager->Sleep(2500);
TaskManager->WaitForThread(blaThread);
RecoveryScreen = new Recovery::KernelRecovery;
CPU::Halt(true); CPU::Halt(true);
} }

View File

@ -16,105 +16,75 @@
*/ */
#include <syscalls.hpp> #include <syscalls.hpp>
#include <memory.hpp> #include <memory.hpp>
#include <lock.hpp> #include <lock.hpp>
#include <exec.hpp> #include <exec.hpp>
#include <errno.h> #include <errno.h>
#include <debug.h> #include <debug.h>
#include "../syscalls.h" #include "../syscalls.h"
#include "../kernel.h" #include "../kernel.h"
#include "../ipc.h" #include "../ipc.h"
#define SysFrm SyscallsFrame
using InterProcessCommunication::IPC; using InterProcessCommunication::IPC;
using InterProcessCommunication::IPCID; using InterProcessCommunication::IPCID;
using Tasking::Token; using Tasking::Token;
using Tasking::TTL; using Tasking::TTL;
using Tasking::TaskStatus::Ready;
using Tasking::TaskStatus::Terminated;
using Tasking::TTL::Trusted; using Tasking::TTL::Trusted;
using Tasking::TTL::TrustedByKernel; using Tasking::TTL::TrustedByKernel;
using Tasking::TTL::UnknownTrustLevel; using Tasking::TTL::UnknownTrustLevel;
using Tasking::TTL::Untrusted; using Tasking::TTL::Untrusted;
static inline bool CheckTrust(int TrustLevel) __noreturn static void sys_exit(SysFrm *, int code)
{ {
Token token = TaskManager->GetCurrentThread()->Security.UniqueToken; trace("Userspace thread %s(%d) exited with code %d (%#x)",
if (likely(TaskManager->GetSecurityManager()->IsTokenTrusted(token, TrustLevel))) TaskManager->GetCurrentThread()->Name,
return true; TaskManager->GetCurrentThread()->ID, code,
code < 0 ? -code : code);
warn("Thread %s(%lld) tried to access a system call \"%s\" with insufficient trust level",
TaskManager->GetCurrentThread()->Name, TaskManager->GetCurrentThread()->ID,
KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_extract_return_addr(__builtin_return_address(0))));
debug("token=%#lx, trust=%d", token, TaskManager->GetSecurityManager()->GetTokenTrustLevel(token));
return false;
}
static int sys_exit(SyscallsFrame *Frame, int code)
{
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted | UnknownTrustLevel))
return SYSCALL_ACCESS_DENIED;
trace("Userspace thread %s(%lld) exited with code %#llx", TaskManager->GetCurrentThread()->Name, TaskManager->GetCurrentThread()->ID, code);
TaskManager->GetCurrentThread()->ExitCode = code; TaskManager->GetCurrentThread()->ExitCode = code;
TaskManager->GetCurrentThread()->Status = Tasking::TaskStatus::Terminated; TaskManager->GetCurrentThread()->Status = Terminated;
TaskManager->Schedule(); TaskManager->Schedule();
__builtin_unreachable();
UNUSED(Frame);
return SYSCALL_OK;
} }
static int sys_print(SyscallsFrame *Frame, char Char, int Index) static int sys_print(SysFrm *, char Char, int Index)
{ {
if (!CheckTrust(TrustedByKernel | Trusted))
return SYSCALL_ACCESS_DENIED;
char ret = Display->Print(Char, Index, true); char ret = Display->Print(Char, Index, true);
if (!Config.BootAnimation && Index == 0) if (!Config.BootAnimation && Index == 0)
#ifdef DEBUG
Display->SetBuffer(Index); Display->SetBuffer(Index);
#else
if (Char == '\n')
Display->SetBuffer(Index);
#endif
UNUSED(Frame);
return ret; return ret;
} }
static uintptr_t sys_request_pages(SyscallsFrame *Frame, size_t Count) static uintptr_t sys_request_pages(SysFrm *, size_t Count)
{ {
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted)) Memory::MemMgr *MemMgr = TaskManager->GetCurrentThread()->Memory;
return SYSCALL_ACCESS_DENIED; return (uintptr_t)MemMgr->RequestPages(Count + 1, true);
UNUSED(Frame);
return (uintptr_t)TaskManager->GetCurrentThread()->Memory->RequestPages(Count + 1, true);
} }
static int sys_free_pages(SyscallsFrame *Frame, uintptr_t Address, size_t Count) static int sys_free_pages(SysFrm *, uintptr_t Address, size_t Count)
{ {
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted)) Memory::MemMgr *MemMgr = TaskManager->GetCurrentThread()->Memory;
return SYSCALL_ACCESS_DENIED; MemMgr->FreePages((void *)Address, Count + 1);
TaskManager->GetCurrentThread()->Memory->FreePages((void *)Address, Count + 1);
UNUSED(Frame);
return SYSCALL_OK; return SYSCALL_OK;
} }
static int sys_detach_address(SyscallsFrame *Frame, uintptr_t Address) static int sys_detach_address(SysFrm *, uintptr_t Address)
{ {
if (!CheckTrust(TrustedByKernel | Trusted)) Memory::MemMgr *MemMgr = TaskManager->GetCurrentThread()->Memory;
return SYSCALL_ACCESS_DENIED; MemMgr->DetachAddress((void *)Address);
TaskManager->GetCurrentThread()->Memory->DetachAddress((void *)Address);
UNUSED(Frame);
return SYSCALL_OK; return SYSCALL_OK;
} }
static int sys_memory_map(SyscallsFrame *Frame, uintptr_t VirtualAddress, uintptr_t PhysicalAddress, size_t Size, enum MemoryMapFlags Flags) static int sys_memory_map(SysFrm *, uintptr_t VirtualAddress,
uintptr_t PhysicalAddress, size_t Size,
enum MemoryMapFlags Flags)
{ {
if (!CheckTrust(TrustedByKernel))
return SYSCALL_ACCESS_DENIED;
if (Flags > 7) /* (MAP_PRESENT | MAP_WRITABLE | MAP_USER) */ if (Flags > 7) /* (MAP_PRESENT | MAP_WRITABLE | MAP_USER) */
return SYSCALL_INVALID_ARGUMENT; return SYSCALL_INVALID_ARGUMENT;
@ -126,15 +96,12 @@ static int sys_memory_map(SyscallsFrame *Frame, uintptr_t VirtualAddress, uintpt
Size, Flags); Size, Flags);
} }
UNUSED(Frame);
return SYSCALL_OK; return SYSCALL_OK;
} }
static int sys_memory_unmap(SyscallsFrame *Frame, uintptr_t VirtualAddress, size_t Size) static int sys_memory_unmap(SysFrm *, uintptr_t VirtualAddress,
size_t Size)
{ {
if (!CheckTrust(TrustedByKernel))
return SYSCALL_ACCESS_DENIED;
Memory::PageTable *PageTable = TaskManager->GetCurrentProcess()->PageTable; Memory::PageTable *PageTable = TaskManager->GetCurrentProcess()->PageTable;
{ {
Memory::Virtual vmm = Memory::Virtual(PageTable); Memory::Virtual vmm = Memory::Virtual(PageTable);
@ -142,19 +109,18 @@ static int sys_memory_unmap(SyscallsFrame *Frame, uintptr_t VirtualAddress, size
Size); Size);
} }
UNUSED(Frame);
return SYSCALL_OK; return SYSCALL_OK;
} }
static uintptr_t sys_kernelctl(SyscallsFrame *Frame, enum KCtl Command, uint64_t Arg1, uint64_t Arg2, uint64_t Arg3, uint64_t Arg4) static uintptr_t sys_kernelctl(SysFrm *,
enum KCtl Command,
uint64_t Arg1, uint64_t Arg2,
uint64_t Arg3, uint64_t Arg4)
{ {
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
return SYSCALL_ACCESS_DENIED;
switch (Command) switch (Command)
{ {
case KCTL_GET_PID: case KCTL_GET_PID:
return TaskManager->GetCurrentThread()->Parent->ID; return TaskManager->GetCurrentProcess()->ID;
case KCTL_GET_TID: case KCTL_GET_TID:
return TaskManager->GetCurrentThread()->ID; return TaskManager->GetCurrentThread()->ID;
case KCTL_GET_PAGE_SIZE: case KCTL_GET_PAGE_SIZE:
@ -163,9 +129,6 @@ static uintptr_t sys_kernelctl(SyscallsFrame *Frame, enum KCtl Command, uint64_t
return TaskManager->GetCurrentThread()->Security.IsCritical; return TaskManager->GetCurrentThread()->Security.IsCritical;
case KCTL_REGISTER_ELF_LIB: case KCTL_REGISTER_ELF_LIB:
{ {
if (!CheckTrust(TrustedByKernel | Trusted))
return SYSCALL_ACCESS_DENIED;
char *Identifier = (char *)Arg1; char *Identifier = (char *)Arg1;
const char *Path = (const char *)Arg2; const char *Path = (const char *)Arg2;
@ -175,7 +138,8 @@ static uintptr_t sys_kernelctl(SyscallsFrame *Frame, enum KCtl Command, uint64_t
std::string FullPath = Path; std::string FullPath = Path;
int retries = 0; int retries = 0;
RetryReadPath: RetryReadPath:
debug("KCTL_REGISTER_ELF_LIB: Trying to open %s", FullPath.c_str()); debug("KCTL_REGISTER_ELF_LIB: Trying to open %s",
FullPath.c_str());
VirtualFileSystem::File f = vfs->Open(FullPath.c_str()); VirtualFileSystem::File f = vfs->Open(FullPath.c_str());
if (!f.IsOK()) if (!f.IsOK())
@ -194,7 +158,8 @@ static uintptr_t sys_kernelctl(SyscallsFrame *Frame, enum KCtl Command, uint64_t
break; break;
case 3: case 3:
{ {
VirtualFileSystem::Node *cwd = TaskManager->GetCurrentProcess()->CurrentWorkingDirectory; VirtualFileSystem::Node *cwd =
TaskManager->GetCurrentProcess()->CurrentWorkingDirectory;
FullPath = vfs->GetPathFromNode(cwd).get(); FullPath = vfs->GetPathFromNode(cwd).get();
break; break;
} }
@ -223,9 +188,6 @@ static uintptr_t sys_kernelctl(SyscallsFrame *Frame, enum KCtl Command, uint64_t
} }
case KCTL_GET_ELF_LIB_MEMORY_IMAGE: case KCTL_GET_ELF_LIB_MEMORY_IMAGE:
{ {
if (!CheckTrust(TrustedByKernel | Trusted))
return SYSCALL_ACCESS_DENIED;
char *Identifier = (char *)Arg1; char *Identifier = (char *)Arg1;
if (!Identifier) if (!Identifier)
return 0; return 0;
@ -234,17 +196,16 @@ static uintptr_t sys_kernelctl(SyscallsFrame *Frame, enum KCtl Command, uint64_t
if (!lib.MemoryImage) if (!lib.MemoryImage)
{ {
debug("Failed to get library memory image %#lx", (uintptr_t)lib.MemoryImage); debug("Failed to get library memory image %#lx",
(uintptr_t)lib.MemoryImage);
} }
debug("Returning memory image %#lx (%s)", (uintptr_t)lib.MemoryImage, Identifier); debug("Returning memory image %#lx (%s)",
(uintptr_t)lib.MemoryImage, Identifier);
return (uintptr_t)lib.MemoryImage; return (uintptr_t)lib.MemoryImage;
} }
case KCTL_GET_ABSOLUTE_PATH: case KCTL_GET_ABSOLUTE_PATH:
{ {
if (!CheckTrust(TrustedByKernel | Trusted))
return SYSCALL_ACCESS_DENIED;
char *Identifier = (char *)Arg1; char *Identifier = (char *)Arg1;
void *Buffer = (void *)Arg2; void *Buffer = (void *)Arg2;
size_t BufferSize = Arg3; size_t BufferSize = Arg3;
@ -274,15 +235,11 @@ static uintptr_t sys_kernelctl(SyscallsFrame *Frame, enum KCtl Command, uint64_t
UNUSED(Arg2); UNUSED(Arg2);
UNUSED(Arg3); UNUSED(Arg3);
UNUSED(Arg4); UNUSED(Arg4);
UNUSED(Frame);
} }
static uint64_t sys_file_open(SyscallsFrame *Frame, const char *Path, uint64_t Flags) static uint64_t sys_file_open(SysFrm *, const char *Path, uint64_t Flags)
{ {
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted)) function("%s, %#lx", Path, Flags);
return SYSCALL_ACCESS_DENIED;
debug("(Path: %s, Flags: %#lx)", Path, Flags);
VirtualFileSystem::Node *cwd = nullptr; VirtualFileSystem::Node *cwd = nullptr;
if (vfs->PathIsRelative(Path)) if (vfs->PathIsRelative(Path))
cwd = TaskManager->GetCurrentProcess()->CurrentWorkingDirectory; cwd = TaskManager->GetCurrentProcess()->CurrentWorkingDirectory;
@ -297,118 +254,111 @@ static uint64_t sys_file_open(SyscallsFrame *Frame, const char *Path, uint64_t F
return SYSCALL_INTERNAL_ERROR; return SYSCALL_INTERNAL_ERROR;
} }
VirtualFileSystem::File *KernelPrivate = (VirtualFileSystem::File *)TaskManager->GetCurrentThread()->Memory->RequestPages(TO_PAGES(sizeof(VirtualFileSystem::File))); Memory::MemMgr *MemMgr = TaskManager->GetCurrentThread()->Memory;
constexpr size_t FileStructPages =
TO_PAGES(sizeof(VirtualFileSystem::File));
VirtualFileSystem::File *KernelPrivate =
(VirtualFileSystem::File *)MemMgr->RequestPages(FileStructPages);
*KernelPrivate = KPObj; *KernelPrivate = KPObj;
debug("Opened file %s (%d)", KPObj.Name, KPObj.Status); debug("Opened file %s (%d)", KPObj.Name, KPObj.Status);
return (uint64_t)KernelPrivate; return (uint64_t)KernelPrivate;
UNUSED(Frame);
UNUSED(Flags); UNUSED(Flags);
} }
static int sys_file_close(SyscallsFrame *Frame, void *KernelPrivate) static int sys_file_close(SysFrm *, void *KernelPrivate)
{ {
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted)) function("%#lx", KernelPrivate);
return SYSCALL_ACCESS_DENIED;
debug("(KernelPrivate: %#lx)", KernelPrivate);
if (KernelPrivate) if (KernelPrivate)
{ {
VirtualFileSystem::File KPObj = *(VirtualFileSystem::File *)KernelPrivate; VirtualFileSystem::File KPObj = *(VirtualFileSystem::File *)KernelPrivate;
debug("Closed file %s (%d)", KPObj.Name, KPObj.Status); debug("Closed file %s (%d)", KPObj.Name, KPObj.Status);
vfs->Close(KPObj); vfs->Close(KPObj);
TaskManager->GetCurrentThread()->Memory->FreePages(KernelPrivate, TO_PAGES(sizeof(VirtualFileSystem::File))); Memory::MemMgr *MemMgr = TaskManager->GetCurrentThread()->Memory;
MemMgr->FreePages(KernelPrivate,
TO_PAGES(sizeof(VirtualFileSystem::File)));
return SYSCALL_OK; return SYSCALL_OK;
} }
return SYSCALL_INVALID_ARGUMENT; return SYSCALL_INVALID_ARGUMENT;
UNUSED(Frame);
} }
static uint64_t sys_file_read(SyscallsFrame *Frame, void *KernelPrivate, uint8_t *Buffer, uint64_t Size) static uint64_t sys_file_read(SysFrm *, void *KernelPrivate,
uint8_t *Buffer, uint64_t Size)
{ {
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
return SYSCALL_ACCESS_DENIED;
if (KernelPrivate == nullptr) if (KernelPrivate == nullptr)
return 0; return 0;
debug("(KernelPrivate: %#lx, Offset: %#lx, Buffer: %#lx, Size: %#lx)", KernelPrivate, Buffer, Size); debug("(KernelPrivate: %#lx, Offset: %#lx, Buffer: %#lx, Size: %#lx)",
return vfs->Read(*(VirtualFileSystem::File *)KernelPrivate, Buffer, (size_t)Size); KernelPrivate, Buffer, Size);
UNUSED(Frame);
}
static uint64_t sys_file_write(SyscallsFrame *Frame, void *KernelPrivate, uint8_t *Buffer, uint64_t Size)
{
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
return SYSCALL_ACCESS_DENIED;
if (KernelPrivate == nullptr)
return 0;
debug("(KernelPrivate: %#lx, Offset: %#lx, Buffer: %#lx, Size: %#lx)", KernelPrivate, Buffer, Size);
return vfs->Write(*(VirtualFileSystem::File *)KernelPrivate, Buffer, (size_t)Size);
UNUSED(Frame);
}
static off_t sys_file_seek(SyscallsFrame *Frame, void *KernelPrivate, off_t Offset, int Whence)
{
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
return SYSCALL_ACCESS_DENIED;
if (KernelPrivate == nullptr)
return 0;
debug("(KernelPrivate: %#lx, Offset: %#lx, Whence: %d)", KernelPrivate, Offset, Whence);
VirtualFileSystem::File *KPObj = (VirtualFileSystem::File *)KernelPrivate; VirtualFileSystem::File *KPObj = (VirtualFileSystem::File *)KernelPrivate;
return vfs->Read(*KPObj, Buffer, (size_t)Size);
}
static uint64_t sys_file_write(SysFrm *, void *KernelPrivate,
uint8_t *Buffer, uint64_t Size)
{
if (KernelPrivate == nullptr)
return 0;
debug("(KernelPrivate: %#lx, Offset: %#lx, Buffer: %#lx, Size: %#lx)",
KernelPrivate, Buffer, Size);
VirtualFileSystem::File *KPObj = (VirtualFileSystem::File *)KernelPrivate;
return vfs->Write(*KPObj, Buffer, (size_t)Size);
}
static off_t sys_file_seek(SysFrm *, void *KernelPrivate,
off_t Offset, int Whence)
{
if (KernelPrivate == nullptr)
return 0;
debug("(KernelPrivate: %#lx, Offset: %#lx, Whence: %d)",
KernelPrivate, Offset, Whence);
VirtualFileSystem::File *KPObj = (VirtualFileSystem::File *)KernelPrivate;
off_t ret = vfs->Seek(*KPObj, (off_t)Offset, (uint8_t)Whence); off_t ret = vfs->Seek(*KPObj, (off_t)Offset, (uint8_t)Whence);
debug("Seek %s %ld", KPObj->Name, ret); debug("Seek %s %ld", KPObj->Name, ret);
return ret; return ret;
UNUSED(Frame);
} }
static int sys_file_status(SyscallsFrame *Frame) static int sys_file_status(SysFrm *)
{ {
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted)) stub;
return SYSCALL_ACCESS_DENIED;
fixme("sys_file_status: %#lx", Frame);
return SYSCALL_NOT_IMPLEMENTED; return SYSCALL_NOT_IMPLEMENTED;
} }
static int sys_ipc(SyscallsFrame *Frame, enum IPCCommand Command, enum IPCType Type, int ID, int Flags, void *Buffer, size_t Size) static int sys_ipc(SysFrm *, enum IPCCommand Command,
enum IPCType Type, int ID, int Flags,
void *Buffer, size_t Size)
{ {
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted)) InterProcessCommunication::IPC *ipc = TaskManager->GetCurrentProcess()->IPC;
return SYSCALL_ACCESS_DENIED; return ipc->HandleSyscall(Command, Type, ID, Flags, Buffer, Size);
UNUSED(Frame);
return TaskManager->GetCurrentProcess()->IPC->HandleSyscall(Command, Type, ID, Flags, Buffer, Size);
} }
static int sys_sleep(SyscallsFrame *Frame, uint64_t Milliseconds) static int sys_sleep(SysFrm *, uint64_t Milliseconds)
{ {
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted)) TaskManager->Sleep(Milliseconds, true);
return SYSCALL_ACCESS_DENIED;
UNUSED(Frame);
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
return SYSCALL_ACCESS_DENIED;
TaskManager->Sleep(Milliseconds);
return 0; return 0;
} }
static int sys_fork(SyscallsFrame *Frame) static int sys_fork(SysFrm *Frame)
{ {
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
return SYSCALL_ACCESS_DENIED;
Tasking::PCB *Parent = TaskManager->GetCurrentThread()->Parent; Tasking::PCB *Parent = TaskManager->GetCurrentThread()->Parent;
Tasking::TCB *Thread = TaskManager->GetCurrentThread(); Tasking::TCB *Thread = TaskManager->GetCurrentThread();
Tasking::PCB *NewProcess = TaskManager->CreateProcess(Parent, void *ProcSymTable = nullptr;
Parent->Name, if (Parent->ELFSymbolTable)
Parent->Security.TrustLevel, ProcSymTable = Parent->ELFSymbolTable->GetImage();
Parent->ELFSymbolTable ? Parent->ELFSymbolTable->GetImage() : nullptr);
Tasking::PCB *NewProcess =
TaskManager->CreateProcess(Parent,
Parent->Name,
Parent->Security.TrustLevel,
ProcSymTable);
if (!NewProcess) if (!NewProcess)
{ {
@ -419,14 +369,15 @@ static int sys_fork(SyscallsFrame *Frame)
strncpy(NewProcess->Name, Parent->Name, sizeof(NewProcess->Name)); strncpy(NewProcess->Name, Parent->Name, sizeof(NewProcess->Name));
NewProcess->IPC->Fork(Parent->IPC); NewProcess->IPC->Fork(Parent->IPC);
Tasking::TCB *NewThread = TaskManager->CreateThread(NewProcess, Tasking::TCB *NewThread =
0, TaskManager->CreateThread(NewProcess,
nullptr, 0,
nullptr, nullptr,
std::vector<AuxiliaryVector>(), nullptr,
Thread->Info.Architecture, std::vector<AuxiliaryVector>(),
Thread->Info.Compatibility, Thread->Info.Architecture,
true); Thread->Info.Compatibility,
true);
strncpy(NewThread->Name, Thread->Name, sizeof(Thread->Name)); strncpy(NewThread->Name, Thread->Name, sizeof(Thread->Name));
@ -444,7 +395,9 @@ static int sys_fork(SyscallsFrame *Frame)
if (RetChild--) if (RetChild--)
{ {
/* We can't just return 0; because the CPUData->SystemCallStack is no longer valid */ /* We can't just return 0; because the
CPUData->SystemCallStack is no
longer valid */
asmv("movq %0, %%rcx\n" asmv("movq %0, %%rcx\n"
: :
: "r"(ReturnAddress)); : "r"(ReturnAddress));
@ -454,10 +407,10 @@ static int sys_fork(SyscallsFrame *Frame)
asmv("mov %0, %%rbp\n" asmv("mov %0, %%rbp\n"
: :
: "r"(ChildStackPointer)); : "r"(ChildStackPointer));
asmv("movq $0, %rax\n"); // Return 0 to the child asmv("movq $0, %rax\n"); /* Return 0 to the child */
asmv("swapgs\n"); // Swap GS back to the user GS asmv("swapgs\n"); /* Swap GS back to the user GS */
asmv("sti\n"); // Enable interrupts asmv("sti\n"); /* Enable interrupts */
asmv("sysretq\n"); // Return to rcx address in user mode asmv("sysretq\n"); /* Return to rcx address in user mode */
} }
RetChild = 1; RetChild = 1;
ReturnAddress = Frame->ReturnAddress; ReturnAddress = Frame->ReturnAddress;
@ -470,10 +423,12 @@ static int sys_fork(SyscallsFrame *Frame)
if (Thread->Security.IsCritical) if (Thread->Security.IsCritical)
NewThread->SetCritical(true); NewThread->SetCritical(true);
TaskManager->GetSecurityManager()->TrustToken(NewProcess->Security.UniqueToken,
(Tasking::TTL)TaskManager->GetSecurityManager()->GetTokenTrustLevel(Parent->Security.UniqueToken)); Tasking::Security *Sec = TaskManager->GetSecurityManager();
TaskManager->GetSecurityManager()->TrustToken(NewThread->Security.UniqueToken, Sec->TrustToken(NewProcess->Security.UniqueToken,
(Tasking::TTL)TaskManager->GetSecurityManager()->GetTokenTrustLevel(Thread->Security.UniqueToken)); (TTL)Sec->GetTokenTrustLevel(Parent->Security.UniqueToken));
Sec->TrustToken(NewThread->Security.UniqueToken,
(TTL)Sec->GetTokenTrustLevel(Thread->Security.UniqueToken));
#ifdef a86 #ifdef a86
NewThread->ShadowGSBase = Thread->ShadowGSBase; NewThread->ShadowGSBase = Thread->ShadowGSBase;
@ -482,180 +437,358 @@ static int sys_fork(SyscallsFrame *Frame)
#endif #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 = Ready;
return (int)NewThread->ID; return (int)NewThread->ID;
UNUSED(Frame);
} }
static int sys_wait(SyscallsFrame *Frame) static int sys_wait(SysFrm *)
{ {
fixme("sys_wait: %#lx", Frame); stub;
return SYSCALL_NOT_IMPLEMENTED; return SYSCALL_NOT_IMPLEMENTED;
} }
static int sys_kill(SyscallsFrame *Frame) static int sys_kill(SysFrm *)
{ {
fixme("sys_kill: %#lx", Frame); stub;
return SYSCALL_NOT_IMPLEMENTED; return SYSCALL_NOT_IMPLEMENTED;
} }
static int sys_spawn(SyscallsFrame *Frame) static int sys_spawn(SysFrm *)
{ {
fixme("sys_spawn: %#lx", Frame); stub;
return SYSCALL_NOT_IMPLEMENTED; return SYSCALL_NOT_IMPLEMENTED;
} }
static int sys_spawn_thread(SyscallsFrame *Frame, uint64_t InstructionPointer) static int sys_spawn_thread(SysFrm *, uint64_t InstructionPointer)
{ {
Tasking::TCB *thread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)InstructionPointer); Tasking::TCB *thread =
TaskManager->CreateThread(TaskManager->GetCurrentProcess(),
(Tasking::IP)InstructionPointer);
if (thread) if (thread)
return (int)thread->ID; return (int)thread->ID;
return SYSCALL_ERROR; return SYSCALL_ERROR;
} }
static int sys_get_thread_list_of_process(SyscallsFrame *Frame) static int sys_get_thread_list_of_process(SysFrm *)
{ {
fixme("sys_get_thread_list_of_process: %#lx", Frame); stub;
return SYSCALL_NOT_IMPLEMENTED; return SYSCALL_NOT_IMPLEMENTED;
} }
static int sys_get_current_process(SyscallsFrame *Frame) static int sys_get_current_process(SysFrm *)
{ {
fixme("sys_get_current_process: %#lx", Frame); stub;
return SYSCALL_NOT_IMPLEMENTED; return SYSCALL_NOT_IMPLEMENTED;
} }
static int sys_get_current_thread(SyscallsFrame *Frame) static int sys_get_current_thread(SysFrm *)
{ {
fixme("sys_get_current_thread: %#lx", Frame); stub;
return SYSCALL_NOT_IMPLEMENTED; return SYSCALL_NOT_IMPLEMENTED;
} }
static int sys_get_current_process_id(SyscallsFrame *Frame) static int sys_get_current_process_id(SysFrm *)
{ {
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
return SYSCALL_ACCESS_DENIED;
return (int)TaskManager->GetCurrentProcess()->ID; return (int)TaskManager->GetCurrentProcess()->ID;
} }
static int sys_get_current_thread_id(SyscallsFrame *Frame) static int sys_get_current_thread_id(SysFrm *)
{ {
if (!CheckTrust(TrustedByKernel | Trusted | Untrusted))
return SYSCALL_ACCESS_DENIED;
return (int)TaskManager->GetCurrentThread()->ID; return (int)TaskManager->GetCurrentThread()->ID;
} }
static int sys_get_process_by_pid(SyscallsFrame *Frame) static int sys_get_process_by_pid(SysFrm *)
{ {
fixme("sys_get_process_by_pid: %#lx", Frame); stub;
return SYSCALL_NOT_IMPLEMENTED; return SYSCALL_NOT_IMPLEMENTED;
} }
static int sys_get_thread_by_tid(SyscallsFrame *Frame) static int sys_get_thread_by_tid(SysFrm *)
{ {
fixme("sys_get_thread_by_tid: %#lx", Frame); stub;
return SYSCALL_NOT_IMPLEMENTED; return SYSCALL_NOT_IMPLEMENTED;
} }
static int sys_kill_process(SyscallsFrame *Frame) static int sys_kill_process(SysFrm *)
{ {
fixme("sys_kill_process: %#lx", Frame); stub;
return SYSCALL_NOT_IMPLEMENTED; return SYSCALL_NOT_IMPLEMENTED;
} }
static int sys_kill_thread(SyscallsFrame *Frame) static int sys_kill_thread(SysFrm *)
{ {
fixme("sys_kill_thread: %#lx", Frame); stub;
return SYSCALL_NOT_IMPLEMENTED; return SYSCALL_NOT_IMPLEMENTED;
} }
static int sys_sys_reserved_create_process(SyscallsFrame *Frame) static int sys_sys_reserved_create_process(SysFrm *)
{ {
fixme("sys_sys_reserved_create_process: %#lx", Frame); stub;
return SYSCALL_NOT_IMPLEMENTED; return SYSCALL_NOT_IMPLEMENTED;
} }
static int sys_sys_reserved_create_thread(SyscallsFrame *Frame) static int sys_sys_reserved_create_thread(SysFrm *)
{ {
fixme("sys_sys_reserved_create_thread: %#lx", Frame); stub;
return SYSCALL_NOT_IMPLEMENTED; return SYSCALL_NOT_IMPLEMENTED;
} }
static void *NativeSyscallsTable[_MaxSyscall] = { struct SyscallData
[_Exit] = (void *)sys_exit, {
[_Print] = (void *)sys_print, const char *Name;
void *Handler;
[_RequestPages] = (void *)sys_request_pages, int TrustLevel;
[_FreePages] = (void *)sys_free_pages,
[_DetachAddress] = (void *)sys_detach_address,
[_MemoryMap] = (void *)sys_memory_map,
[_MemoryUnmap] = (void *)sys_memory_unmap,
[_KernelCTL] = (void *)sys_kernelctl,
[_FileOpen] = (void *)sys_file_open,
[_FileClose] = (void *)sys_file_close,
[_FileRead] = (void *)sys_file_read,
[_FileWrite] = (void *)sys_file_write,
[_FileSeek] = (void *)sys_file_seek,
[_FileStatus] = (void *)sys_file_status,
[_IPC] = (void *)sys_ipc,
[_Sleep] = (void *)sys_sleep,
[_Fork] = (void *)sys_fork,
[_Wait] = (void *)sys_wait,
[_Kill] = (void *)sys_kill,
[_Spawn] = (void *)sys_spawn,
[_SpawnThread] = (void *)sys_spawn_thread,
[_GetThreadListOfProcess] = (void *)sys_get_thread_list_of_process,
[_GetCurrentProcess] = (void *)sys_get_current_process,
[_GetCurrentThread] = (void *)sys_get_current_thread,
[_GetCurrentProcessID] = (void *)sys_get_current_process_id,
[_GetCurrentThreadID] = (void *)sys_get_current_thread_id,
[_GetProcessByPID] = (void *)sys_get_process_by_pid,
[_GetThreadByTID] = (void *)sys_get_thread_by_tid,
[_KillProcess] = (void *)sys_kill_process,
[_KillThread] = (void *)sys_kill_thread,
[_SysReservedCreateProcess] = (void *)sys_sys_reserved_create_process,
[_SysReservedCreateThread] = (void *)sys_sys_reserved_create_thread,
}; };
uintptr_t HandleNativeSyscalls(SyscallsFrame *Frame) static SyscallData NativeSyscallsTable[_MaxSyscall] = {
/**
*
* Basic syscalls
*
*/
[_Exit] = {
"Exit",
(void *)sys_exit,
TrustedByKernel | Trusted | Untrusted | UnknownTrustLevel,
},
[_Print] = {
"Print",
(void *)sys_print,
TrustedByKernel | Trusted,
},
/**
*
* Memory syscalls
*
*/
[_RequestPages] = {
"RequestPages",
(void *)sys_request_pages,
TrustedByKernel | Trusted | Untrusted,
},
[_FreePages] = {
"FreePages",
(void *)sys_free_pages,
TrustedByKernel | Trusted | Untrusted,
},
[_DetachAddress] = {
"DetachAddress",
(void *)sys_detach_address,
TrustedByKernel | Trusted,
},
[_MemoryMap] = {
"MemoryMap",
(void *)sys_memory_map,
TrustedByKernel,
},
[_MemoryUnmap] = {
"MemoryUnmap",
(void *)sys_memory_unmap,
TrustedByKernel,
},
/**
*
* Kernel Control syscalls
*
*/
[_KernelCTL] = {
"KernelCTL",
(void *)sys_kernelctl,
TrustedByKernel | Trusted | Untrusted,
},
/**
*
* File syscalls
*
*/
[_FileOpen] = {
"FileOpen",
(void *)sys_file_open,
TrustedByKernel | Trusted | Untrusted,
},
[_FileClose] = {
"FileClose",
(void *)sys_file_close,
TrustedByKernel | Trusted | Untrusted,
},
[_FileRead] = {
"FileRead",
(void *)sys_file_read,
TrustedByKernel | Trusted | Untrusted,
},
[_FileWrite] = {
"FileWrite",
(void *)sys_file_write,
TrustedByKernel | Trusted | Untrusted,
},
[_FileSeek] = {
"FileSeek",
(void *)sys_file_seek,
TrustedByKernel | Trusted | Untrusted,
},
[_FileStatus] = {
"FileStatus",
(void *)sys_file_status,
TrustedByKernel | Trusted | Untrusted,
},
/**
*
* Process syscalls
*
*/
[_IPC] = {
"IPC",
(void *)sys_ipc,
TrustedByKernel | Trusted | Untrusted,
},
[_Sleep] = {
"Sleep",
(void *)sys_sleep,
TrustedByKernel | Trusted | Untrusted,
},
[_Fork] = {
"Fork",
(void *)sys_fork,
TrustedByKernel | Trusted | Untrusted,
},
[_Wait] = {
"Wait",
(void *)sys_wait,
0,
},
[_Kill] = {
"Kill",
(void *)sys_kill,
0,
},
[_Spawn] = {
"Spawn",
(void *)sys_spawn,
0,
},
[_SpawnThread] = {
"SpawnThread",
(void *)sys_spawn_thread,
0,
},
[_GetThreadListOfProcess] = {
"GetThreadListOfProcess",
(void *)sys_get_thread_list_of_process,
0,
},
[_GetCurrentProcess] = {
"GetCurrentProcess",
(void *)sys_get_current_process,
0,
},
[_GetCurrentThread] = {
"GetCurrentThread",
(void *)sys_get_current_thread,
0,
},
[_GetCurrentProcessID] = {
"GetCurrentProcessID",
(void *)sys_get_current_process_id,
TrustedByKernel | Trusted | Untrusted,
},
[_GetCurrentThreadID] = {
"GetCurrentThreadID",
(void *)sys_get_current_thread_id,
TrustedByKernel | Trusted | Untrusted,
},
[_GetProcessByPID] = {
"GetProcessByPID",
(void *)sys_get_process_by_pid,
0,
},
[_GetThreadByTID] = {
"GetThreadByTID",
(void *)sys_get_thread_by_tid,
0,
},
[_KillProcess] = {
"KillProcess",
(void *)sys_kill_process,
0,
},
[_KillThread] = {
"KillThread",
(void *)sys_kill_thread,
0,
},
[_SysReservedCreateProcess] = {
"SysReservedCreateProcess",
(void *)sys_sys_reserved_create_process,
0,
},
[_SysReservedCreateThread] = {
"SysReservedCreateThread",
(void *)sys_sys_reserved_create_thread,
0,
},
};
uintptr_t HandleNativeSyscalls(SysFrm *Frame)
{ {
#if defined(a64) #if defined(a64)
if (Frame->rax > sizeof(NativeSyscallsTable)) if (unlikely(Frame->rax > _MaxSyscall))
{ {
fixme("Syscall %ld not implemented", Frame->rax); fixme("Syscall %ld not implemented.", Frame->rax);
return SYSCALL_NOT_IMPLEMENTED; return SYSCALL_NOT_IMPLEMENTED;
} }
uintptr_t (*call)(uintptr_t, ...) = reinterpret_cast<uintptr_t (*)(uintptr_t, ...)>(NativeSyscallsTable[Frame->rax]); SyscallData Syscall = NativeSyscallsTable[Frame->rax];
if (!call)
uintptr_t (*call)(SysFrm *, uintptr_t, ...) =
r_cst(uintptr_t(*)(SysFrm *, uintptr_t, ...),
Syscall.Handler);
if (unlikely(!call))
{ {
error("Syscall %#lx failed.", Frame->rax); error("Syscall %#lx not implemented.", Frame->rax);
return SYSCALL_INTERNAL_ERROR; return SYSCALL_NOT_IMPLEMENTED;
} }
debug("[%#lx]->( %#lx %#lx %#lx %#lx %#lx %#lx )", Token token = TaskManager->GetCurrentThread()->Security.UniqueToken;
Frame->rax, Tasking::Security *Sec = TaskManager->GetSecurityManager();
Frame->rdi, Frame->rsi, Frame->rdx, Frame->rcx, Frame->r8, Frame->r9); if (unlikely(!Sec->IsTokenTrusted(token, Syscall.TrustLevel)))
{
warn("Thread %s(%d) tried to access a system call \"%s\" with insufficient trust level",
TaskManager->GetCurrentThread()->Name,
TaskManager->GetCurrentThread()->ID,
Syscall.Name);
uintptr_t ret = call((uintptr_t)Frame, Frame->rdi, Frame->rsi, Frame->rdx, Frame->r10, Frame->r8, Frame->r9); #ifdef DEBUG
Frame->rax = ret; int TknTl = Sec->GetTokenTrustLevel(token);
return ret; debug("token=%#lx, trust=%d%d%d%d",token,
TknTl & TrustedByKernel ? 1 : 0,
TknTl & Trusted ? 1 : 0,
TknTl & Untrusted ? 1 : 0,
TknTl & UnknownTrustLevel ? 1 : 0);
#endif
return SYSCALL_ACCESS_DENIED;
}
debug("[%d:\"%s\"]->( %#lx %#lx %#lx %#lx %#lx %#lx )",
Frame->rax, Syscall.Name,
Frame->rdi, Frame->rsi, Frame->rdx,
Frame->r10, Frame->r8, Frame->r9);
return call(Frame,
Frame->rdi, Frame->rsi, Frame->rdx,
Frame->r10, Frame->r8, Frame->r9);
#elif defined(a32) #elif defined(a32)
if (Frame->eax > sizeof(NativeSyscallsTable)) return SYSCALL_NOT_IMPLEMENTED;
{
fixme("Syscall %ld not implemented", Frame->eax);
return SYSCALL_NOT_IMPLEMENTED;
}
/* ... */
return SYSCALL_INTERNAL_ERROR;
#elif defined(aa64) #elif defined(aa64)
return SYSCALL_INTERNAL_ERROR; return SYSCALL_NOT_IMPLEMENTED;
#endif #endif
} }

View File

@ -21,12 +21,8 @@
#include "../kernel.h" #include "../kernel.h"
NewLock(SyscallsLock);
extern "C" uintptr_t SystemCallsHandler(SyscallsFrame *Frame) extern "C" uintptr_t SystemCallsHandler(SyscallsFrame *Frame)
{ {
SmartLock(SyscallsLock); /* TODO: This should be replaced or moved somewhere else. */
Tasking::TaskInfo *Ptinfo = &TaskManager->GetCurrentProcess()->Info; Tasking::TaskInfo *Ptinfo = &TaskManager->GetCurrentProcess()->Info;
Tasking::TaskInfo *Ttinfo = &TaskManager->GetCurrentThread()->Info; Tasking::TaskInfo *Ttinfo = &TaskManager->GetCurrentThread()->Info;
uint64_t TempTimeCalc = TimeManager->GetCounter(); uint64_t TempTimeCalc = TimeManager->GetCounter();

View File

@ -248,17 +248,24 @@ namespace Tasking
CPU::Pause(); CPU::Pause();
} }
void Task::Sleep(uint64_t Milliseconds) void Task::Sleep(uint64_t Milliseconds, bool NoSwitch)
{ {
SmartLock(TaskingLock);
TCB *thread = this->GetCurrentThread(); TCB *thread = this->GetCurrentThread();
PCB *process = this->GetCurrentProcess();
thread->Status = TaskStatus::Sleeping; thread->Status = TaskStatus::Sleeping;
if (thread->Parent->Threads.size() == 1) if (process->Threads.size() == 1)
thread->Parent->Status = TaskStatus::Sleeping; process->Status = TaskStatus::Sleeping;
thread->Info.SleepUntil = TimeManager->CalculateTarget(Milliseconds, Time::Units::Milliseconds);
tskdbg("Thread \"%s\"(%d) is going to sleep until %llu", thread->Name, thread->ID, thread->Info.SleepUntil); thread->Info.SleepUntil =
TaskingLock.Unlock(); TimeManager->CalculateTarget(Milliseconds,
this->Schedule(); Time::Units::Milliseconds);
debug("Thread \"%s\"(%d) is going to sleep until %llu",
thread->Name, thread->ID, thread->Info.SleepUntil);
if (!NoSwitch)
this->Schedule();
} }
void Task::SignalShutdown() void Task::SignalShutdown()
@ -410,6 +417,8 @@ namespace Tasking
{ {
Thread->Security.IsCritical = true; Thread->Security.IsCritical = true;
Thread->Stack = new Memory::StackGuard(false, Parent->PageTable); Thread->Stack = new Memory::StackGuard(false, Parent->PageTable);
Thread->SyscallStack = __UINTPTR_MAX__;
Thread->TempStack = __UINTPTR_MAX__;
#if defined(a64) #if defined(a64)
SecurityManager.TrustToken(Thread->Security.UniqueToken, TTL::TrustedByKernel); SecurityManager.TrustToken(Thread->Security.UniqueToken, TTL::TrustedByKernel);
Thread->ShadowGSBase = CPU::x64::rdmsr(CPU::x64::MSRID::MSR_SHADOW_GS_BASE); Thread->ShadowGSBase = CPU::x64::rdmsr(CPU::x64::MSRID::MSR_SHADOW_GS_BASE);
@ -430,9 +439,11 @@ namespace Tasking
case TaskTrustLevel::User: case TaskTrustLevel::User:
{ {
Thread->Stack = new Memory::StackGuard(true, Parent->PageTable); Thread->Stack = new Memory::StackGuard(true, Parent->PageTable);
Thread->SyscallStack = (uintptr_t)Thread->Memory->RequestPages(TO_PAGES(STACK_SIZE)) + STACK_SIZE;
Thread->TempStack = 0x0;
#if defined(a64) #if defined(a64)
SecurityManager.TrustToken(Thread->Security.UniqueToken, TTL::Untrusted); SecurityManager.TrustToken(Thread->Security.UniqueToken, TTL::Untrusted);
Thread->ShadowGSBase = (uint64_t)GetCurrentCPU(); Thread->ShadowGSBase = (uintptr_t)Thread;
Thread->GSBase = 0; Thread->GSBase = 0;
Thread->FSBase = 0; Thread->FSBase = 0;
Thread->Registers.cs = GDT_USER_CODE; Thread->Registers.cs = GDT_USER_CODE;
@ -742,7 +753,6 @@ namespace Tasking
Task::Task(const IP EntryPoint) : Interrupts::Handler(16) /* IRQ16 */ Task::Task(const IP EntryPoint) : Interrupts::Handler(16) /* IRQ16 */
{ {
SmartLock(TaskingLock);
#if defined(a64) #if defined(a64)
// Map the IRQ16 to the first CPU. // Map the IRQ16 to the first CPU.
((APIC::APIC *)Interrupts::apic[0])->RedirectIRQ(0, CPU::x86::IRQ16 - CPU::x86::IRQ0, 1); ((APIC::APIC *)Interrupts::apic[0])->RedirectIRQ(0, CPU::x86::IRQ16 - CPU::x86::IRQ0, 1);
@ -750,7 +760,6 @@ namespace Tasking
#elif defined(aa64) #elif defined(aa64)
#endif #endif
KPrint("Starting Tasking With Instruction Pointer: %p (\e666666%s\eCCCCCC)", EntryPoint, KernelSymbolTable->GetSymbolFromAddress(EntryPoint)); KPrint("Starting Tasking With Instruction Pointer: %p (\e666666%s\eCCCCCC)", EntryPoint, KernelSymbolTable->GetSymbolFromAddress(EntryPoint));
TaskingLock.Unlock();
#if defined(a64) #if defined(a64)
TaskArchitecture Arch = TaskArchitecture::x64; TaskArchitecture Arch = TaskArchitecture::x64;
@ -765,7 +774,6 @@ namespace Tasking
TCB *kthrd = CreateThread(kproc, EntryPoint, nullptr, nullptr, std::vector<AuxiliaryVector>(), Arch); TCB *kthrd = CreateThread(kproc, EntryPoint, nullptr, nullptr, std::vector<AuxiliaryVector>(), Arch);
kthrd->Rename("Main Thread"); kthrd->Rename("Main Thread");
debug("Created Kernel Process: %s and Thread: %s", kproc->Name, kthrd->Name); debug("Created Kernel Process: %s and Thread: %s", kproc->Name, kthrd->Name);
TaskingLock.Lock(__FUNCTION__);
bool MONITORSupported = false; bool MONITORSupported = false;
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0) if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
@ -792,7 +800,6 @@ namespace Tasking
CPU::Interrupts(CPU::Enable); CPU::Interrupts(CPU::Enable);
} }
TaskingLock.Unlock();
IdleProcess = CreateProcess(nullptr, (char *)"Idle", TaskTrustLevel::Kernel); IdleProcess = CreateProcess(nullptr, (char *)"Idle", TaskTrustLevel::Kernel);
IdleProcess->ELFSymbolTable = KernelSymbolTable; IdleProcess->ELFSymbolTable = KernelSymbolTable;
for (int i = 0; i < SMP::CPUCores; i++) for (int i = 0; i < SMP::CPUCores; i++)

View File

@ -1076,6 +1076,7 @@ namespace Memory
~MemMgr(); ~MemMgr();
private: private:
NewLock(MgrLock);
Bitmap PageBitmap; Bitmap PageBitmap;
PageTable *Table; PageTable *Table;
VirtualFileSystem::Node *Directory; VirtualFileSystem::Node *Directory;

View File

@ -41,14 +41,8 @@ struct CPUArchData
struct CPUData struct CPUData
{ {
/** @brief Used by syscall handler */
uint8_t *SystemCallStack; /* gs+0x0 */
/** @brief Used by syscall handler */
uintptr_t TempStack; /* gs+0x8 */
/** @brief Used by CPU */ /** @brief Used by CPU */
uintptr_t Stack; /* gs+0x10 */ uintptr_t Stack;
/** @brief CPU ID. */ /** @brief CPU ID. */
int ID; int ID;

View File

@ -122,6 +122,12 @@ namespace Tasking
struct TCB struct TCB
{ {
/** @brief Used by syscall handler */
uintptr_t SyscallStack; /* gs+0x0 */
/** @brief Used by syscall handler */
uintptr_t TempStack; /* gs+0x8 */
TID ID; TID ID;
char Name[256]; char Name[256];
struct PCB *Parent; struct PCB *Parent;
@ -132,12 +138,12 @@ namespace Tasking
TaskStatus Status; TaskStatus Status;
#if defined(a64) #if defined(a64)
CPU::x64::TrapFrame Registers; CPU::x64::TrapFrame Registers;
uint64_t ShadowGSBase, GSBase, FSBase; uintptr_t ShadowGSBase, GSBase, FSBase;
#elif defined(a32) #elif defined(a32)
CPU::x32::TrapFrame Registers; // TODO CPU::x32::TrapFrame Registers; // TODO
uint64_t ShadowGSBase, GSBase, FSBase; uintptr_t ShadowGSBase, GSBase, FSBase;
#elif defined(aa64) #elif defined(aa64)
uint64_t Registers; // TODO uintptr_t Registers; // TODO
#endif #endif
uintptr_t IPHistory[128]; uintptr_t IPHistory[128];
TaskSecurity Security; TaskSecurity Security;
@ -244,7 +250,8 @@ namespace Tasking
Untrusted = 0b0010, Untrusted = 0b0010,
Trusted = 0b0100, Trusted = 0b0100,
TrustedByKernel = 0b1000, TrustedByKernel = 0b1000,
FullTrust = Trusted | TrustedByKernel FullTrust = Trusted | TrustedByKernel,
AllFlags = 0b1111
}; };
class Security class Security
@ -379,7 +386,7 @@ namespace Tasking
* *
* @param Milliseconds Amount of milliseconds to sleep * @param Milliseconds Amount of milliseconds to sleep
*/ */
void Sleep(uint64_t Milliseconds); void Sleep(uint64_t Milliseconds, bool NoSwitch = false);
PCB *CreateProcess(PCB *Parent, PCB *CreateProcess(PCB *Parent,
const char *Name, const char *Name,

View File

@ -76,12 +76,12 @@ namespace std
#ifdef DEBUG_MEM_ALLOCATION #ifdef DEBUG_MEM_ALLOCATION
debug("VECTOR INIT: vector( <vector> )->Size: %lld", VectorSize); debug("VECTOR INIT: vector( <vector> )->Size: %lld", VectorSize);
#endif #endif
if (VectorSize > 0) if (!v.VectorBuffer || VectorSize <= 0)
{ return;
VectorBuffer = new T[VectorSize];
for (size_t i = 0; i < VectorSize; i++) VectorBuffer = new T[VectorSize];
VectorBuffer[i] = v.VectorBuffer[i]; for (size_t i = 0; i < VectorSize; i++)
} VectorBuffer[i] = v.VectorBuffer[i];
} }
NIF ~vector() NIF ~vector()

View File

@ -8,15 +8,15 @@
modification, are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this 1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer. list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, 2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution. and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its 3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from contributors may be used to endorse or promote products derived from
this software without specific prior written permission. this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@ -49,47 +49,47 @@
enum MemoryMapFlags enum MemoryMapFlags
{ {
MAP_PRESENT = 1 << 0, MAP_PRESENT = 1 << 0,
MAP_WRITABLE = 1 << 1, MAP_WRITABLE = 1 << 1,
MAP_USER = 1 << 2, MAP_USER = 1 << 2,
}; };
enum KCtl enum KCtl
{ {
KCTL_NULL, KCTL_NULL,
KCTL_GET_PID, KCTL_GET_PID,
KCTL_GET_TID, KCTL_GET_TID,
KCTL_GET_UID, KCTL_GET_UID,
KCTL_GET_GID, KCTL_GET_GID,
/** /**
* @brief Get the page size * @brief Get the page size
*/ */
KCTL_GET_PAGE_SIZE, KCTL_GET_PAGE_SIZE,
/** /**
* @brief Check whether the current thread is critical * @brief Check whether the current thread is critical
*/ */
KCTL_IS_CRITICAL, KCTL_IS_CRITICAL,
/** /**
* @brief Register an ELF library * @brief Register an ELF library
* @fn int RegisterELFLib(char *Identifier, char *Path) * @fn int RegisterELFLib(char *Identifier, char *Path)
*/ */
KCTL_REGISTER_ELF_LIB, KCTL_REGISTER_ELF_LIB,
/** /**
* @brief Get an ELF library * @brief Get an ELF library
* @fn uintptr_t GetELFLib(char *Identifier); * @fn uintptr_t GetELFLib(char *Identifier);
*/ */
KCTL_GET_ELF_LIB_MEMORY_IMAGE, KCTL_GET_ELF_LIB_MEMORY_IMAGE,
/** /**
* @brief Get the absolute path of a library file * @brief Get the absolute path of a library file
* @fn int GetAbsolutePath(char *Identifier, char *Buffer, size_t BufferSize) * @fn int GetAbsolutePath(char *Identifier, char *Buffer, size_t BufferSize)
*/ */
KCTL_GET_ABSOLUTE_PATH, KCTL_GET_ABSOLUTE_PATH,
}; };
/** /**
@ -98,230 +98,230 @@ enum KCtl
*/ */
enum NativeSyscalls enum NativeSyscalls
{ {
/** /**
* *
* Basic syscalls * Basic syscalls
* *
*/ */
/** @brief Exit the process. /** @brief Exit the process.
* @fn int Exit(int Code) * @fn int Exit(int Code)
* This syscall is used to exit the current process with the provided exit code. * This syscall is used to exit the current process with the provided exit code.
*/ */
_Exit = 0, _Exit = 0,
/** @brief Print a message to the kernel console /** @brief Print a message to the kernel console
* @fn int Print(char Char, int Index) * @fn int Print(char Char, int Index)
* This syscall is used to print a message to the kernel console. * This syscall is used to print a message to the kernel console.
*/ */
_Print, _Print,
/** /**
* *
* Memory syscalls * Memory syscalls
* *
*/ */
/** @brief Request pages of memory /** @brief Request pages of memory
* @fn uintptr_t RequestPages(size_t Count) * @fn uintptr_t RequestPages(size_t Count)
* This syscall is used to request a specific number of pages of memory from the kernel. * This syscall is used to request a specific number of pages of memory from the kernel.
*/ */
_RequestPages, _RequestPages,
/** @brief Free pages of memory /** @brief Free pages of memory
* @fn int FreePages(uintptr_t Address, size_t Count) * @fn int FreePages(uintptr_t Address, size_t Count)
* This syscall is used to free a specific number of pages of memory that were previously requested. * This syscall is used to free a specific number of pages of memory that were previously requested.
*/ */
_FreePages, _FreePages,
/** @brief Detach memory address /** @brief Detach memory address
* @fn int DetachAddress(uintptr_t Address) * @fn int DetachAddress(uintptr_t Address)
* This syscall is used to detach a specific memory address from the current process. * This syscall is used to detach a specific memory address from the current process.
*/ */
_DetachAddress, _DetachAddress,
/** /**
* @brief Map memory address * @brief Map memory address
* @fn int MapAddress(uintptr_t VirtualAddress, uintptr_t PhysicalAddress, size_t Size, enum MemoryMapFlags Flags) * @fn int MapAddress(uintptr_t VirtualAddress, uintptr_t PhysicalAddress, size_t Size, enum MemoryMapFlags Flags)
* This syscall is used to map a specific memory address to the current process. * This syscall is used to map a specific memory address to the current process.
* *
* @param Size The size of the memory region to map. Not pages. * @param Size The size of the memory region to map. Not pages.
*/ */
_MemoryMap, _MemoryMap,
/** @brief Unmap memory address /** @brief Unmap memory address
* @fn int UnmapAddress(uintptr_t VirtualAddress, size_t Size) * @fn int UnmapAddress(uintptr_t VirtualAddress, size_t Size)
* This syscall is used to unmap a specific memory address from the current process. * This syscall is used to unmap a specific memory address from the current process.
* *
* @param Size The size of the memory region to unmap. Not pages. * @param Size The size of the memory region to unmap. Not pages.
*/ */
_MemoryUnmap, _MemoryUnmap,
/** /**
* *
* Kernel Control syscalls * Kernel Control syscalls
* *
*/ */
/** @brief Kernel Control /** @brief Kernel Control
* @fn uintptr_t KernelCTL(enum KCtl Command, uint64_t Arg1, uint64_t Arg2, uint64_t Arg3, uint64_t Arg4) * @fn uintptr_t KernelCTL(enum KCtl Command, uint64_t Arg1, uint64_t Arg2, uint64_t Arg3, uint64_t Arg4)
* This syscall is used to control certain aspects of the kernel or get information about it. * This syscall is used to control certain aspects of the kernel or get information about it.
*/ */
_KernelCTL, _KernelCTL,
/** /**
* *
* File syscalls * File syscalls
* *
*/ */
/** @brief Open a file /** @brief Open a file
* @fn void *FileOpen(const char *Path, uint64_t Flags) * @fn void *FileOpen(const char *Path, uint64_t Flags)
* This syscall is used to open a file with the provided path and flags. * This syscall is used to open a file with the provided path and flags.
*/ */
_FileOpen, _FileOpen,
/** @brief Close a file /** @brief Close a file
* @fn int FileClose(void *KernelPrivate) * @fn int FileClose(void *KernelPrivate)
* This syscall is used to close a file that was previously opened. * This syscall is used to close a file that was previously opened.
*/ */
_FileClose, _FileClose,
/** @brief Read from a file /** @brief Read from a file
* @fn uint64_t FileRead(void *KernelPrivate, uint8_t *Buffer, uint64_t Size) * @fn uint64_t FileRead(void *KernelPrivate, uint8_t *Buffer, uint64_t Size)
* This syscall is used to read a specific number of bytes from a file at a specific offset. * This syscall is used to read a specific number of bytes from a file at a specific offset.
*/ */
_FileRead, _FileRead,
/** @brief Write to a file /** @brief Write to a file
* @fn uint64_t FileWrite(void *KernelPrivate, uint8_t *Buffer, uint64_t Size) * @fn uint64_t FileWrite(void *KernelPrivate, uint8_t *Buffer, uint64_t Size)
* This syscall is used to write a specific number of bytes to a file at a specific offset. * This syscall is used to write a specific number of bytes to a file at a specific offset.
*/ */
_FileWrite, _FileWrite,
/** @brief Seek in a file /** @brief Seek in a file
* @fn off_t FileSeek(void *KernelPrivate, off_t Offset, int Whence) * @fn off_t FileSeek(void *KernelPrivate, off_t Offset, int Whence)
* This syscall is used to change the current offset in a file. * This syscall is used to change the current offset in a file.
*/ */
_FileSeek, _FileSeek,
/** @brief Get file status /** @brief Get file status
* @fn * @fn
* This syscall is used to retrieve information about a file such as its size, permissions, etc. * This syscall is used to retrieve information about a file such as its size, permissions, etc.
*/ */
_FileStatus, _FileStatus,
/** /**
* *
* Process syscalls * Process syscalls
* *
*/ */
/** /**
* @brief Creates/Reads/Writes/Deletes an IPC Pipe/Shared Memory/Message Queue/etc. * @brief Creates/Reads/Writes/Deletes an IPC Pipe/Shared Memory/Message Queue/etc.
* @fn int IPC(enum IPCCommand Command, enum IPCType Type, int ID, int Flags, void *Buffer, size_t Size) * @fn int IPC(enum IPCCommand Command, enum IPCType Type, int ID, int Flags, void *Buffer, size_t Size)
* This syscall is used to create, read, write or delete an IPC Pipe/Shared Memory/Message Queue/etc. * This syscall is used to create, read, write or delete an IPC Pipe/Shared Memory/Message Queue/etc.
*/ */
_IPC, _IPC,
/** @brief Sleep for a specific amount of time /** @brief Sleep for a specific amount of time
* @fn int Sleep(uint64_t Milliseconds) * @fn int Sleep(uint64_t Milliseconds)
* This syscall is used to sleep the current thread for a specific amount of time. * This syscall is used to sleep the current thread for a specific amount of time.
*/ */
_Sleep, _Sleep,
/** @brief Fork the current process /** @brief Fork the current process
* @fn int Fork() * @fn int Fork()
* This syscall is used to create a new process that is a copy of the current process. * This syscall is used to create a new process that is a copy of the current process.
*/ */
_Fork, _Fork,
/** @brief Wait for a process or a thread /** @brief Wait for a process or a thread
* @fn * @fn
* This syscall is used to wait for a specific process or thread to terminate. It returns the exit code of the process or thread. * This syscall is used to wait for a specific process or thread to terminate. It returns the exit code of the process or thread.
*/ */
_Wait, _Wait,
/** @brief Kill a process or a thread /** @brief Kill a process or a thread
* @fn * @fn
* This syscall is used to send a termination signal to a specific process or thread * This syscall is used to send a termination signal to a specific process or thread
*/ */
_Kill, _Kill,
/** @brief Spawn a new process /** @brief Spawn a new process
* @fn * @fn
* This syscall is used to create a new process with the provided path and arguments. * This syscall is used to create a new process with the provided path and arguments.
*/ */
_Spawn, _Spawn,
/** @brief Spawn a new thread /** @brief Spawn a new thread
* @fn int SpawnThread(uint64_t InstructionPointer) * @fn int SpawnThread(uint64_t InstructionPointer)
* This syscall is used to create a new thread within the current process with the provided function and arguments. * This syscall is used to create a new thread within the current process with the provided function and arguments.
*/ */
_SpawnThread, _SpawnThread,
/** @brief Get thread list of a process /** @brief Get thread list of a process
* @fn * @fn
* This syscall is used to retrieve a list of all the threads within a specific process. * This syscall is used to retrieve a list of all the threads within a specific process.
*/ */
_GetThreadListOfProcess, _GetThreadListOfProcess,
/** @brief Get current process /** @brief Get current process
* @fn * @fn
* This syscall is used to retrieve information about the current process. * This syscall is used to retrieve information about the current process.
*/ */
_GetCurrentProcess, _GetCurrentProcess,
/** @brief Get current thread /** @brief Get current thread
* @fn * @fn
* This syscall is used to retrieve information about the current thread. * This syscall is used to retrieve information about the current thread.
*/ */
_GetCurrentThread, _GetCurrentThread,
/** @brief Get current process ID /** @brief Get current process ID
* @fn int GetCurrentProcessID() * @fn int GetCurrentProcessID()
* This syscall is used to retrieve information about the current process. * This syscall is used to retrieve information about the current process.
*/ */
_GetCurrentProcessID, _GetCurrentProcessID,
/** @brief Get current thread ID /** @brief Get current thread ID
* @fn int GetCurrentThreadID() * @fn int GetCurrentThreadID()
* This syscall is used to retrieve information about the current thread. * This syscall is used to retrieve information about the current thread.
*/ */
_GetCurrentThreadID, _GetCurrentThreadID,
/** @brief Get process by PID /** @brief Get process by PID
* @fn * @fn
* This syscall is used to retrieve information about a specific process by its PID. * This syscall is used to retrieve information about a specific process by its PID.
*/ */
_GetProcessByPID, _GetProcessByPID,
/** @brief Get thread by TID /** @brief Get thread by TID
* @fn * @fn
* This syscall is used to retrieve information about a specific thread by its TID. * This syscall is used to retrieve information about a specific thread by its TID.
*/ */
_GetThreadByTID, _GetThreadByTID,
/** @brief Kill a process /** @brief Kill a process
* @fn * @fn
* This syscall is used to send a termination signal to a specific process. * This syscall is used to send a termination signal to a specific process.
*/ */
_KillProcess, _KillProcess,
/** @brief Kill a thread /** @brief Kill a thread
* @fn * @fn
* This syscall is used to send a termination signal to a specific thread. * This syscall is used to send a termination signal to a specific thread.
*/ */
_KillThread, _KillThread,
/** @brief Reserved syscall */ /** @brief Reserved syscall */
_SysReservedCreateProcess, _SysReservedCreateProcess,
/** @brief Reserved syscall */ /** @brief Reserved syscall */
_SysReservedCreateThread, _SysReservedCreateThread,
/** @brief Not a real syscall */ /** @brief Not a real syscall */
_MaxSyscall _MaxSyscall
}; };
/** /**
@ -330,122 +330,122 @@ enum NativeSyscalls
*/ */
enum SyscallsErrorCodes enum SyscallsErrorCodes
{ {
/** /**
* @brief Access denied * @brief Access denied
* This error code is returned when the current thread does not have the required permissions to perform the requested operation. * This error code is returned when the current thread does not have the required permissions to perform the requested operation.
*/ */
SYSCALL_ACCESS_DENIED = -0xDEADACC, SYSCALL_ACCESS_DENIED = -0xDEADACC,
/** /**
* @brief Invalid argument * @brief Invalid argument
* This error code is returned when an invalid argument is passed to a syscall. * This error code is returned when an invalid argument is passed to a syscall.
*/ */
SYSCALL_INVALID_ARGUMENT = -0xBADAEE, SYSCALL_INVALID_ARGUMENT = -0xBADAEE,
/** /**
* @brief Invalid syscall * @brief Invalid syscall
* This error code is returned when an invalid syscall number is passed to the syscall handler. * This error code is returned when an invalid syscall number is passed to the syscall handler.
*/ */
SYSCALL_INVALID_SYSCALL = -0xBAD55CA, SYSCALL_INVALID_SYSCALL = -0xBAD55CA,
/** /**
* @brief Internal error * @brief Internal error
* This error code is returned when an internal error occurs in the syscall handler. * This error code is returned when an internal error occurs in the syscall handler.
*/ */
SYSCALL_INTERNAL_ERROR = -0xBADBAD5, SYSCALL_INTERNAL_ERROR = -0xBADBAD5,
/** /**
* @brief Not implemented * @brief Not implemented
* This error code is returned when a syscall is not implemented. * This error code is returned when a syscall is not implemented.
*/ */
SYSCALL_NOT_IMPLEMENTED = -0xBAD5EED, SYSCALL_NOT_IMPLEMENTED = -0xBAD5EED,
/** /**
* @brief Generic error * @brief Generic error
* This error code is returned when a syscall fails for an unknown reason. * This error code is returned when a syscall fails for an unknown reason.
*/ */
SYSCALL_ERROR = -1, SYSCALL_ERROR = -1,
/** /**
* @brief Success * @brief Success
* This error code is returned when a syscall succeeds. * This error code is returned when a syscall succeeds.
*/ */
SYSCALL_OK = 0, SYSCALL_OK = 0,
}; };
static inline bool IsSyscallError(long ret) static inline bool IsSyscallError(long ret)
{ {
return ret < 0; return ret < 0;
} }
static inline long syscall0(long syscall) static inline long syscall0(long syscall)
{ {
long ret; long ret;
__asm__ __volatile__("syscall" __asm__ __volatile__("syscall"
: "=a"(ret) : "=a"(ret)
: "a"(syscall) : "a"(syscall)
: "rcx", "r11", "memory"); : "rcx", "r11", "memory");
return ret; return ret;
} }
static inline long syscall1(long syscall, long arg1) static inline long syscall1(long syscall, long arg1)
{ {
long ret; long ret;
__asm__ __volatile__("syscall" __asm__ __volatile__("syscall"
: "=a"(ret) : "=a"(ret)
: "a"(syscall), "D"(arg1) : "a"(syscall), "D"(arg1)
: "rcx", "r11", "memory"); : "rcx", "r11", "memory");
return ret; return ret;
} }
static inline long syscall2(long syscall, long arg1, long arg2) static inline long syscall2(long syscall, long arg1, long arg2)
{ {
long ret; long ret;
__asm__ __volatile__("syscall" __asm__ __volatile__("syscall"
: "=a"(ret) : "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2) : "a"(syscall), "D"(arg1), "S"(arg2)
: "rcx", "r11", "memory"); : "rcx", "r11", "memory");
return ret; return ret;
} }
static inline long syscall3(long syscall, long arg1, long arg2, long arg3) static inline long syscall3(long syscall, long arg1, long arg2, long arg3)
{ {
long ret; long ret;
__asm__ __volatile__("syscall" __asm__ __volatile__("syscall"
: "=a"(ret) : "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3) : "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3)
: "rcx", "r11", "memory"); : "rcx", "r11", "memory");
return ret; return ret;
} }
static inline long syscall4(long syscall, long arg1, long arg2, long arg3, long arg4) static inline long syscall4(long syscall, long arg1, long arg2, long arg3, long arg4)
{ {
long ret; long ret;
register long r10 __asm__("r10") = arg4; register long r10 __asm__("r10") = arg4;
__asm__ __volatile__("syscall" __asm__ __volatile__("syscall"
: "=a"(ret) : "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10) : "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10)
: "rcx", "r11", "memory"); : "rcx", "r11", "memory");
return ret; return ret;
} }
static inline long syscall5(long syscall, long arg1, long arg2, long arg3, long arg4, long arg5) static inline long syscall5(long syscall, long arg1, long arg2, long arg3, long arg4, long arg5)
{ {
long ret; long ret;
register long r10 __asm__("r10") = arg4; register long r10 __asm__("r10") = arg4;
register long r8 __asm__("r8") = arg5; register long r8 __asm__("r8") = arg5;
__asm__ __volatile__("syscall" __asm__ __volatile__("syscall"
: "=a"(ret) : "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8) : "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8)
: "rcx", "r11", "memory"); : "rcx", "r11", "memory");
return ret; return ret;
} }
static inline long syscall6(long syscall, long arg1, long arg2, long arg3, long arg4, long arg5, long arg6) static inline long syscall6(long syscall, long arg1, long arg2, long arg3, long arg4, long arg5, long arg6)
{ {
long ret; long ret;
register long r10 __asm__("r10") = arg4; register long r10 __asm__("r10") = arg4;
register long r8 __asm__("r8") = arg5; register long r8 __asm__("r8") = arg5;
register long r9 __asm__("r9") = arg6; register long r9 __asm__("r9") = arg6;
__asm__ __volatile__("syscall" __asm__ __volatile__("syscall"
: "=a"(ret) : "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8), "r"(r9) : "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8), "r"(r9)
: "rcx", "r11", "memory"); : "rcx", "r11", "memory");
return ret; return ret;
} }
#endif // !__FENNIX_KERNEL_SYSCALLS_LIST_H__ #endif // !__FENNIX_KERNEL_SYSCALLS_LIST_H__