This commit is contained in:
TheBrokenRail 2024-06-08 03:09:44 -04:00
parent b2cf446e9d
commit 027e58ee9b
7 changed files with 66 additions and 44 deletions

View File

@ -2,25 +2,19 @@
#include <stdint.h> #include <stdint.h>
// Switch Between Pipe?PTrace Mode // Shared Memory
#ifdef MCPI_USE_NATIVE_TRAMPOLINE #define TRAMPOLINE_SHARED_MEMORY_ENV "_MCPI_TRAMPOLINE_SHARED_MEMORY"
#define TRAMPOLINE_USE_PTRACE_ENV "_MCPI_TRAMPOLINE_USE_PTRACE"
#endif // Switch Between Pipe/PTrace Mode
#define TRAMPOLINE_USE_PIPES_ENV "_MCPI_TRAMPOLINE_USE_PIPES"
// System Call Constants // System Call Constants
#define MAX_TRAMPOLINE_ARGS_SIZE 2097152 // 2 MiB #define MAX_TRAMPOLINE_ARGS_SIZE 2097152 // 2 MiB
#define TRAMPOLINE_SYSCALL 0x1337 #define TRAMPOLINE_SYSCALL 0x1337
// Pipe Constants // Pipe Constants
#ifdef MCPI_USE_NATIVE_TRAMPOLINE
#define TRAMPOLINE_ARGUMENTS_PIPE_ENV "_MCPI_TRAMPOLINE_ARGUMENTS" #define TRAMPOLINE_ARGUMENTS_PIPE_ENV "_MCPI_TRAMPOLINE_ARGUMENTS"
#define TRAMPOLINE_RETURN_VALUE_PIPE_ENV "_MCPI_TRAMPOLINE_RETURN_VALUE" #define TRAMPOLINE_RETURN_VALUE_PIPE_ENV "_MCPI_TRAMPOLINE_RETURN_VALUE"
struct trampoline_pipe_arguments {
uint32_t id;
uint32_t length;
uint32_t args_addr;
};
#endif
// Function Types // Function Types
typedef void (*trampoline_writer_t)(uint32_t guest_addr, void *data, uint32_t size); typedef void (*trampoline_writer_t)(uint32_t guest_addr, void *data, uint32_t size);

View File

