2024-06-04 17:22:15 -04:00
|
|
|
#include <sys/wait.h>
|
|
|
|
#include <sys/uio.h>
|
|
|
|
#include <cstring>
|
|
|
|
#include <cerrno>
|
|
|
|
#include <elf.h>
|
|
|
|
|
|
|
|
#ifndef __aarch64__
|
|
|
|
#error "Unsupported Host Architecture"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "ptrace.h"
|
2024-06-05 21:18:48 -04:00
|
|
|
#include "../log.h"
|
|
|
|
#include "../trampoline.h"
|
|
|
|
#include "../memory.h"
|
2024-06-04 17:22:15 -04:00
|
|
|
|
|
|
|
// Helper Functions
|
2024-06-05 21:18:48 -04:00
|
|
|
void safe_ptrace(__ptrace_request request, pid_t pid, void *addr, void *data) {
|
2024-06-04 17:22:15 -04:00
|
|
|
if (ptrace(request, pid, addr, data) == -1) {
|
|
|
|
ERR("PTrace Error: %s", strerror(errno));
|
|
|
|
}
|
|
|
|
}
|
2024-06-05 21:18:48 -04:00
|
|
|
void safe_wait(pid_t guest_pid, int *status) {
|
|
|
|
int real_status;
|
|
|
|
if (waitpid(guest_pid, &real_status, 0) == -1) {
|
2024-06-04 17:22:15 -04:00
|
|
|
ERR("Unable To Wait For Guest");
|
|
|
|
}
|
2024-06-05 21:18:48 -04:00
|
|
|
if (WIFEXITED(real_status)) {
|
2024-06-04 17:22:15 -04:00
|
|
|
// Process Exited
|
2024-06-08 03:09:44 -04:00
|
|
|
free_shared_memory();
|
2024-06-05 21:18:48 -04:00
|
|
|
exit(WEXITSTATUS(real_status));
|
|
|
|
}
|
|
|
|
if (status != nullptr) {
|
|
|
|
*status = real_status;
|
2024-06-04 17:22:15 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
static void ptrace_wait_syscall(pid_t guest_pid) {
|
|
|
|
while (true) {
|
2024-06-05 00:11:54 -04:00
|
|
|
safe_ptrace(PTRACE_CONT, guest_pid, nullptr, nullptr);
|
2024-06-04 17:22:15 -04:00
|
|
|
int status;
|
|
|
|
safe_wait(guest_pid, &status);
|
2024-06-05 00:11:54 -04:00
|
|
|
if ((status >> 8) == (SIGTRAP | (PTRACE_EVENT_SECCOMP << 8))) {
|
2024-06-04 17:22:15 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Registers
|
|
|
|
struct arm32_pt_regs {
|
|
|
|
uint32_t regs[18];
|
|
|
|
};
|
|
|
|
static bool check_syscall(pid_t guest_pid, arm32_pt_regs *out) {
|
|
|
|
// Read Registers
|
|
|
|
arm32_pt_regs regs = {};
|
|
|
|
iovec io = {
|
|
|
|
.iov_base = ®s,
|
|
|
|
.iov_len = sizeof(regs)
|
|
|
|
};
|
2024-06-05 00:11:54 -04:00
|
|
|
safe_ptrace(PTRACE_GETREGSET, guest_pid, (void *) NT_PRSTATUS, &io);
|
2024-06-04 17:22:15 -04:00
|
|
|
if (io.iov_len != sizeof(regs)) {
|
|
|
|
ERR("Guest Must Be 32-Bit");
|
|
|
|
}
|
|
|
|
// Check Syscall
|
|
|
|
if (regs.regs[7] != TRAMPOLINE_SYSCALL) {
|
|
|
|
// Not Trampoline
|
|
|
|
return false;
|
|
|
|
}
|
2024-06-05 00:11:54 -04:00
|
|
|
// Block Syscall
|
|
|
|
int new_syscall = -1;
|
|
|
|
iovec syscall_io = {
|
|
|
|
.iov_base = &new_syscall,
|
|
|
|
.iov_len = sizeof(int),
|
|
|
|
};
|
|
|
|
safe_ptrace(PTRACE_SETREGSET, guest_pid, (void *) NT_ARM_SYSTEM_CALL, &syscall_io);
|
2024-06-04 17:22:15 -04:00
|
|
|
// Export Registers
|
|
|
|
*out = regs;
|
|
|
|
// Return
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
static void get_arguments(arm32_pt_regs *regs, uint32_t *arg1, uint32_t *arg2, uint32_t *arg3) {
|
2024-06-05 00:11:54 -04:00
|
|
|
*arg1 = regs->regs[0];
|
|
|
|
*arg2 = regs->regs[1];
|
|
|
|
*arg3 = regs->regs[2];
|
2024-06-04 17:22:15 -04:00
|
|
|
}
|
|
|
|
static void set_syscall_return(pid_t guest_pid, arm32_pt_regs *regs) {
|
|
|
|
regs->regs[0] = 0;
|
|
|
|
iovec io = {
|
|
|
|
.iov_base = regs,
|
|
|
|
.iov_len = sizeof(arm32_pt_regs)
|
|
|
|
};
|
|
|
|
safe_ptrace(PTRACE_SETREGSET, guest_pid, (void *) NT_PRSTATUS, &io);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Main Loop
|
|
|
|
void loop_ptrace(pid_t guest_pid) {
|
2024-06-08 03:09:44 -04:00
|
|
|
unsigned char *args = shared_memory_host_only;
|
2024-06-04 17:22:15 -04:00
|
|
|
while (true) {
|
|
|
|
// Wait For Syscall
|
|
|
|
ptrace_wait_syscall(guest_pid);
|
|
|
|
|
2024-06-05 00:11:54 -04:00
|
|
|
// Handle Syscall
|
2024-06-04 17:22:15 -04:00
|
|
|
arm32_pt_regs regs = {};
|
|
|
|
bool is_trampoline = check_syscall(guest_pid, ®s);
|
|
|
|
if (is_trampoline) {
|
|
|
|
// Get Arguments
|
|
|
|
uint32_t id;
|
|
|
|
uint32_t length;
|
|
|
|
uint32_t args_addr;
|
|
|
|
get_arguments(®s, &id, &length, &args_addr);
|
|
|
|
// Run Trampoline
|
2024-06-08 03:09:44 -04:00
|
|
|
const uint32_t ret = trampoline(id, args);
|
|
|
|
*(uint32_t *) args = ret;
|
2024-06-05 00:11:54 -04:00
|
|
|
// Set Syscall Return
|
2024-06-04 17:22:15 -04:00
|
|
|
set_syscall_return(guest_pid, ®s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|