2023-07-06 13:26:57 +02:00
|
|
|
#include "thread.hpp"
|
2023-07-06 15:55:25 +02:00
|
|
|
#include "orbis/sys/sysentry.hpp"
|
2023-07-06 13:26:57 +02:00
|
|
|
#include <asm/prctl.h>
|
2023-07-06 15:55:25 +02:00
|
|
|
#include <csignal>
|
2023-07-06 13:26:57 +02:00
|
|
|
#include <immintrin.h>
|
|
|
|
|
#include <link.h>
|
|
|
|
|
#include <linux/prctl.h>
|
2023-07-10 14:32:45 +02:00
|
|
|
#include <string>
|
2023-07-06 13:26:57 +02:00
|
|
|
#include <sys/prctl.h>
|
|
|
|
|
#include <sys/ucontext.h>
|
|
|
|
|
#include <ucontext.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
|
|
thread_local orbis::Thread *rx::thread::g_current = nullptr;
|
|
|
|
|
|
2023-07-06 15:55:25 +02:00
|
|
|
static __attribute__((no_stack_protector)) void
|
|
|
|
|
handleSigSys(int sig, siginfo_t *info, void *ucontext) {
|
|
|
|
|
if (auto hostFs = _readgsbase_u64()) {
|
|
|
|
|
_writefsbase_u64(hostFs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto prevContext = std::exchange(rx::thread::g_current->context, ucontext);
|
|
|
|
|
orbis::syscall_entry(rx::thread::g_current);
|
|
|
|
|
rx::thread::g_current->context = prevContext;
|
|
|
|
|
_writefsbase_u64(rx::thread::g_current->fsBase);
|
|
|
|
|
}
|
2023-07-06 13:26:57 +02:00
|
|
|
|
|
|
|
|
void rx::thread::initialize() {
|
2023-07-06 15:55:25 +02:00
|
|
|
struct sigaction act {};
|
|
|
|
|
act.sa_sigaction = handleSigSys;
|
|
|
|
|
act.sa_flags = SA_SIGINFO | SA_ONSTACK;
|
|
|
|
|
|
|
|
|
|
if (sigaction(SIGSYS, &act, NULL)) {
|
|
|
|
|
perror("Error sigaction:");
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
2023-07-06 13:26:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rx::thread::deinitialize() {}
|
|
|
|
|
|
|
|
|
|
void rx::thread::invoke(orbis::Thread *thread) {
|
|
|
|
|
g_current = thread;
|
|
|
|
|
|
2023-07-06 15:55:25 +02:00
|
|
|
sigset_t unblockSigs{};
|
|
|
|
|
sigset_t oldSigmask{};
|
|
|
|
|
sigaddset(&unblockSigs, SIGSYS);
|
|
|
|
|
if (pthread_sigmask(SIG_UNBLOCK, &unblockSigs, &oldSigmask)) {
|
|
|
|
|
perror("pthread_sigmask failed\n");
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-06 13:26:57 +02:00
|
|
|
std::uint64_t hostFs = _readfsbase_u64();
|
|
|
|
|
_writegsbase_u64(hostFs);
|
|
|
|
|
|
|
|
|
|
if (prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_ON,
|
2023-07-12 03:19:13 +02:00
|
|
|
(void *)0x100'0000'0000, ~0ull - 0x100'0000'0000, nullptr)) {
|
2023-07-06 13:26:57 +02:00
|
|
|
perror("prctl failed\n");
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_writefsbase_u64(thread->fsBase);
|
|
|
|
|
auto context = reinterpret_cast<ucontext_t *>(thread->context);
|
|
|
|
|
|
2023-07-06 17:31:04 +02:00
|
|
|
asm volatile("movq %1, %%rsp\n"
|
2023-07-06 13:26:57 +02:00
|
|
|
"callq *%0\n"
|
|
|
|
|
:
|
|
|
|
|
: "rm"(context->uc_mcontext.gregs[REG_RIP]),
|
|
|
|
|
"rm"(context->uc_mcontext.gregs[REG_RSP]),
|
|
|
|
|
"D"(context->uc_mcontext.gregs[REG_RDI]),
|
|
|
|
|
"S"(context->uc_mcontext.gregs[REG_RSI]),
|
|
|
|
|
"d"(context->uc_mcontext.gregs[REG_RDX]),
|
|
|
|
|
"c"(context->uc_mcontext.gregs[REG_RCX]),
|
|
|
|
|
"b"(context->uc_mcontext.gregs[REG_RBX])
|
|
|
|
|
: "memory");
|
|
|
|
|
_writefsbase_u64(hostFs);
|
|
|
|
|
}
|