Fixes
This commit is contained in:
parent
2a1ee6a91b
commit
4d09fd9396
@ -9,6 +9,10 @@ target_compile_options(trampoline PRIVATE -Wall -Wextra -Werror -Wpointer-arith
|
|||||||
# Link
|
# Link
|
||||||
target_link_libraries(trampoline dl trampoline-headers)
|
target_link_libraries(trampoline dl trampoline-headers)
|
||||||
|
|
||||||
|
# RPath
|
||||||
|
set_target_properties(trampoline PROPERTIES INSTALL_RPATH "$ORIGIN/../lib/native")
|
||||||
|
target_link_options(trampoline PRIVATE "LINKER:--disable-new-dtags")
|
||||||
|
|
||||||
# Install
|
# Install
|
||||||
function(install_trampoline bin_dir)
|
function(install_trampoline bin_dir)
|
||||||
install(TARGETS trampoline DESTINATION "${bin_dir}")
|
install(TARGETS trampoline DESTINATION "${bin_dir}")
|
||||||
|
@ -3,6 +3,12 @@
|
|||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <sys/ptrace.h>
|
#include <sys/ptrace.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
#include <linux/seccomp.h>
|
||||||
|
#include <linux/filter.h>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <sys/prctl.h>
|
||||||
|
|
||||||
|
#include <trampoline/types.h>
|
||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
@ -16,8 +22,30 @@ int main(__attribute__((unused)) int argc, char *argv[]) {
|
|||||||
if (pid == -1) {
|
if (pid == -1) {
|
||||||
ERR("Unable To Fork Process: %s", strerror(errno));
|
ERR("Unable To Fork Process: %s", strerror(errno));
|
||||||
} else if (pid == 0) {
|
} else if (pid == 0) {
|
||||||
// Child
|
// 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
|
||||||
ptrace(PTRACE_TRACEME, 0, 0, 0);
|
ptrace(PTRACE_TRACEME, 0, 0, 0);
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
// Execute Program
|
||||||
execvp(argv[1], (char *const *) &argv[1]);
|
execvp(argv[1], (char *const *) &argv[1]);
|
||||||
ERR("Unable To Execute Program: %s: %s", argv[1], strerror(errno));
|
ERR("Unable To Execute Program: %s: %s", argv[1], strerror(errno));
|
||||||
} else {
|
} else {
|
||||||
@ -26,7 +54,7 @@ int main(__attribute__((unused)) int argc, char *argv[]) {
|
|||||||
// Wait For PTrace
|
// Wait For PTrace
|
||||||
waitpid(pid, nullptr, 0);
|
waitpid(pid, nullptr, 0);
|
||||||
// Configure PTrace
|
// Configure PTrace
|
||||||
ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_EXITKILL | PTRACE_O_TRACESYSGOOD);
|
ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_EXITKILL | PTRACE_O_TRACESECCOMP);
|
||||||
|
|
||||||
// Setup Trampoline
|
// Setup Trampoline
|
||||||
init_memory(pid);
|
init_memory(pid);
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
|
#include <cstring>
|
||||||
|
#include <cerrno>
|
||||||
|
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
@ -11,6 +13,9 @@ void init_memory(pid_t pid) {
|
|||||||
|
|
||||||
// Read Memory
|
// Read Memory
|
||||||
void memory_reader(uint32_t guest_addr, void *data, uint32_t size) {
|
void memory_reader(uint32_t guest_addr, void *data, uint32_t size) {
|
||||||
|
if (size == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
iovec local[1];
|
iovec local[1];
|
||||||
local[0].iov_base = data;
|
local[0].iov_base = data;
|
||||||
local[0].iov_len = size;
|
local[0].iov_len = size;
|
||||||
@ -19,7 +24,7 @@ void memory_reader(uint32_t guest_addr, void *data, uint32_t size) {
|
|||||||
remote[0].iov_len = size;
|
remote[0].iov_len = size;
|
||||||
ssize_t ret = process_vm_readv(guest_pid, local, 1, remote, 1, 0);
|
ssize_t ret = process_vm_readv(guest_pid, local, 1, remote, 1, 0);
|
||||||
if (ret != size) {
|
if (ret != size) {
|
||||||
ERR("Unable To Read Data");
|
ERR("Unable To Read Data: %s", strerror(errno));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,6 +38,6 @@ void memory_writer(uint32_t guest_addr, void *data, uint32_t size) {
|
|||||||
remote[0].iov_len = size;
|
remote[0].iov_len = size;
|
||||||
ssize_t ret = process_vm_writev(guest_pid, local, 1, remote, 1, 0);
|
ssize_t ret = process_vm_writev(guest_pid, local, 1, remote, 1, 0);
|
||||||
if (ret != size) {
|
if (ret != size) {
|
||||||
ERR("Unable To Write Data");
|
ERR("Unable To Write Data: %s", strerror(errno));
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -32,10 +32,10 @@ static void safe_wait(pid_t guest_pid, int *status) {
|
|||||||
}
|
}
|
||||||
static void ptrace_wait_syscall(pid_t guest_pid) {
|
static void ptrace_wait_syscall(pid_t guest_pid) {
|
||||||
while (true) {
|
while (true) {
|
||||||
safe_ptrace(PTRACE_SYSCALL, guest_pid, nullptr, nullptr);
|
safe_ptrace(PTRACE_CONT, guest_pid, nullptr, nullptr);
|
||||||
int status;
|
int status;
|
||||||
safe_wait(guest_pid, &status);
|
safe_wait(guest_pid, &status);
|
||||||
if (WIFSTOPPED(status) && (WSTOPSIG(status) & 0x80)) {
|
if ((status >> 8) == (SIGTRAP | (PTRACE_EVENT_SECCOMP << 8))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -52,7 +52,7 @@ static bool check_syscall(pid_t guest_pid, arm32_pt_regs *out) {
|
|||||||
.iov_base = ®s,
|
.iov_base = ®s,
|
||||||
.iov_len = sizeof(regs)
|
.iov_len = sizeof(regs)
|
||||||
};
|
};
|
||||||
safe_ptrace(PTRACE_GETREGSET, guest_pid, nullptr, ®s);
|
safe_ptrace(PTRACE_GETREGSET, guest_pid, (void *) NT_PRSTATUS, &io);
|
||||||
if (io.iov_len != sizeof(regs)) {
|
if (io.iov_len != sizeof(regs)) {
|
||||||
ERR("Guest Must Be 32-Bit");
|
ERR("Guest Must Be 32-Bit");
|
||||||
}
|
}
|
||||||
@ -61,15 +61,22 @@ static bool check_syscall(pid_t guest_pid, arm32_pt_regs *out) {
|
|||||||
// Not Trampoline
|
// Not Trampoline
|
||||||
return false;
|
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
|
// Export Registers
|
||||||
*out = regs;
|
*out = regs;
|
||||||
// Return
|
// Return
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
static void get_arguments(arm32_pt_regs *regs, uint32_t *arg1, uint32_t *arg2, uint32_t *arg3) {
|
static void get_arguments(arm32_pt_regs *regs, uint32_t *arg1, uint32_t *arg2, uint32_t *arg3) {
|
||||||
*arg1 = regs->regs[1];
|
*arg1 = regs->regs[0];
|
||||||
*arg2 = regs->regs[2];
|
*arg2 = regs->regs[1];
|
||||||
*arg3 = regs->regs[3];
|
*arg3 = regs->regs[2];
|
||||||
}
|
}
|
||||||
static void set_syscall_return(pid_t guest_pid, arm32_pt_regs *regs) {
|
static void set_syscall_return(pid_t guest_pid, arm32_pt_regs *regs) {
|
||||||
regs->regs[0] = 0;
|
regs->regs[0] = 0;
|
||||||
@ -86,7 +93,7 @@ void loop_ptrace(pid_t guest_pid) {
|
|||||||
// Wait For Syscall
|
// Wait For Syscall
|
||||||
ptrace_wait_syscall(guest_pid);
|
ptrace_wait_syscall(guest_pid);
|
||||||
|
|
||||||
// Handle Syscall Entrance
|
// Handle Syscall
|
||||||
arm32_pt_regs regs = {};
|
arm32_pt_regs regs = {};
|
||||||
bool is_trampoline = check_syscall(guest_pid, ®s);
|
bool is_trampoline = check_syscall(guest_pid, ®s);
|
||||||
if (is_trampoline) {
|
if (is_trampoline) {
|
||||||
@ -100,13 +107,7 @@ void loop_ptrace(pid_t guest_pid) {
|
|||||||
// Run Trampoline
|
// Run Trampoline
|
||||||
uint32_t ret = trampoline(id, args);
|
uint32_t ret = trampoline(id, args);
|
||||||
memory_writer(args_addr, &ret, sizeof(uint32_t));
|
memory_writer(args_addr, &ret, sizeof(uint32_t));
|
||||||
}
|
// Set Syscall Return
|
||||||
|
|
||||||
// Handle Syscall Exit
|
|
||||||
ptrace_wait_syscall(guest_pid);
|
|
||||||
|
|
||||||
// Set Syscall Return
|
|
||||||
if (is_trampoline) {
|
|
||||||
set_syscall_return(guest_pid, ®s);
|
set_syscall_return(guest_pid, ®s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user