WIP
This commit is contained in:
parent
b2cf446e9d
commit
027e58ee9b
@ -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);
|
||||||
|
@ -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")
|
||||||
|
@ -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();
|
||||||
|
@ -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());
|
||||||
|
}
|
@ -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();
|
@ -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 {
|
||||||
|
@ -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(®s, &id, &length, &args_addr);
|
get_arguments(®s, &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, ®s);
|
set_syscall_return(guest_pid, ®s);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user