mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-05-27 15:04:33 +00:00
795 lines
18 KiB
C++
795 lines
18 KiB
C++
/*
|
|
This file is part of Fennix Kernel.
|
|
|
|
Fennix Kernel is free software: you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation, either version 3 of
|
|
the License, or (at your option) any later version.
|
|
|
|
Fennix Kernel is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <syscalls.hpp>
|
|
|
|
#include <memory.hpp>
|
|
#include <lock.hpp>
|
|
#include <exec.hpp>
|
|
#include <errno.h>
|
|
#include <debug.h>
|
|
|
|
#include "../syscalls.h"
|
|
#include "../kernel.h"
|
|
#include "../ipc.h"
|
|
|
|
#define SysFrm SyscallsFrame
|
|
|
|
using InterProcessCommunication::IPC;
|
|
using InterProcessCommunication::IPCID;
|
|
using Tasking::Token;
|
|
using Tasking::TTL;
|
|
using Tasking::TaskStatus::Ready;
|
|
using Tasking::TaskStatus::Terminated;
|
|
using Tasking::TTL::Trusted;
|
|
using Tasking::TTL::TrustedByKernel;
|
|
using Tasking::TTL::UnknownTrustLevel;
|
|
using Tasking::TTL::Untrusted;
|
|
|
|
__noreturn static void sys_exit(SysFrm *, int code)
|
|
{
|
|
trace("Userspace thread %s(%d) exited with code %d (%#x)",
|
|
TaskManager->GetCurrentThread()->Name,
|
|
TaskManager->GetCurrentThread()->ID, code,
|
|
code < 0 ? -code : code);
|
|
|
|
TaskManager->GetCurrentThread()->ExitCode = code;
|
|
TaskManager->GetCurrentThread()->Status = Terminated;
|
|
TaskManager->Schedule();
|
|
__builtin_unreachable();
|
|
}
|
|
|
|
static int sys_print(SysFrm *, char Char, int Index)
|
|
{
|
|
char ret = Display->Print(Char, Index, true);
|
|
if (!Config.BootAnimation && Index == 0)
|
|
Display->SetBuffer(Index);
|
|
return ret;
|
|
}
|
|
|
|
static uintptr_t sys_request_pages(SysFrm *, size_t Count)
|
|
{
|
|
Memory::MemMgr *MemMgr = TaskManager->GetCurrentThread()->Memory;
|
|
return (uintptr_t)MemMgr->RequestPages(Count + 1, true);
|
|
}
|
|
|
|
static int sys_free_pages(SysFrm *, uintptr_t Address, size_t Count)
|
|
{
|
|
Memory::MemMgr *MemMgr = TaskManager->GetCurrentThread()->Memory;
|
|
MemMgr->FreePages((void *)Address, Count + 1);
|
|
return SYSCALL_OK;
|
|
}
|
|
|
|
static int sys_detach_address(SysFrm *, uintptr_t Address)
|
|
{
|
|
Memory::MemMgr *MemMgr = TaskManager->GetCurrentThread()->Memory;
|
|
MemMgr->DetachAddress((void *)Address);
|
|
return SYSCALL_OK;
|
|
}
|
|
|
|
static int sys_memory_map(SysFrm *, uintptr_t VirtualAddress,
|
|
uintptr_t PhysicalAddress, size_t Size,
|
|
enum MemoryMapFlags Flags)
|
|
{
|
|
if (Flags > 7) /* (MAP_PRESENT | MAP_WRITABLE | MAP_USER) */
|
|
return SYSCALL_INVALID_ARGUMENT;
|
|
|
|
Memory::PageTable *PageTable = TaskManager->GetCurrentProcess()->PageTable;
|
|
{
|
|
Memory::Virtual vmm = Memory::Virtual(PageTable);
|
|
vmm.Map((void *)VirtualAddress,
|
|
(void *)PhysicalAddress,
|
|
Size, Flags);
|
|
}
|
|
|
|
return SYSCALL_OK;
|
|
}
|
|
|
|
static int sys_memory_unmap(SysFrm *, uintptr_t VirtualAddress,
|
|
size_t Size)
|
|
{
|
|
Memory::PageTable *PageTable = TaskManager->GetCurrentProcess()->PageTable;
|
|
{
|
|
Memory::Virtual vmm = Memory::Virtual(PageTable);
|
|
vmm.Unmap((void *)VirtualAddress,
|
|
Size);
|
|
}
|
|
|
|
return SYSCALL_OK;
|
|
}
|
|
|
|
static uintptr_t sys_kernelctl(SysFrm *,
|
|
enum KCtl Command,
|
|
uint64_t Arg1, uint64_t Arg2,
|
|
uint64_t Arg3, uint64_t Arg4)
|
|
{
|
|
switch (Command)
|
|
{
|
|
case KCTL_GET_PID:
|
|
return TaskManager->GetCurrentProcess()->ID;
|
|
case KCTL_GET_TID:
|
|
return TaskManager->GetCurrentThread()->ID;
|
|
case KCTL_GET_PAGE_SIZE:
|
|
return PAGE_SIZE;
|
|
case KCTL_IS_CRITICAL:
|
|
return TaskManager->GetCurrentThread()->Security.IsCritical;
|
|
case KCTL_REGISTER_ELF_LIB:
|
|
{
|
|
char *Identifier = (char *)Arg1;
|
|
const char *Path = (const char *)Arg2;
|
|
|
|
if (!Identifier || !Path)
|
|
return SYSCALL_INVALID_ARGUMENT;
|
|
|
|
std::string FullPath = Path;
|
|
int retries = 0;
|
|
RetryReadPath:
|
|
debug("KCTL_REGISTER_ELF_LIB: Trying to open %s",
|
|
FullPath.c_str());
|
|
VirtualFileSystem::File f = vfs->Open(FullPath.c_str());
|
|
|
|
if (!f.IsOK())
|
|
{
|
|
FullPath.clear();
|
|
switch (retries)
|
|
{
|
|
case 0:
|
|
FullPath = "/lib/";
|
|
break;
|
|
case 1:
|
|
FullPath = "/usr/lib/";
|
|
break;
|
|
case 2:
|
|
FullPath = "/";
|
|
break;
|
|
case 3:
|
|
{
|
|
VirtualFileSystem::Node *cwd =
|
|
TaskManager->GetCurrentProcess()->CurrentWorkingDirectory;
|
|
FullPath = vfs->GetPathFromNode(cwd).get();
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
vfs->Close(f);
|
|
return SYSCALL_INVALID_ARGUMENT;
|
|
}
|
|
}
|
|
FullPath += Path;
|
|
vfs->Close(f);
|
|
retries++;
|
|
goto RetryReadPath;
|
|
}
|
|
|
|
if (Execute::AddLibrary(Identifier, f))
|
|
{
|
|
vfs->Close(f);
|
|
return SYSCALL_OK;
|
|
}
|
|
else
|
|
{
|
|
vfs->Close(f);
|
|
return SYSCALL_INTERNAL_ERROR;
|
|
}
|
|
}
|
|
case KCTL_GET_ELF_LIB_MEMORY_IMAGE:
|
|
{
|
|
char *Identifier = (char *)Arg1;
|
|
if (!Identifier)
|
|
return 0;
|
|
|
|
Execute::SharedLibrary lib = Execute::GetLibrary(Identifier);
|
|
|
|
if (!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);
|
|
return (uintptr_t)lib.MemoryImage;
|
|
}
|
|
case KCTL_GET_ABSOLUTE_PATH:
|
|
{
|
|
char *Identifier = (char *)Arg1;
|
|
void *Buffer = (void *)Arg2;
|
|
size_t BufferSize = Arg3;
|
|
|
|
if (!Identifier || !Buffer || !BufferSize)
|
|
return SYSCALL_INVALID_ARGUMENT;
|
|
|
|
Execute::SharedLibrary lib = Execute::GetLibrary(Identifier);
|
|
|
|
if (!lib.MemoryImage)
|
|
return SYSCALL_INTERNAL_ERROR;
|
|
|
|
if (BufferSize < sizeof(lib.Path))
|
|
return SYSCALL_INVALID_ARGUMENT;
|
|
|
|
memcpy(Buffer, lib.Path, sizeof(lib.Path));
|
|
return SYSCALL_OK;
|
|
}
|
|
default:
|
|
{
|
|
warn("KernelCTL: Unknown command: %lld", Command);
|
|
return SYSCALL_INVALID_ARGUMENT;
|
|
}
|
|
}
|
|
|
|
UNUSED(Arg1);
|
|
UNUSED(Arg2);
|
|
UNUSED(Arg3);
|
|
UNUSED(Arg4);
|
|
}
|
|
|
|
static uint64_t sys_file_open(SysFrm *, const char *Path, uint64_t Flags)
|
|
{
|
|
function("%s, %#lx", Path, Flags);
|
|
VirtualFileSystem::Node *cwd = nullptr;
|
|
if (vfs->PathIsRelative(Path))
|
|
cwd = TaskManager->GetCurrentProcess()->CurrentWorkingDirectory;
|
|
else
|
|
cwd = vfs->GetRootNode();
|
|
|
|
VirtualFileSystem::File KPObj = vfs->Open(Path, cwd);
|
|
if (!KPObj.IsOK())
|
|
{
|
|
debug("Failed to open file %s (%d)", Path, KPObj.Status);
|
|
vfs->Close(KPObj);
|
|
return SYSCALL_INTERNAL_ERROR;
|
|
}
|
|
|
|
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;
|
|
debug("Opened file %s (%d)", KPObj.Name, KPObj.Status);
|
|
return (uint64_t)KernelPrivate;
|
|
UNUSED(Flags);
|
|
}
|
|
|
|
static int sys_file_close(SysFrm *, void *KernelPrivate)
|
|
{
|
|
function("%#lx", KernelPrivate);
|
|
|
|
if (KernelPrivate)
|
|
{
|
|
VirtualFileSystem::File KPObj = *(VirtualFileSystem::File *)KernelPrivate;
|
|
debug("Closed file %s (%d)", KPObj.Name, KPObj.Status);
|
|
vfs->Close(KPObj);
|
|
Memory::MemMgr *MemMgr = TaskManager->GetCurrentThread()->Memory;
|
|
MemMgr->FreePages(KernelPrivate,
|
|
TO_PAGES(sizeof(VirtualFileSystem::File)));
|
|
return SYSCALL_OK;
|
|
}
|
|
return SYSCALL_INVALID_ARGUMENT;
|
|
}
|
|
|
|
static uint64_t sys_file_read(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->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);
|
|
debug("Seek %s %ld", KPObj->Name, ret);
|
|
return ret;
|
|
}
|
|
|
|
static int sys_file_status(SysFrm *)
|
|
{
|
|
stub;
|
|
return SYSCALL_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
static int sys_ipc(SysFrm *, enum IPCCommand Command,
|
|
enum IPCType Type, int ID, int Flags,
|
|
void *Buffer, size_t Size)
|
|
{
|
|
InterProcessCommunication::IPC *ipc = TaskManager->GetCurrentProcess()->IPC;
|
|
return ipc->HandleSyscall(Command, Type, ID, Flags, Buffer, Size);
|
|
}
|
|
|
|
static int sys_sleep(SysFrm *, uint64_t Milliseconds)
|
|
{
|
|
TaskManager->Sleep(Milliseconds, true);
|
|
return 0;
|
|
}
|
|
|
|
static int sys_fork(SysFrm *Frame)
|
|
{
|
|
Tasking::PCB *Parent = TaskManager->GetCurrentThread()->Parent;
|
|
Tasking::TCB *Thread = TaskManager->GetCurrentThread();
|
|
|
|
void *ProcSymTable = nullptr;
|
|
if (Parent->ELFSymbolTable)
|
|
ProcSymTable = Parent->ELFSymbolTable->GetImage();
|
|
|
|
Tasking::PCB *NewProcess =
|
|
TaskManager->CreateProcess(Parent,
|
|
Parent->Name,
|
|
Parent->Security.TrustLevel,
|
|
ProcSymTable);
|
|
|
|
if (!NewProcess)
|
|
{
|
|
error("Failed to create process for fork");
|
|
return SYSCALL_ERROR;
|
|
}
|
|
|
|
strncpy(NewProcess->Name, Parent->Name, sizeof(NewProcess->Name));
|
|
NewProcess->IPC->Fork(Parent->IPC);
|
|
|
|
Tasking::TCB *NewThread =
|
|
TaskManager->CreateThread(NewProcess,
|
|
0,
|
|
nullptr,
|
|
nullptr,
|
|
std::vector<AuxiliaryVector>(),
|
|
Thread->Info.Architecture,
|
|
Thread->Info.Compatibility,
|
|
true);
|
|
|
|
strncpy(NewThread->Name, Thread->Name, sizeof(Thread->Name));
|
|
|
|
if (!NewThread)
|
|
{
|
|
error("Failed to create thread for fork");
|
|
return SYSCALL_ERROR;
|
|
}
|
|
|
|
static int RetChild = 0;
|
|
static uint64_t ReturnAddress = 0;
|
|
static uint64_t ChildStackPointer = 0;
|
|
|
|
TaskManager->Schedule();
|
|
|
|
if (RetChild--)
|
|
{
|
|
/* We can't just return 0; because the
|
|
CPUData->SystemCallStack is no
|
|
longer valid */
|
|
asmv("movq %0, %%rcx\n"
|
|
:
|
|
: "r"(ReturnAddress));
|
|
asmv("mov %0, %%rsp\n"
|
|
:
|
|
: "r"(ChildStackPointer));
|
|
asmv("mov %0, %%rbp\n"
|
|
:
|
|
: "r"(ChildStackPointer));
|
|
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);
|
|
|
|
Tasking::Security *Sec = TaskManager->GetSecurityManager();
|
|
Sec->TrustToken(NewProcess->Security.UniqueToken,
|
|
(TTL)Sec->GetTokenTrustLevel(Parent->Security.UniqueToken));
|
|
Sec->TrustToken(NewThread->Security.UniqueToken,
|
|
(TTL)Sec->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 = Ready;
|
|
return (int)NewThread->ID;
|
|
}
|
|
|
|
static int sys_wait(SysFrm *)
|
|
{
|
|
stub;
|
|
return SYSCALL_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
static int sys_kill(SysFrm *)
|
|
{
|
|
stub;
|
|
return SYSCALL_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
static int sys_spawn(SysFrm *)
|
|
{
|
|
stub;
|
|
return SYSCALL_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
static int sys_spawn_thread(SysFrm *, uint64_t InstructionPointer)
|
|
{
|
|
Tasking::TCB *thread =
|
|
TaskManager->CreateThread(TaskManager->GetCurrentProcess(),
|
|
(Tasking::IP)InstructionPointer);
|
|
if (thread)
|
|
return (int)thread->ID;
|
|
return SYSCALL_ERROR;
|
|
}
|
|
|
|
static int sys_get_thread_list_of_process(SysFrm *)
|
|
{
|
|
stub;
|
|
return SYSCALL_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
static int sys_get_current_process(SysFrm *)
|
|
{
|
|
stub;
|
|
return SYSCALL_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
static int sys_get_current_thread(SysFrm *)
|
|
{
|
|
stub;
|
|
return SYSCALL_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
static int sys_get_current_process_id(SysFrm *)
|
|
{
|
|
return (int)TaskManager->GetCurrentProcess()->ID;
|
|
}
|
|
|
|
static int sys_get_current_thread_id(SysFrm *)
|
|
{
|
|
return (int)TaskManager->GetCurrentThread()->ID;
|
|
}
|
|
|
|
static int sys_get_process_by_pid(SysFrm *)
|
|
{
|
|
stub;
|
|
return SYSCALL_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
static int sys_get_thread_by_tid(SysFrm *)
|
|
{
|
|
stub;
|
|
return SYSCALL_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
static int sys_kill_process(SysFrm *)
|
|
{
|
|
stub;
|
|
return SYSCALL_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
static int sys_kill_thread(SysFrm *)
|
|
{
|
|
stub;
|
|
return SYSCALL_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
static int sys_sys_reserved_create_process(SysFrm *)
|
|
{
|
|
stub;
|
|
return SYSCALL_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
static int sys_sys_reserved_create_thread(SysFrm *)
|
|
{
|
|
stub;
|
|
return SYSCALL_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
struct SyscallData
|
|
{
|
|
const char *Name;
|
|
void *Handler;
|
|
int TrustLevel;
|
|
};
|
|
|
|
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 (unlikely(Frame->rax > _MaxSyscall))
|
|
{
|
|
fixme("Syscall %ld not implemented.", Frame->rax);
|
|
return SYSCALL_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
SyscallData Syscall = NativeSyscallsTable[Frame->rax];
|
|
|
|
uintptr_t (*call)(SysFrm *, uintptr_t, ...) =
|
|
r_cst(uintptr_t(*)(SysFrm *, uintptr_t, ...),
|
|
Syscall.Handler);
|
|
|
|
if (unlikely(!call))
|
|
{
|
|
error("Syscall %#lx not implemented.", Frame->rax);
|
|
return SYSCALL_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
Token token = TaskManager->GetCurrentThread()->Security.UniqueToken;
|
|
Tasking::Security *Sec = TaskManager->GetSecurityManager();
|
|
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);
|
|
|
|
#ifdef DEBUG
|
|
int TknTl = Sec->GetTokenTrustLevel(token);
|
|
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)
|
|
return SYSCALL_NOT_IMPLEMENTED;
|
|
#elif defined(aa64)
|
|
return SYSCALL_NOT_IMPLEMENTED;
|
|
#endif
|
|
}
|