Remove PTrace
This commit is contained in:
parent
50d94d5299
commit
54b79db457
@ -15,6 +15,8 @@ if(NOT TRAMPOLINE_HEADERS_ONLY)
|
||||
check_symbol_exists("__x86_64__" "" USE_QEMU_TRAMPOLINE)
|
||||
|
||||
# Include Correct Sub-Project
|
||||
set(TRAMPOLINE_RPATH "$ORIGIN/../lib/native")
|
||||
set(TRAMPOLINE_EXTRA_LINK_FLAG "--disable-new-dtags")
|
||||
if(USE_NATIVE_TRAMPOLINE)
|
||||
add_subdirectory(native)
|
||||
target_compile_definitions(trampoline-headers INTERFACE MCPI_USE_NATIVE_TRAMPOLINE)
|
||||
|
@ -2,11 +2,10 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// Switch Between Pipe/PTrace Mode
|
||||
#define TRAMPOLINE_USE_PIPES_ENV "_MCPI_TRAMPOLINE_USE_PIPES"
|
||||
// Maximum Arguments Length
|
||||
#define MAX_TRAMPOLINE_ARGS_SIZE 2097152 // 2 MiB
|
||||
|
||||
// System Call Constants
|
||||
#define MAX_TRAMPOLINE_ARGS_SIZE 2097152 // 2 MiB
|
||||
#define TRAMPOLINE_SYSCALL 0x1337
|
||||
|
||||
// Pipe Constants
|
||||
|
@ -7,7 +7,7 @@ add_executable(trampoline
|
||||
src/trampoline.cpp
|
||||
src/ptrace/loop.cpp
|
||||
src/ptrace/init.cpp
|
||||
src/pipe/pipe.cpp
|
||||
src/pipe.cpp
|
||||
src/signals.cpp
|
||||
)
|
||||
|
||||
@ -18,8 +18,8 @@ target_compile_options(trampoline PRIVATE -Wall -Wextra -Werror -Wpointer-arith
|
||||
target_link_libraries(trampoline dl rt trampoline-headers)
|
||||
|
||||
# RPath
|
||||
set_target_properties(trampoline PROPERTIES INSTALL_RPATH "$ORIGIN/../lib/native")
|
||||
target_link_options(trampoline PRIVATE "LINKER:--disable-new-dtags")
|
||||
set_target_properties(trampoline PROPERTIES INSTALL_RPATH "${TRAMPOLINE_RPATH}")
|
||||
target_link_options(trampoline PRIVATE "LINKER:${TRAMPOLINE_EXTRA_LINK_FLAG}")
|
||||
|
||||
# Install
|
||||
function(install_trampoline bin_dir)
|
||||
|
@ -6,8 +6,7 @@
|
||||
#include "log.h"
|
||||
#include "memory.h"
|
||||
#include "trampoline.h"
|
||||
#include "ptrace/ptrace.h"
|
||||
#include "pipe/pipe.h"
|
||||
#include "pipe.h"
|
||||
#include "signals.h"
|
||||
|
||||
// Main
|
||||
@ -16,11 +15,8 @@ int main(__attribute__((unused)) int argc, char *argv[]) {
|
||||
if (argc < 2) {
|
||||
ERR("Invalid Arguments");
|
||||
}
|
||||
bool use_ptrace = getenv(TRAMPOLINE_USE_PIPES_ENV) == nullptr;
|
||||
// Setup
|
||||
if (!use_ptrace) {
|
||||
init_pipe_common();
|
||||
}
|
||||
init_pipe_common();
|
||||
// Fork
|
||||
pid_t pid = fork();
|
||||
if (pid == -1) {
|
||||
@ -28,11 +24,7 @@ int main(__attribute__((unused)) int argc, char *argv[]) {
|
||||
} else if (pid == 0) {
|
||||
// Setup
|
||||
setpgid(0, 0);
|
||||
if (use_ptrace) {
|
||||
init_ptrace_guest();
|
||||
} else {
|
||||
init_pipe_guest();
|
||||
}
|
||||
init_pipe_guest();
|
||||
// Execute Program
|
||||
execvp(argv[1], (char *const *) &argv[1]);
|
||||
ERR("Unable To Execute Program: %s: %s", argv[1], strerror(errno));
|
||||
@ -44,11 +36,7 @@ int main(__attribute__((unused)) int argc, char *argv[]) {
|
||||
init_memory(pid);
|
||||
init_trampoline();
|
||||
|
||||
// Start PTrace
|
||||
if (use_ptrace) {
|
||||
init_ptrace_host(pid);
|
||||
} else {
|
||||
init_pipe_host(pid);
|
||||
}
|
||||
// Start Pipes
|
||||
init_pipe_host(pid);
|
||||
}
|
||||
}
|
@ -8,9 +8,9 @@
|
||||
|
||||
#include "pipe.h"
|
||||
|
||||
#include "../log.h"
|
||||
#include "../trampoline.h"
|
||||
#include "../memory.h"
|
||||
#include "log.h"
|
||||
#include "trampoline.h"
|
||||
#include "memory.h"
|
||||
|
||||
// Setup Pipes
|
||||
#define PIPE_READ 0
|
@ -1,46 +0,0 @@
|
||||
#include <linux/seccomp.h>
|
||||
#include <linux/filter.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <cstddef>
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
|
||||
#include <trampoline/types.h>
|
||||
|
||||
#include "ptrace.h"
|
||||
#include "../log.h"
|
||||
|
||||
// Init
|
||||
void init_ptrace_host(pid_t guest_pid) {
|
||||
// Wait For PTrace
|
||||
safe_wait(guest_pid, nullptr);
|
||||
// Configure PTrace
|
||||
safe_ptrace(PTRACE_SETOPTIONS, guest_pid, nullptr, (void *) (PTRACE_O_EXITKILL | PTRACE_O_TRACESECCOMP));
|
||||
// Start Loop
|
||||
loop_ptrace(guest_pid);
|
||||
}
|
||||
void init_ptrace_guest() {
|
||||
// seccomp Filter
|
||||
sock_filter filter[] = {
|
||||
// Load Syscall Number To Accumulator
|
||||
BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(seccomp_data, nr)),
|
||||
// If Syscall Does Not Match The Trampoline, Then Skip The Next Instruction
|
||||
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, TRAMPOLINE_SYSCALL, 0, 1),
|
||||
// Trigger PTrace And End Filter
|
||||
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_TRACE),
|
||||
// Allow Syscall And End Filter
|
||||
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW)
|
||||
};
|
||||
sock_fprog prog = {
|
||||
.len = (unsigned short) (sizeof(filter) / sizeof(filter[0])),
|
||||
.filter = filter
|
||||
};
|
||||
// Setup PTrace
|
||||
safe_ptrace(PTRACE_TRACEME, 0, nullptr, nullptr);
|
||||
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1) {
|
||||
ERR("Unable To Prepare Process For Seccomp: %s", strerror(errno));
|
||||
}
|
||||
if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) == -1) {
|
||||
ERR("Unable To Set Seccomp Filter: %s", strerror(errno));
|
||||
}
|
||||
}
|
@ -1,116 +0,0 @@
|
||||
#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"
|
||||
#include "../log.h"
|
||||
#include "../trampoline.h"
|
||||
#include "../memory.h"
|
||||
|
||||
// Helper Functions
|
||||
void safe_ptrace(__ptrace_request request, pid_t pid, void *addr, void *data) {
|
||||
if (ptrace(request, pid, addr, data) == -1) {
|
||||
ERR("PTrace Error: %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
void safe_wait(pid_t guest_pid, int *status) {
|
||||
int real_status;
|
||||
if (waitpid(guest_pid, &real_status, 0) == -1) {
|
||||
ERR("Unable To Wait For Guest");
|
||||
}
|
||||
if (WIFEXITED(real_status)) {
|
||||
// Process Exited
|
||||
exit(WEXITSTATUS(real_status));
|
||||
}
|
||||
if (status != nullptr) {
|
||||
*status = real_status;
|
||||
}
|
||||
}
|
||||
static void ptrace_wait_syscall(pid_t guest_pid) {
|
||||
while (true) {
|
||||
safe_ptrace(PTRACE_CONT, guest_pid, nullptr, nullptr);
|
||||
int status;
|
||||
safe_wait(guest_pid, &status);
|
||||
if ((status >> 8) == (SIGTRAP | (PTRACE_EVENT_SECCOMP << 8))) {
|
||||
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)
|
||||
};
|
||||
safe_ptrace(PTRACE_GETREGSET, guest_pid, (void *) NT_PRSTATUS, &io);
|
||||
if (io.iov_len != sizeof(regs)) {
|
||||
ERR("Guest Must Be 32-Bit");
|
||||
}
|
||||
// Check Syscall
|
||||
if (regs.regs[7] != TRAMPOLINE_SYSCALL) {
|
||||
// Not Trampoline
|
||||
return false;
|
||||
}
|
||||
// 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);
|
||||
// Export Registers
|
||||
*out = regs;
|
||||
// Return
|
||||
return true;
|
||||
}
|
||||
static void get_arguments(arm32_pt_regs *regs, uint32_t *arg1, uint32_t *arg2, uint32_t *arg3) {
|
||||
*arg1 = regs->regs[0];
|
||||
*arg2 = regs->regs[1];
|
||||
*arg3 = regs->regs[2];
|
||||
}
|
||||
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) {
|
||||
while (true) {
|
||||
// Wait For Syscall
|
||||
ptrace_wait_syscall(guest_pid);
|
||||
|
||||
// Handle Syscall
|
||||
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);
|
||||
unsigned char args[MAX_TRAMPOLINE_ARGS_SIZE];
|
||||
memory_reader(args_addr, args, length);
|
||||
// Run Trampoline
|
||||
const uint32_t ret = trampoline(id, args);
|
||||
memory_writer(args_addr, &ret, sizeof(uint32_t));
|
||||
// Set Syscall Return
|
||||
set_syscall_return(guest_pid, ®s);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ptrace.h>
|
||||
|
||||
void safe_ptrace(__ptrace_request request, pid_t pid, void *addr, void *data);
|
||||
void safe_wait(pid_t guest_pid, int *status);
|
||||
void init_ptrace_host(pid_t guest_pid);
|
||||
void init_ptrace_guest();
|
||||
void loop_ptrace(pid_t guest_pid);
|
@ -2,10 +2,6 @@
|
||||
|
||||
#include "signals.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <cerrno>
|
||||
|
||||
// Signal Handlers
|
||||
static pid_t guest_pid = -1;
|
||||
static void exit_handler(__attribute__((unused)) int signal_id) {
|
||||
|
@ -36,7 +36,7 @@ ExternalProject_Add(qemu
|
||||
"--cross-prefix="
|
||||
"--cc=${CMAKE_C_COMPILER}"
|
||||
"--cxx=${CMAKE_CXX_COMPILER}"
|
||||
"--extra-ldflags=-ldl -Wl,-rpath=$ORIGIN/../lib/native -Wl,--disable-new-dtags"
|
||||
"--extra-ldflags=-ldl -Wl,-rpath=${TRAMPOLINE_RPATH} -Wl,${TRAMPOLINE_EXTRA_LINK_FLAG}"
|
||||
"--disable-debug-info"
|
||||
"--target-list=arm-linux-user"
|
||||
"--without-default-features"
|
||||
|
Loading…
Reference in New Issue
Block a user