/* 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 . */ #include #include #include #include #include "../../kernel.h" #include "linux_syscalls.hpp" struct SyscallData { const char *Name; void *Handler; }; using InterProcessCommunication::IPC; using InterProcessCommunication::IPCID; using Tasking::TaskStatus::Ready; using Tasking::TaskStatus::Terminated; #define ARCH_SET_GS 0x1001 #define ARCH_SET_FS 0x1002 #define ARCH_GET_FS 0x1003 #define ARCH_GET_GS 0x1004 #define ARCH_GET_CPUID 0x1011 #define ARCH_SET_CPUID 0x1012 #define ARCH_GET_XCOMP_SUPP 0x1021 #define ARCH_GET_XCOMP_PERM 0x1022 #define ARCH_REQ_XCOMP_PERM 0x1023 #define ARCH_GET_XCOMP_GUEST_PERM 0x1024 #define ARCH_REQ_XCOMP_GUEST_PERM 0x1025 #define ARCH_XCOMP_TILECFG 17 #define ARCH_XCOMP_TILEDATA 18 #define ARCH_MAP_VDSO_X32 0x2001 #define ARCH_MAP_VDSO_32 0x2002 #define ARCH_MAP_VDSO_64 0x2003 #define ARCH_GET_UNTAG_MASK 0x4001 #define ARCH_ENABLE_TAGGED_ADDR 0x4002 #define ARCH_GET_MAX_TAG_BITS 0x4003 #define ARCH_FORCE_TAGGED_SVA 0x4004 #define PROT_NONE 0 #define PROT_READ 1 #define PROT_WRITE 2 #define PROT_EXEC 4 #define PROT_GROWSDOWN 0x01000000 #define PROT_GROWSUP 0x02000000 #define MAP_TYPE 0x0f #define MAP_FILE 0 #define MAP_SHARED 0x01 #define MAP_PRIVATE 0x02 #define MAP_SHARED_VALIDATE 0x03 #define MAP_FIXED 0x10 #define MAP_ANONYMOUS 0x20 #define MAP_NORESERVE 0x4000 #define MAP_GROWSDOWN 0x0100 #define MAP_DENYWRITE 0x0800 #define MAP_EXECUTABLE 0x1000 #define MAP_LOCKED 0x2000 #define MAP_POPULATE 0x8000 #define MAP_NONBLOCK 0x10000 #define MAP_STACK 0x20000 #define MAP_HUGETLB 0x40000 #define MAP_SYNC 0x80000 #define MAP_FIXED_NOREPLACE 0x100000 typedef int pid_t; struct iovec { void *iov_base; size_t iov_len; }; #if defined(a64) || defined(aa64) static ssize_t ConvertErrno(ssize_t r) { if (r >= 0) return r; return -errno; } #endif static int ConvertErrno(int r) { if (r >= 0) return r; return -errno; } /* https://man7.org/linux/man-pages/man2/read.2.html */ static ssize_t sys_read(int fd, void *buf, size_t count) { debug("Reading %d bytes from fd %d", count, fd); Tasking::PCB *pcb = thisProcess; VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; Memory::Virtual vmm = Memory::Virtual(pcb->PageTable); if (!vmm.Check(buf, Memory::US)) { warn("Invalid address %#lx", buf); return -EFAULT; } auto pBuf = pcb->PageTable->Get(buf); ssize_t ret = ConvertErrno(fdt->_read(fd, pBuf, count)); debug("Read %d bytes from fd %d, got %d", count, fd, ret); return ret; } /* https://man7.org/linux/man-pages/man2/write.2.html */ static ssize_t sys_write(int fd, const void *buf, size_t count) { debug("Writing %d bytes to fd %d", count, fd); Tasking::PCB *pcb = thisProcess; VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; Memory::Virtual vmm = Memory::Virtual(pcb->PageTable); if (!vmm.Check((void *)buf, Memory::US)) { warn("Invalid address %#lx", buf); return -EFAULT; } auto pBuf = pcb->PageTable->Get(buf); ssize_t ret = ConvertErrno(fdt->_write(fd, pBuf, count)); debug("Wrote %d bytes to fd %d, got %d", count, fd, ret); return ret; } /* https://man7.org/linux/man-pages/man2/open.2.html */ static int sys_open(const char *pathname, int flags, mode_t mode) { Tasking::PCB *pcb = thisProcess; VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; Memory::Virtual vmm = Memory::Virtual(pcb->PageTable); if (!vmm.Check((void *)pathname, Memory::US)) { warn("Invalid address %#lx", pathname); return -EFAULT; } auto pPathname = pcb->PageTable->Get(pathname); int ret = ConvertErrno(fdt->_open(pPathname, flags, mode)); debug("Opened %s with flags %d and mode %d, got fd %d", pPathname, flags, mode, ret); return ret; } /* https://man7.org/linux/man-pages/man2/close.2.html */ static int sys_close(int fd) { Tasking::PCB *pcb = thisProcess; VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; int ret = ConvertErrno(fdt->_close(fd)); debug("Closed fd %d, got %d", fd, ret); return ret; } /* https://man7.org/linux/man-pages/man3/stat.3p.html */ static int sys_stat(const char *pathname, struct stat *statbuf) { Tasking::PCB *pcb = thisProcess; VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; Memory::Virtual vmm = Memory::Virtual(pcb->PageTable); if (!vmm.Check((void *)pathname, Memory::US)) { warn("Invalid address %#lx", pathname); return -EFAULT; } auto pPathname = pcb->PageTable->Get(pathname); return ConvertErrno(fdt->_stat(pPathname, statbuf)); } /* https://man7.org/linux/man-pages/man3/fstat.3p.html */ static int sys_fstat(int fd, struct stat *statbuf) { #undef fstat Tasking::PCB *pcb = thisProcess; VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; Memory::Virtual vmm = Memory::Virtual(pcb->PageTable); if (!vmm.Check((void *)statbuf, Memory::US)) { warn("Invalid address %#lx", statbuf); return -EFAULT; } auto pStatbuf = pcb->PageTable->Get(statbuf); return ConvertErrno(fdt->_fstat(fd, pStatbuf)); } /* https://man7.org/linux/man-pages/man2/lstat.2.html */ static int sys_lstat(const char *pathname, struct stat *statbuf) { #undef lstat Tasking::PCB *pcb = thisProcess; VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; Memory::Virtual vmm = Memory::Virtual(pcb->PageTable); if (!vmm.Check((void *)pathname, Memory::US)) { warn("Invalid address %#lx", pathname); return -EFAULT; } if (!vmm.Check((void *)statbuf, Memory::US)) { warn("Invalid address %#lx", statbuf); return -EFAULT; } auto pPathname = pcb->PageTable->Get(pathname); auto pStatbuf = pcb->PageTable->Get(statbuf); return ConvertErrno(fdt->_lstat(pPathname, pStatbuf)); } /* https://man7.org/linux/man-pages/man2/lseek.2.html */ static off_t sys_lseek(int fd, off_t offset, int whence) { Tasking::PCB *pcb = thisProcess; VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; off_t ret = ConvertErrno(fdt->_lseek(fd, offset, whence)); debug("(%d, %d, %d) = %d", fd, offset, whence, ret); return ret; } /* https://man7.org/linux/man-pages/man3/mmap.3p.html */ static void *sys_mmap(void *addr, size_t length, int prot, int flags, int fildes, off_t offset) { UNUSED(offset); /* FIXME */ Tasking::PCB *pcb = thisProcess; Memory::MemMgr *mm = pcb->Memory; void *newPages = mm->RequestPages(TO_PAGES(length)); if (newPages == nullptr) return (void *)-ENOMEM; bool MustUseAddr = (flags & MAP_FIXED) != 0; if (addr == NULL && !MustUseAddr) addr = newPages; if (MustUseAddr) { debug("Using fixed address %#lx", addr); } Memory::Virtual vmm = Memory::Virtual(pcb->PageTable); uint64_t MapFlags = Memory::P; if (prot & PROT_READ) MapFlags |= Memory::US; if (prot & PROT_WRITE) MapFlags |= Memory::RW; if (prot & PROT_EXEC) { debug("PROT_EXEC ignored"); /* MapFlags |= Memory::XD; */ } switch (flags & MAP_TYPE) { case MAP_FILE: debug("MAP_FILE ignored"); [[fallthrough]]; case MAP_SHARED: fixme("MAP_SHARED not implemented"); [[fallthrough]]; case MAP_SHARED_VALIDATE: fixme("MAP_SHARED_VALIDATE not implemented"); [[fallthrough]]; case MAP_PRIVATE: debug("MAP_PRIVATE ignored"); [[fallthrough]]; case MAP_ANONYMOUS: fixme("MAP_ANONYMOUS not implemented"); [[fallthrough]]; default: { debug("mmap flags %#x", flags); break; } } vmm.Map(addr, newPages, length, MapFlags, Memory::Virtual::FourKiB); debug("Mapped %#lx to %#lx (%d pages)", addr, newPages, TO_PAGES(length)); if (fildes != -1) { fixme("File mapping not implemented"); mm->FreePages(newPages, TO_PAGES(length)); return (void *)-ENOSYS; } return addr; } /* https://man7.org/linux/man-pages/man3/mprotect.3p.html */ static int sys_mprotect(void *addr, size_t len, int prot) { Tasking::PCB *pcb = thisProcess; Memory::Virtual vmm = Memory::Virtual(pcb->PageTable); vmm.Map(addr, addr, len, Memory::P, Memory::Virtual::FourKiB); if (prot & PROT_READ) vmm.Map(addr, addr, len, Memory::P | Memory::US, Memory::Virtual::FourKiB); if (prot & PROT_WRITE) vmm.Map(addr, addr, len, Memory::RW, Memory::Virtual::FourKiB); if (prot & PROT_EXEC) { debug("PROT_EXEC ignored"); /* MapFlags |= Memory::XD; */ } return 0; } /* https://man7.org/linux/man-pages/man3/munmap.3p.html */ static int sys_munmap(void *addr, size_t length) { Tasking::PCB *pcb = thisProcess; Memory::MemMgr *mm = pcb->Memory; Memory::Virtual vmm = Memory::Virtual(pcb->PageTable); mm->FreePages(addr, TO_PAGES(length)); vmm.Unmap(addr, length, Memory::Virtual::FourKiB); return 0; } /* https://man7.org/linux/man-pages/man2/brk.2.html */ static void *sys_brk(void *addr) { trace("Ignoring brk syscall..."); return (void *)-ENOSYS; // Tasking::PCB *pcb = thisProcess; // void *ret = pcb->ProgramBreak->brk(addr); // debug("brk(%#lx) = %#lx", addr, ret); // return ret; } /* https://man7.org/linux/man-pages/man2/ioctl.2.html */ static int sys_ioctl(int fd, unsigned long request, void *argp) { Tasking::PCB *pcb = thisProcess; VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; Memory::Virtual vmm = Memory::Virtual(pcb->PageTable); if (!vmm.Check((void *)argp, Memory::US)) { warn("Invalid address %#lx", argp); return -EFAULT; } auto pArgp = pcb->PageTable->Get(argp); return ConvertErrno(fdt->_ioctl(fd, request, pArgp)); } /* https://man7.org/linux/man-pages/man3/readv.3p.html */ static ssize_t sys_readv(int fildes, const struct iovec *iov, int iovcnt) { ssize_t Total = 0; for (int i = 0; i < iovcnt; i++) { debug("%d: iov[%d]: %p %d", fildes, i, iov[i].iov_base, iov[i].iov_len); ssize_t n = sys_read(fildes, iov[i].iov_base, iov[i].iov_len); if (n < 0) return n; debug("n: %d", n); Total += n; if (n < (ssize_t)iov[i].iov_len) { debug("break"); break; } } debug("readv: %d", Total); return Total; } /* https://man7.org/linux/man-pages/man3/writev.3p.html */ static ssize_t sys_writev(int fildes, const struct iovec *iov, int iovcnt) { ssize_t Total = 0; for (int i = 0; i < iovcnt; i++) { debug("%d: iov[%d]: %p %d", fildes, i, iov[i].iov_base, iov[i].iov_len); ssize_t n = sys_write(fildes, iov[i].iov_base, iov[i].iov_len); if (n < 0) return n; debug("n: %d", n); Total += n; if (n < (ssize_t)iov[i].iov_len) { debug("break"); break; } } debug("writev: %d", Total); return Total; } /* https://man7.org/linux/man-pages/man2/dup.2.html */ static int sys_dup(int oldfd) { Tasking::PCB *pcb = thisProcess; VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; return ConvertErrno(fdt->_dup(oldfd)); } /* https://man7.org/linux/man-pages/man2/dup.2.html */ static int sys_dup2(int oldfd, int newfd) { Tasking::PCB *pcb = thisProcess; VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; return ConvertErrno(fdt->_dup2(oldfd, newfd)); } /* https://man7.org/linux/man-pages/man3/exit.3.html */ static __noreturn void sys_exit(int status) { trace("Userspace thread %s(%d) exited with code %d (%#x)", thisThread->Name, thisThread->ID, status, status < 0 ? -status : status); thisThread->ExitCode = status; thisThread->Status = Terminated; TaskManager->Yield(); __builtin_unreachable(); } /* https://man7.org/linux/man-pages/man3/creat.3p.html */ static int sys_creat(const char *pathname, mode_t mode) { Tasking::PCB *pcb = thisProcess; VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; return ConvertErrno(fdt->_creat(pathname, mode)); } /* https://man7.org/linux/man-pages/man2/arch_prctl.2.html */ static int sys_arch_prctl(int code, unsigned long addr) { Tasking::PCB *pcb = thisProcess; Memory::Virtual vmm = Memory::Virtual(pcb->PageTable); if (!vmm.Check((void *)addr)) { warn("Invalid address %#lx", addr); return -EFAULT; } if (!vmm.Check((void *)addr, Memory::US)) { warn("Address %#lx is not user accessible", addr); return -EPERM; } switch (code) { case ARCH_SET_GS: { #if defined(a64) CPU::x64::wrmsr(CPU::x64::MSRID::MSR_GS_BASE, addr); #elif defined(a32) CPU::x32::wrmsr(CPU::x32::MSRID::MSR_GS_BASE, addr); #endif return 0; } case ARCH_SET_FS: { #if defined(a64) CPU::x64::wrmsr(CPU::x64::MSRID::MSR_FS_BASE, addr); #elif defined(a32) CPU::x32::wrmsr(CPU::x32::MSRID::MSR_FS_BASE, addr); #endif return 0; } case ARCH_GET_FS: { #if defined(a64) *r_cst(uint64_t *, addr) = CPU::x64::rdmsr(CPU::x64::MSRID::MSR_FS_BASE); #elif defined(a32) *r_cst(uint64_t *, addr) = CPU::x32::rdmsr(CPU::x32::MSRID::MSR_FS_BASE); #endif return 0; } case ARCH_GET_GS: { #if defined(a64) *r_cst(uint64_t *, addr) = CPU::x64::rdmsr(CPU::x64::MSRID::MSR_GS_BASE); #elif defined(a32) *r_cst(uint64_t *, addr) = CPU::x32::rdmsr(CPU::x32::MSRID::MSR_GS_BASE); #endif return 0; } case ARCH_GET_CPUID: case ARCH_SET_CPUID: case ARCH_GET_XCOMP_SUPP: case ARCH_GET_XCOMP_PERM: case ARCH_REQ_XCOMP_PERM: case ARCH_GET_XCOMP_GUEST_PERM: case ARCH_REQ_XCOMP_GUEST_PERM: case ARCH_XCOMP_TILECFG: case ARCH_XCOMP_TILEDATA: case ARCH_MAP_VDSO_X32: case ARCH_MAP_VDSO_32: case ARCH_MAP_VDSO_64: case ARCH_GET_UNTAG_MASK: case ARCH_ENABLE_TAGGED_ADDR: case ARCH_GET_MAX_TAG_BITS: case ARCH_FORCE_TAGGED_SVA: { fixme("Code %#lx not implemented", code); return -ENOSYS; } default: { warn("Invalid code %#lx", code); return -EINVAL; } } } /* https://man7.org/linux/man-pages/man2/set_tid_address.2.html */ static pid_t sys_set_tid_address(int *tidptr) { if (tidptr == nullptr) return -EINVAL; Tasking::TCB *tcb = thisThread; tcb->Linux.clear_child_tid = tidptr; return tcb->ID; } /* https://man7.org/linux/man-pages/man2/exit_group.2.html */ static __noreturn void sys_exit_group(int status) { fixme("status=%d", status); sys_exit(status); } static SyscallData LinuxSyscallsTable[] = { [__NR_read] = {"read", (void *)sys_read}, [__NR_write] = {"write", (void *)sys_write}, [__NR_open] = {"open", (void *)sys_open}, [__NR_close] = {"close", (void *)sys_close}, [__NR_stat] = {"stat", (void *)sys_stat}, [__NR_fstat] = {"fstat", (void *)sys_fstat}, [__NR_lstat] = {"lstat", (void *)sys_lstat}, [__NR_poll] = {"poll", (void *)nullptr}, [__NR_lseek] = {"lseek", (void *)sys_lseek}, [__NR_mmap] = {"mmap", (void *)sys_mmap}, [__NR_mprotect] = {"mprotect", (void *)sys_mprotect}, [__NR_munmap] = {"munmap", (void *)sys_munmap}, [__NR_brk] = {"brk", (void *)sys_brk}, [__NR_rt_sigaction] = {"rt_sigaction", (void *)nullptr}, [__NR_rt_sigprocmask] = {"rt_sigprocmask", (void *)nullptr}, [__NR_rt_sigreturn] = {"rt_sigreturn", (void *)nullptr}, [__NR_ioctl] = {"ioctl", (void *)sys_ioctl}, [__NR_pread64] = {"pread64", (void *)nullptr}, [__NR_pwrite64] = {"pwrite64", (void *)nullptr}, [__NR_readv] = {"readv", (void *)sys_readv}, [__NR_writev] = {"writev", (void *)sys_writev}, [__NR_access] = {"access", (void *)nullptr}, [__NR_pipe] = {"pipe", (void *)nullptr}, [__NR_select] = {"select", (void *)nullptr}, [__NR_sched_yield] = {"sched_yield", (void *)nullptr}, [__NR_mremap] = {"mremap", (void *)nullptr}, [__NR_msync] = {"msync", (void *)nullptr}, [__NR_mincore] = {"mincore", (void *)nullptr}, [__NR_madvise] = {"madvise", (void *)nullptr}, [__NR_shmget] = {"shmget", (void *)nullptr}, [__NR_shmat] = {"shmat", (void *)nullptr}, [__NR_shmctl] = {"shmctl", (void *)nullptr}, [__NR_dup] = {"dup", (void *)sys_dup}, [__NR_dup2] = {"dup2", (void *)sys_dup2}, [__NR_pause] = {"pause", (void *)nullptr}, [__NR_nanosleep] = {"nanosleep", (void *)nullptr}, [__NR_getitimer] = {"getitimer", (void *)nullptr}, [__NR_alarm] = {"alarm", (void *)nullptr}, [__NR_setitimer] = {"setitimer", (void *)nullptr}, [__NR_getpid] = {"getpid", (void *)nullptr}, [__NR_sendfile] = {"sendfile", (void *)nullptr}, [__NR_socket] = {"socket", (void *)nullptr}, [__NR_connect] = {"connect", (void *)nullptr}, [__NR_accept] = {"accept", (void *)nullptr}, [__NR_sendto] = {"sendto", (void *)nullptr}, [__NR_recvfrom] = {"recvfrom", (void *)nullptr}, [__NR_sendmsg] = {"sendmsg", (void *)nullptr}, [__NR_recvmsg] = {"recvmsg", (void *)nullptr}, [__NR_shutdown] = {"shutdown", (void *)nullptr}, [__NR_bind] = {"bind", (void *)nullptr}, [__NR_listen] = {"listen", (void *)nullptr}, [__NR_getsockname] = {"getsockname", (void *)nullptr}, [__NR_getpeername] = {"getpeername", (void *)nullptr}, [__NR_socketpair] = {"socketpair", (void *)nullptr}, [__NR_setsockopt] = {"setsockopt", (void *)nullptr}, [__NR_getsockopt] = {"getsockopt", (void *)nullptr}, [__NR_clone] = {"clone", (void *)nullptr}, [__NR_fork] = {"fork", (void *)nullptr}, [__NR_vfork] = {"vfork", (void *)nullptr}, [__NR_execve] = {"execve", (void *)nullptr}, [__NR_exit] = {"exit", (void *)sys_exit}, [__NR_wait4] = {"wait4", (void *)nullptr}, [__NR_kill] = {"kill", (void *)nullptr}, [__NR_uname] = {"uname", (void *)nullptr}, [__NR_semget] = {"semget", (void *)nullptr}, [__NR_semop] = {"semop", (void *)nullptr}, [__NR_semctl] = {"semctl", (void *)nullptr}, [__NR_shmdt] = {"shmdt", (void *)nullptr}, [__NR_msgget] = {"msgget", (void *)nullptr}, [__NR_msgsnd] = {"msgsnd", (void *)nullptr}, [__NR_msgrcv] = {"msgrcv", (void *)nullptr}, [__NR_msgctl] = {"msgctl", (void *)nullptr}, [__NR_fcntl] = {"fcntl", (void *)nullptr}, [__NR_flock] = {"flock", (void *)nullptr}, [__NR_fsync] = {"fsync", (void *)nullptr}, [__NR_fdatasync] = {"fdatasync", (void *)nullptr}, [__NR_truncate] = {"truncate", (void *)nullptr}, [__NR_ftruncate] = {"ftruncate", (void *)nullptr}, [__NR_getdents] = {"getdents", (void *)nullptr}, [__NR_getcwd] = {"getcwd", (void *)nullptr}, [__NR_chdir] = {"chdir", (void *)nullptr}, [__NR_fchdir] = {"fchdir", (void *)nullptr}, [__NR_rename] = {"rename", (void *)nullptr}, [__NR_mkdir] = {"mkdir", (void *)nullptr}, [__NR_rmdir] = {"rmdir", (void *)nullptr}, [__NR_creat] = {"creat", (void *)sys_creat}, [__NR_link] = {"link", (void *)nullptr}, [__NR_unlink] = {"unlink", (void *)nullptr}, [__NR_symlink] = {"symlink", (void *)nullptr}, [__NR_readlink] = {"readlink", (void *)nullptr}, [__NR_chmod] = {"chmod", (void *)nullptr}, [__NR_fchmod] = {"fchmod", (void *)nullptr}, [__NR_chown] = {"chown", (void *)nullptr}, [__NR_fchown] = {"fchown", (void *)nullptr}, [__NR_lchown] = {"lchown", (void *)nullptr}, [__NR_umask] = {"umask", (void *)nullptr}, [__NR_gettimeofday] = {"gettimeofday", (void *)nullptr}, [__NR_getrlimit] = {"getrlimit", (void *)nullptr}, [__NR_getrusage] = {"getrusage", (void *)nullptr}, [__NR_sysinfo] = {"sysinfo", (void *)nullptr}, [__NR_times] = {"times", (void *)nullptr}, [__NR_ptrace] = {"ptrace", (void *)nullptr}, [__NR_getuid] = {"getuid", (void *)nullptr}, [__NR_syslog] = {"syslog", (void *)nullptr}, [__NR_getgid] = {"getgid", (void *)nullptr}, [__NR_setuid] = {"setuid", (void *)nullptr}, [__NR_setgid] = {"setgid", (void *)nullptr}, [__NR_geteuid] = {"geteuid", (void *)nullptr}, [__NR_getegid] = {"getegid", (void *)nullptr}, [__NR_setpgid] = {"setpgid", (void *)nullptr}, [__NR_getppid] = {"getppid", (void *)nullptr}, [__NR_getpgrp] = {"getpgrp", (void *)nullptr}, [__NR_setsid] = {"setsid", (void *)nullptr}, [__NR_setreuid] = {"setreuid", (void *)nullptr}, [__NR_setregid] = {"setregid", (void *)nullptr}, [__NR_getgroups] = {"getgroups", (void *)nullptr}, [__NR_setgroups] = {"setgroups", (void *)nullptr}, [__NR_setresuid] = {"setresuid", (void *)nullptr}, [__NR_getresuid] = {"getresuid", (void *)nullptr}, [__NR_setresgid] = {"setresgid", (void *)nullptr}, [__NR_getresgid] = {"getresgid", (void *)nullptr}, [__NR_getpgid] = {"getpgid", (void *)nullptr}, [__NR_setfsuid] = {"setfsuid", (void *)nullptr}, [__NR_setfsgid] = {"setfsgid", (void *)nullptr}, [__NR_getsid] = {"getsid", (void *)nullptr}, [__NR_capget] = {"capget", (void *)nullptr}, [__NR_capset] = {"capset", (void *)nullptr}, [__NR_rt_sigpending] = {"rt_sigpending", (void *)nullptr}, [__NR_rt_sigtimedwait] = {"rt_sigtimedwait", (void *)nullptr}, [__NR_rt_sigqueueinfo] = {"rt_sigqueueinfo", (void *)nullptr}, [__NR_rt_sigsuspend] = {"rt_sigsuspend", (void *)nullptr}, [__NR_sigaltstack] = {"sigaltstack", (void *)nullptr}, [__NR_utime] = {"utime", (void *)nullptr}, [__NR_mknod] = {"mknod", (void *)nullptr}, [__NR_uselib] = {"uselib", (void *)nullptr}, [__NR_personality] = {"personality", (void *)nullptr}, [__NR_ustat] = {"ustat", (void *)nullptr}, [__NR_statfs] = {"statfs", (void *)nullptr}, [__NR_fstatfs] = {"fstatfs", (void *)nullptr}, [__NR_sysfs] = {"sysfs", (void *)nullptr}, [__NR_getpriority] = {"getpriority", (void *)nullptr}, [__NR_setpriority] = {"setpriority", (void *)nullptr}, [__NR_sched_setparam] = {"sched_setparam", (void *)nullptr}, [__NR_sched_getparam] = {"sched_getparam", (void *)nullptr}, [__NR_sched_setscheduler] = {"sched_setscheduler", (void *)nullptr}, [__NR_sched_getscheduler] = {"sched_getscheduler", (void *)nullptr}, [__NR_sched_get_priority_max] = {"sched_get_priority_max", (void *)nullptr}, [__NR_sched_get_priority_min] = {"sched_get_priority_min", (void *)nullptr}, [__NR_sched_rr_get_interval] = {"sched_rr_get_interval", (void *)nullptr}, [__NR_mlock] = {"mlock", (void *)nullptr}, [__NR_munlock] = {"munlock", (void *)nullptr}, [__NR_mlockall] = {"mlockall", (void *)nullptr}, [__NR_munlockall] = {"munlockall", (void *)nullptr}, [__NR_vhangup] = {"vhangup", (void *)nullptr}, [__NR_modify_ldt] = {"modify_ldt", (void *)nullptr}, [__NR_pivot_root] = {"pivot_root", (void *)nullptr}, [__NR__sysctl] = {"_sysctl", (void *)nullptr}, [__NR_prctl] = {"prctl", (void *)nullptr}, [__NR_arch_prctl] = {"arch_prctl", (void *)sys_arch_prctl}, [__NR_adjtimex] = {"adjtimex", (void *)nullptr}, [__NR_setrlimit] = {"setrlimit", (void *)nullptr}, [__NR_chroot] = {"chroot", (void *)nullptr}, [__NR_sync] = {"sync", (void *)nullptr}, [__NR_acct] = {"acct", (void *)nullptr}, [__NR_settimeofday] = {"settimeofday", (void *)nullptr}, [__NR_mount] = {"mount", (void *)nullptr}, [__NR_umount2] = {"umount2", (void *)nullptr}, [__NR_swapon] = {"swapon", (void *)nullptr}, [__NR_swapoff] = {"swapoff", (void *)nullptr}, [__NR_reboot] = {"reboot", (void *)nullptr}, [__NR_sethostname] = {"sethostname", (void *)nullptr}, [__NR_setdomainname] = {"setdomainname", (void *)nullptr}, [__NR_iopl] = {"iopl", (void *)nullptr}, [__NR_ioperm] = {"ioperm", (void *)nullptr}, [__NR_create_module] = {"create_module", (void *)nullptr}, [__NR_init_module] = {"init_module", (void *)nullptr}, [__NR_delete_module] = {"delete_module", (void *)nullptr}, [__NR_get_kernel_syms] = {"get_kernel_syms", (void *)nullptr}, [__NR_query_module] = {"query_module", (void *)nullptr}, [__NR_quotactl] = {"quotactl", (void *)nullptr}, [__NR_nfsservctl] = {"nfsservctl", (void *)nullptr}, [__NR_getpmsg] = {"getpmsg", (void *)nullptr}, [__NR_putpmsg] = {"putpmsg", (void *)nullptr}, [__NR_afs_syscall] = {"afs_syscall", (void *)nullptr}, [__NR_tuxcall] = {"tuxcall", (void *)nullptr}, [__NR_security] = {"security", (void *)nullptr}, [__NR_gettid] = {"gettid", (void *)nullptr}, [__NR_readahead] = {"readahead", (void *)nullptr}, [__NR_setxattr] = {"setxattr", (void *)nullptr}, [__NR_lsetxattr] = {"lsetxattr", (void *)nullptr}, [__NR_fsetxattr] = {"fsetxattr", (void *)nullptr}, [__NR_getxattr] = {"getxattr", (void *)nullptr}, [__NR_lgetxattr] = {"lgetxattr", (void *)nullptr}, [__NR_fgetxattr] = {"fgetxattr", (void *)nullptr}, [__NR_listxattr] = {"listxattr", (void *)nullptr}, [__NR_llistxattr] = {"llistxattr", (void *)nullptr}, [__NR_flistxattr] = {"flistxattr", (void *)nullptr}, [__NR_removexattr] = {"removexattr", (void *)nullptr}, [__NR_lremovexattr] = {"lremovexattr", (void *)nullptr}, [__NR_fremovexattr] = {"fremovexattr", (void *)nullptr}, [__NR_tkill] = {"tkill", (void *)nullptr}, [__NR_time] = {"time", (void *)nullptr}, [__NR_futex] = {"futex", (void *)nullptr}, [__NR_sched_setaffinity] = {"sched_setaffinity", (void *)nullptr}, [__NR_sched_getaffinity] = {"sched_getaffinity", (void *)nullptr}, [__NR_set_thread_area] = {"set_thread_area", (void *)nullptr}, [__NR_io_setup] = {"io_setup", (void *)nullptr}, [__NR_io_destroy] = {"io_destroy", (void *)nullptr}, [__NR_io_getevents] = {"io_getevents", (void *)nullptr}, [__NR_io_submit] = {"io_submit", (void *)nullptr}, [__NR_io_cancel] = {"io_cancel", (void *)nullptr}, [__NR_get_thread_area] = {"get_thread_area", (void *)nullptr}, [__NR_lookup_dcookie] = {"lookup_dcookie", (void *)nullptr}, [__NR_epoll_create] = {"epoll_create", (void *)nullptr}, [__NR_epoll_ctl_old] = {"epoll_ctl_old", (void *)nullptr}, [__NR_epoll_wait_old] = {"epoll_wait_old", (void *)nullptr}, [__NR_remap_file_pages] = {"remap_file_pages", (void *)nullptr}, [__NR_getdents64] = {"getdents64", (void *)nullptr}, [__NR_set_tid_address] = {"set_tid_address", (void *)sys_set_tid_address}, [__NR_restart_syscall] = {"restart_syscall", (void *)nullptr}, [__NR_semtimedop] = {"semtimedop", (void *)nullptr}, [__NR_fadvise64] = {"fadvise64", (void *)nullptr}, [__NR_timer_create] = {"timer_create", (void *)nullptr}, [__NR_timer_settime] = {"timer_settime", (void *)nullptr}, [__NR_timer_gettime] = {"timer_gettime", (void *)nullptr}, [__NR_timer_getoverrun] = {"timer_getoverrun", (void *)nullptr}, [__NR_timer_delete] = {"timer_delete", (void *)nullptr}, [__NR_clock_settime] = {"clock_settime", (void *)nullptr}, [__NR_clock_gettime] = {"clock_gettime", (void *)nullptr}, [__NR_clock_getres] = {"clock_getres", (void *)nullptr}, [__NR_clock_nanosleep] = {"clock_nanosleep", (void *)nullptr}, [__NR_exit_group] = {"exit_group", (void *)sys_exit_group}, [__NR_epoll_wait] = {"epoll_wait", (void *)nullptr}, [__NR_epoll_ctl] = {"epoll_ctl", (void *)nullptr}, [__NR_tgkill] = {"tgkill", (void *)nullptr}, [__NR_utimes] = {"utimes", (void *)nullptr}, [__NR_vserver] = {"vserver", (void *)nullptr}, [__NR_mbind] = {"mbind", (void *)nullptr}, [__NR_set_mempolicy] = {"set_mempolicy", (void *)nullptr}, [__NR_get_mempolicy] = {"get_mempolicy", (void *)nullptr}, [__NR_mq_open] = {"mq_open", (void *)nullptr}, [__NR_mq_unlink] = {"mq_unlink", (void *)nullptr}, [__NR_mq_timedsend] = {"mq_timedsend", (void *)nullptr}, [__NR_mq_timedreceive] = {"mq_timedreceive", (void *)nullptr}, [__NR_mq_notify] = {"mq_notify", (void *)nullptr}, [__NR_mq_getsetattr] = {"mq_getsetattr", (void *)nullptr}, [__NR_kexec_load] = {"kexec_load", (void *)nullptr}, [__NR_waitid] = {"waitid", (void *)nullptr}, [__NR_add_key] = {"add_key", (void *)nullptr}, [__NR_request_key] = {"request_key", (void *)nullptr}, [__NR_keyctl] = {"keyctl", (void *)nullptr}, [__NR_ioprio_set] = {"ioprio_set", (void *)nullptr}, [__NR_ioprio_get] = {"ioprio_get", (void *)nullptr}, [__NR_inotify_init] = {"inotify_init", (void *)nullptr}, [__NR_inotify_add_watch] = {"inotify_add_watch", (void *)nullptr}, [__NR_inotify_rm_watch] = {"inotify_rm_watch", (void *)nullptr}, [__NR_migrate_pages] = {"migrate_pages", (void *)nullptr}, [__NR_openat] = {"openat", (void *)nullptr}, [__NR_mkdirat] = {"mkdirat", (void *)nullptr}, [__NR_mknodat] = {"mknodat", (void *)nullptr}, [__NR_fchownat] = {"fchownat", (void *)nullptr}, [__NR_futimesat] = {"futimesat", (void *)nullptr}, [__NR_newfstatat] = {"newfstatat", (void *)nullptr}, [__NR_unlinkat] = {"unlinkat", (void *)nullptr}, [__NR_renameat] = {"renameat", (void *)nullptr}, [__NR_linkat] = {"linkat", (void *)nullptr}, [__NR_symlinkat] = {"symlinkat", (void *)nullptr}, [__NR_readlinkat] = {"readlinkat", (void *)nullptr}, [__NR_fchmodat] = {"fchmodat", (void *)nullptr}, [__NR_faccessat] = {"faccessat", (void *)nullptr}, [__NR_pselect6] = {"pselect6", (void *)nullptr}, [__NR_ppoll] = {"ppoll", (void *)nullptr}, [__NR_unshare] = {"unshare", (void *)nullptr}, [__NR_set_robust_list] = {"set_robust_list", (void *)nullptr}, [__NR_get_robust_list] = {"get_robust_list", (void *)nullptr}, [__NR_splice] = {"splice", (void *)nullptr}, [__NR_tee] = {"tee", (void *)nullptr}, [__NR_sync_file_range] = {"sync_file_range", (void *)nullptr}, [__NR_vmsplice] = {"vmsplice", (void *)nullptr}, [__NR_move_pages] = {"move_pages", (void *)nullptr}, [__NR_utimensat] = {"utimensat", (void *)nullptr}, [__NR_epoll_pwait] = {"epoll_pwait", (void *)nullptr}, [__NR_signalfd] = {"signalfd", (void *)nullptr}, [__NR_timerfd_create] = {"timerfd_create", (void *)nullptr}, [__NR_eventfd] = {"eventfd", (void *)nullptr}, [__NR_fallocate] = {"fallocate", (void *)nullptr}, [__NR_timerfd_settime] = {"timerfd_settime", (void *)nullptr}, [__NR_timerfd_gettime] = {"timerfd_gettime", (void *)nullptr}, [__NR_accept4] = {"accept4", (void *)nullptr}, [__NR_signalfd4] = {"signalfd4", (void *)nullptr}, [__NR_eventfd2] = {"eventfd2", (void *)nullptr}, [__NR_epoll_create1] = {"epoll_create1", (void *)nullptr}, [__NR_dup3] = {"dup3", (void *)nullptr}, [__NR_pipe2] = {"pipe2", (void *)nullptr}, [__NR_inotify_init1] = {"inotify_init1", (void *)nullptr}, [__NR_preadv] = {"preadv", (void *)nullptr}, [__NR_pwritev] = {"pwritev", (void *)nullptr}, [__NR_rt_tgsigqueueinfo] = {"rt_tgsigqueueinfo", (void *)nullptr}, [__NR_perf_event_open] = {"perf_event_open", (void *)nullptr}, [__NR_recvmmsg] = {"recvmmsg", (void *)nullptr}, [__NR_fanotify_init] = {"fanotify_init", (void *)nullptr}, [__NR_fanotify_mark] = {"fanotify_mark", (void *)nullptr}, [__NR_prlimit64] = {"prlimit64", (void *)nullptr}, [__NR_name_to_handle_at] = {"name_to_handle_at", (void *)nullptr}, [__NR_open_by_handle_at] = {"open_by_handle_at", (void *)nullptr}, [__NR_clock_adjtime] = {"clock_adjtime", (void *)nullptr}, [__NR_syncfs] = {"syncfs", (void *)nullptr}, [__NR_sendmmsg] = {"sendmmsg", (void *)nullptr}, [__NR_setns] = {"setns", (void *)nullptr}, [__NR_getcpu] = {"getcpu", (void *)nullptr}, [__NR_process_vm_readv] = {"process_vm_readv", (void *)nullptr}, [__NR_process_vm_writev] = {"process_vm_writev", (void *)nullptr}, [__NR_kcmp] = {"kcmp", (void *)nullptr}, [__NR_finit_module] = {"finit_module", (void *)nullptr}, [__NR_sched_setattr] = {"sched_setattr", (void *)nullptr}, [__NR_sched_getattr] = {"sched_getattr", (void *)nullptr}, [__NR_renameat2] = {"renameat2", (void *)nullptr}, [__NR_seccomp] = {"seccomp", (void *)nullptr}, [__NR_getrandom] = {"getrandom", (void *)nullptr}, [__NR_memfd_create] = {"memfd_create", (void *)nullptr}, [__NR_kexec_file_load] = {"kexec_file_load", (void *)nullptr}, [__NR_bpf] = {"bpf", (void *)nullptr}, [__NR_execveat] = {"execveat", (void *)nullptr}, [__NR_userfaultfd] = {"userfaultfd", (void *)nullptr}, [__NR_membarrier] = {"membarrier", (void *)nullptr}, [__NR_mlock2] = {"mlock2", (void *)nullptr}, [__NR_copy_file_range] = {"copy_file_range", (void *)nullptr}, [__NR_preadv2] = {"preadv2", (void *)nullptr}, [__NR_pwritev2] = {"pwritev2", (void *)nullptr}, [__NR_pkey_mprotect] = {"pkey_mprotect", (void *)nullptr}, [__NR_pkey_alloc] = {"pkey_alloc", (void *)nullptr}, [__NR_pkey_free] = {"pkey_free", (void *)nullptr}, [__NR_statx] = {"statx", (void *)nullptr}, [__NR_io_pgetevents] = {"io_pgetevents", (void *)nullptr}, [__NR_rseq] = {"rseq", (void *)nullptr}, [335] = {"reserved", (void *)nullptr}, [336] = {"reserved", (void *)nullptr}, [337] = {"reserved", (void *)nullptr}, [338] = {"reserved", (void *)nullptr}, [339] = {"reserved", (void *)nullptr}, [340] = {"reserved", (void *)nullptr}, [341] = {"reserved", (void *)nullptr}, [342] = {"reserved", (void *)nullptr}, [343] = {"reserved", (void *)nullptr}, [344] = {"reserved", (void *)nullptr}, [345] = {"reserved", (void *)nullptr}, [346] = {"reserved", (void *)nullptr}, [347] = {"reserved", (void *)nullptr}, [348] = {"reserved", (void *)nullptr}, [349] = {"reserved", (void *)nullptr}, [350] = {"reserved", (void *)nullptr}, [351] = {"reserved", (void *)nullptr}, [352] = {"reserved", (void *)nullptr}, [353] = {"reserved", (void *)nullptr}, [354] = {"reserved", (void *)nullptr}, [355] = {"reserved", (void *)nullptr}, [356] = {"reserved", (void *)nullptr}, [357] = {"reserved", (void *)nullptr}, [358] = {"reserved", (void *)nullptr}, [359] = {"reserved", (void *)nullptr}, [360] = {"reserved", (void *)nullptr}, [361] = {"reserved", (void *)nullptr}, [362] = {"reserved", (void *)nullptr}, [363] = {"reserved", (void *)nullptr}, [364] = {"reserved", (void *)nullptr}, [365] = {"reserved", (void *)nullptr}, [366] = {"reserved", (void *)nullptr}, [367] = {"reserved", (void *)nullptr}, [368] = {"reserved", (void *)nullptr}, [369] = {"reserved", (void *)nullptr}, [370] = {"reserved", (void *)nullptr}, [371] = {"reserved", (void *)nullptr}, [372] = {"reserved", (void *)nullptr}, [373] = {"reserved", (void *)nullptr}, [374] = {"reserved", (void *)nullptr}, [375] = {"reserved", (void *)nullptr}, [376] = {"reserved", (void *)nullptr}, [377] = {"reserved", (void *)nullptr}, [378] = {"reserved", (void *)nullptr}, [379] = {"reserved", (void *)nullptr}, [380] = {"reserved", (void *)nullptr}, [381] = {"reserved", (void *)nullptr}, [382] = {"reserved", (void *)nullptr}, [383] = {"reserved", (void *)nullptr}, [384] = {"reserved", (void *)nullptr}, [385] = {"reserved", (void *)nullptr}, [386] = {"reserved", (void *)nullptr}, [387] = {"reserved", (void *)nullptr}, [388] = {"reserved", (void *)nullptr}, [389] = {"reserved", (void *)nullptr}, [390] = {"reserved", (void *)nullptr}, [391] = {"reserved", (void *)nullptr}, [392] = {"reserved", (void *)nullptr}, [393] = {"reserved", (void *)nullptr}, [394] = {"reserved", (void *)nullptr}, [395] = {"reserved", (void *)nullptr}, [396] = {"reserved", (void *)nullptr}, [397] = {"reserved", (void *)nullptr}, [398] = {"reserved", (void *)nullptr}, [399] = {"reserved", (void *)nullptr}, [400] = {"reserved", (void *)nullptr}, [401] = {"reserved", (void *)nullptr}, [402] = {"reserved", (void *)nullptr}, [403] = {"reserved", (void *)nullptr}, [404] = {"reserved", (void *)nullptr}, [405] = {"reserved", (void *)nullptr}, [406] = {"reserved", (void *)nullptr}, [407] = {"reserved", (void *)nullptr}, [408] = {"reserved", (void *)nullptr}, [409] = {"reserved", (void *)nullptr}, [410] = {"reserved", (void *)nullptr}, [411] = {"reserved", (void *)nullptr}, [412] = {"reserved", (void *)nullptr}, [413] = {"reserved", (void *)nullptr}, [414] = {"reserved", (void *)nullptr}, [415] = {"reserved", (void *)nullptr}, [416] = {"reserved", (void *)nullptr}, [417] = {"reserved", (void *)nullptr}, [418] = {"reserved", (void *)nullptr}, [419] = {"reserved", (void *)nullptr}, [420] = {"reserved", (void *)nullptr}, [421] = {"reserved", (void *)nullptr}, [422] = {"reserved", (void *)nullptr}, [423] = {"reserved", (void *)nullptr}, [__NR_pidfd_send_signal] = {"pidfd_send_signal", (void *)nullptr}, [__NR_io_uring_setup] = {"io_uring_setup", (void *)nullptr}, [__NR_io_uring_enter] = {"io_uring_enter", (void *)nullptr}, [__NR_io_uring_register] = {"io_uring_register", (void *)nullptr}, [__NR_open_tree] = {"open_tree", (void *)nullptr}, [__NR_move_mount] = {"move_mount", (void *)nullptr}, [__NR_fsopen] = {"fsopen", (void *)nullptr}, [__NR_fsconfig] = {"fsconfig", (void *)nullptr}, [__NR_fsmount] = {"fsmount", (void *)nullptr}, [__NR_fspick] = {"fspick", (void *)nullptr}, [__NR_pidfd_open] = {"pidfd_open", (void *)nullptr}, [__NR_clone3] = {"clone3", (void *)nullptr}, [__NR_close_range] = {"close_range", (void *)nullptr}, [__NR_openat2] = {"openat2", (void *)nullptr}, [__NR_pidfd_getfd] = {"pidfd_getfd", (void *)nullptr}, [__NR_faccessat2] = {"faccessat2", (void *)nullptr}, [__NR_process_madvise] = {"process_madvise", (void *)nullptr}, [__NR_epoll_pwait2] = {"epoll_pwait2", (void *)nullptr}, [__NR_mount_setattr] = {"mount_setattr", (void *)nullptr}, [443] = {"reserved", (void *)nullptr}, [__NR_landlock_create_ruleset] = {"landlock_create_ruleset", (void *)nullptr}, [__NR_landlock_add_rule] = {"landlock_add_rule", (void *)nullptr}, [__NR_landlock_restrict_self] = {"landlock_restrict_self", (void *)nullptr}, }; uintptr_t HandleLinuxSyscalls(SyscallsFrame *Frame) { #if defined(a64) if (Frame->rax > sizeof(LinuxSyscallsTable) / sizeof(SyscallData)) { fixme("Syscall %d not implemented", Frame->rax); return -ENOSYS; } SyscallData Syscall = LinuxSyscallsTable[Frame->rax]; long (*call)(long, ...) = r_cst(long (*)(long, ...), Syscall.Handler); if (unlikely(!call)) { fixme("Syscall %s(%d) not implemented.", Syscall.Name, Frame->rax); return -ENOSYS; } 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->rdi, Frame->rsi, Frame->rdx, Frame->r10, Frame->r8, Frame->r9); #elif defined(a32) if (Frame->eax > sizeof(LinuxSyscallsTable) / sizeof(SyscallData)) { fixme("Syscall %d not implemented", Frame->eax); return -ENOSYS; } SyscallData Syscall = LinuxSyscallsTable[Frame->eax]; long (*call)(long, ...) = r_cst(long (*)(long, ...), Syscall.Handler); if (unlikely(!call)) { fixme("Syscall %s(%d) not implemented.", Syscall.Name, Frame->eax); return -ENOSYS; } debug("[%d:\"%s\"]->( %#lx %#lx %#lx %#lx %#lx %#lx )", Frame->eax, Syscall.Name, Frame->ebx, Frame->ecx, Frame->edx, Frame->esi, Frame->edi, Frame->ebp); return call(Frame->ebx, Frame->ecx, Frame->edx, Frame->esi, Frame->edi, Frame->ebp); #elif defined(aa64) return 0; #endif }