@ -15,7 +15,7 @@ add_executable(trampoline
target_compile_options(trampoline PRIVATE -Wall -Wextra -Werror -Wpointer-arith -Wshadow -Wnull-dereference) target_compile_options(trampoline PRIVATE -Wall -Wextra -Werror -Wpointer-arith -Wshadow -Wnull-dereference)
# Link # Link
target_link_libraries(trampoline dl trampoline-headers) target_link_libraries(trampoline dl rt trampoline-headers)
# RPath # RPath
set_target_properties(trampoline PROPERTIES INSTALL_RPATH "$ORIGIN/../lib/native") set_target_properties(trampoline PROPERTIES INSTALL_RPATH "$ORIGIN/../lib/native")

View File

@ -16,8 +16,9 @@ int main(__attribute__((unused)) int argc, char *argv[]) {
if (argc < 2) { if (argc < 2) {
ERR("Invalid Arguments"); ERR("Invalid Arguments");
} }
bool use_ptrace = getenv(TRAMPOLINE_USE_PTRACE_ENV) != nullptr; bool use_ptrace = getenv(TRAMPOLINE_USE_PIPES_ENV) == nullptr;
// Setup // Setup
init_shared_memory_common();
if (!use_ptrace) { if (!use_ptrace) {
init_pipe_common(); init_pipe_common();
} }
@ -28,6 +29,7 @@ int main(__attribute__((unused)) int argc, char *argv[]) {
} else if (pid == 0) { } else if (pid == 0) {
// Setup // Setup
setpgid(0, 0); setpgid(0, 0);
init_shared_memory_guest();
if (use_ptrace) { if (use_ptrace) {
init_ptrace_guest(); init_ptrace_guest();
} else { } else {
@ -40,6 +42,7 @@ int main(__attribute__((unused)) int argc, char *argv[]) {
// Parent // Parent
// Setup Trampoline // Setup Trampoline
init_shared_memory_host();
init_signals(pid); init_signals(pid);
init_memory(pid); init_memory(pid);
init_trampoline(); init_trampoline();

View File

@ -1,18 +1,22 @@
#include <sys/uio.h> #include <sys/uio.h>
#include <cstring> #include <cstring>
#include <cerrno> #include <cerrno>
#include <sys/mman.h>
#include <fcntl.h>
#include <string>
#include <unistd.h>
#include <trampoline/types.h>
#include "memory.h" #include "memory.h"
#include "log.h" #include "log.h"
// Store PID // Read Memory
static pid_t guest_pid; static pid_t guest_pid;
void init_memory(pid_t pid) { void init_memory(pid_t pid) {
guest_pid = pid; guest_pid = pid;
} }
void memory_writer(uint32_t guest_addr, void *data, uint32_t size) {
// Read Memory
void memory_reader(uint32_t guest_addr, void *data, uint32_t size) {
if (size == 0) { if (size == 0) {
return; return;
} }
@ -22,22 +26,36 @@ void memory_reader(uint32_t guest_addr, void *data, uint32_t size) {
iovec remote[1]; iovec remote[1];
remote[0].iov_base = (void *) (uint64_t) guest_addr; remote[0].iov_base = (void *) (uint64_t) guest_addr;
remote[0].iov_len = size; remote[0].iov_len = size;
ssize_t ret = process_vm_readv(guest_pid, local, 1, remote, 1, 0); const ssize_t ret = process_vm_writev(guest_pid, local, 1, remote, 1, 0);
if (ret != size) {
ERR("Unable To Read Data: %s", strerror(errno));
}
}
// Write Memory
void memory_writer(uint32_t guest_addr, void *data, uint32_t size) {
iovec local[1];
local[0].iov_base = data;
local[0].iov_len = size;
iovec remote[1];
remote[0].iov_base = (void *) (uint64_t) guest_addr;
remote[0].iov_len = size;
ssize_t ret = process_vm_writev(guest_pid, local, 1, remote, 1, 0);
if (ret != size) { if (ret != size) {
ERR("Unable To Write Data: %s", strerror(errno)); ERR("Unable To Write Data: %s", strerror(errno));
} }
} }
// Shared Memory
static std::string shared_memory_name;
static int shared_memory_fd;
void init_shared_memory_common() {
shared_memory_name = std::string("/mcpi-trampoline-") + std::to_string(getpid());
shared_memory_fd = shm_open(shared_memory_name.c_str(), O_CREAT | O_EXCL | O_RDWR, 0600);
if (shared_memory_fd == -1) {
ERR("Unable To Create Shared Memory: %s", strerror(errno));
}
if (ftruncate(shared_memory_fd, MAX_TRAMPOLINE_ARGS_SIZE) == -1) {
ERR("Unable To Set Shared Memory Size: %s", strerror(errno));
}
}
void init_shared_memory_guest() {
setenv(TRAMPOLINE_SHARED_MEMORY_ENV, shared_memory_name.c_str(), true);
}
unsigned char *shared_memory_host_only;
void init_shared_memory_host() {
shared_memory_host_only = (unsigned char *) mmap(nullptr, MAX_TRAMPOLINE_ARGS_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shared_memory_fd, 0);
if (shared_memory_host_only == MAP_FAILED) {
ERR("Unable To Map Shared Memory: %s", strerror(errno));
}
}
void free_shared_memory() {
munmap(shared_memory_host_only, MAX_TRAMPOLINE_ARGS_SIZE);
shm_unlink(shared_memory_name.c_str());
}

View File

@ -3,6 +3,13 @@
#include <cstdint> #include <cstdint>
#include <sys/types.h> #include <sys/types.h>
void memory_reader(uint32_t guest_addr, void *data, uint32_t size); // Read External Memory
void memory_writer(uint32_t guest_addr, void *data, uint32_t size); void memory_writer(uint32_t guest_addr, void *data, uint32_t size);
void init_memory(pid_t guest_pid); void init_memory(pid_t guest_pid);
// Shared Memory
void init_shared_memory_common();
void init_shared_memory_guest();
void init_shared_memory_host();
extern unsigned char *shared_memory_host_only;
void free_shared_memory();

View File

@ -44,11 +44,9 @@ void init_pipe_host(pid_t guest_pid) {
close(arguments_pipe[PIPE_WRITE]); close(arguments_pipe[PIPE_WRITE]);
close(return_value_pipe[PIPE_READ]); close(return_value_pipe[PIPE_READ]);
// Wait For Commands // Wait For Commands
trampoline_pipe_arguments cmd = {}; uint32_t cmd;
while (read(arguments_pipe[PIPE_READ], &cmd, sizeof(trampoline_pipe_arguments)) > 0) { while (read(arguments_pipe[PIPE_READ], &cmd, sizeof(uint32_t)) > 0) {
static unsigned char args[MAX_TRAMPOLINE_ARGS_SIZE]; uint32_t ret = trampoline(cmd, shared_memory_host_only);
memory_reader(cmd.args_addr, args, cmd.length);
uint32_t ret = trampoline(cmd.id, args);
write(return_value_pipe[PIPE_WRITE], &ret, sizeof(uint32_t)); write(return_value_pipe[PIPE_WRITE], &ret, sizeof(uint32_t));
} }
// Reap Child // Reap Child
@ -56,6 +54,9 @@ void init_pipe_host(pid_t guest_pid) {
if (waitpid(guest_pid, &status, 0) == -1) { if (waitpid(guest_pid, &status, 0) == -1) {
ERR("Unable To Reap Child: %s", strerror(errno)); ERR("Unable To Reap Child: %s", strerror(errno));
} }
// Close Shared Memory
free_shared_memory();
// Exit
if (WIFEXITED(status)) { if (WIFEXITED(status)) {
exit(WEXITSTATUS(status)); exit(WEXITSTATUS(status));
} else { } else {

View File

@ -7,7 +7,6 @@
#ifndef __aarch64__ #ifndef __aarch64__
#error "Unsupported Host Architecture" #error "Unsupported Host Architecture"
#endif #endif
#include <asm/ptrace.h>
#include "ptrace.h" #include "ptrace.h"
#include "../log.h" #include "../log.h"
@ -27,6 +26,7 @@ void safe_wait(pid_t guest_pid, int *status) {
} }
if (WIFEXITED(real_status)) { if (WIFEXITED(real_status)) {
// Process Exited // Process Exited
free_shared_memory();
exit(WEXITSTATUS(real_status)); exit(WEXITSTATUS(real_status));
} }
if (status != nullptr) { if (status != nullptr) {
@ -92,6 +92,7 @@ static void set_syscall_return(pid_t guest_pid, arm32_pt_regs *regs) {
// Main Loop // Main Loop
void loop_ptrace(pid_t guest_pid) { void loop_ptrace(pid_t guest_pid) {
unsigned char *args = shared_memory_host_only;
while (true) { while (true) {
// Wait For Syscall // Wait For Syscall
ptrace_wait_syscall(guest_pid); ptrace_wait_syscall(guest_pid);
@ -105,11 +106,9 @@ void loop_ptrace(pid_t guest_pid) {
uint32_t length; uint32_t length;
uint32_t args_addr; uint32_t args_addr;
get_arguments(&regs, &id, &length, &args_addr); get_arguments(&regs, &id, &length, &args_addr);
static unsigned char args[MAX_TRAMPOLINE_ARGS_SIZE];
memory_reader(args_addr, args, length);
// Run Trampoline // Run Trampoline
uint32_t ret = trampoline(id, args); const uint32_t ret = trampoline(id, args);
memory_writer(args_addr, &ret, sizeof(uint32_t)); *(uint32_t *) args = ret;
// Set Syscall Return // Set Syscall Return
set_syscall_return(guest_pid, &regs); set_syscall_return(guest_pid, &regs);
} }