#include #include #include #include #include #include #include #include #include "sandbox.h" static inline void get_args(struct s_sandboxenv *env) { } int waitForSyscall(const int pid, int _status) { int status; static int current_status = SANDBOX_SYS_EXIT; if (current_status == _status || (_status != SANDBOX_SYS_ENTER && _status != SANDBOX_SYS_EXIT)) return 0; ptrace(PTRACE_SYSCALL, pid, NULL, 0); current_status = _status; if (waitpid(pid, &status, 0) == -1) return -1; return 0; } int manageSyscall(struct s_sandboxenv *env) { t_syscall_fnc ovr_fnc; if (env->syscall_no.syscall_no >= NR_syscalls || !(ovr_fnc = env->functions[env->syscall_no.syscall_no])) { /* Unrecognized syscall */ return 0; } return (ovr_fnc)(env); } void read_registers(struct s_sandboxenv *env) { struct iovec iov = { &(env->registers), sizeof(env->registers) }; ptrace(PTRACE_GETREGSET, env->child_pid, NT_PRSTATUS, &iov); #ifdef __x86_64__ env->syscall_no.syscall_no = (unsigned int) env->registers.orig_rax; env->syscall_no.syscall_return = (unsigned int) env->registers.rax; REGISTER_TYPE result[] = { env->registers.rdi, env->registers.rsi, env->registers.rdx, env->registers.r10, env->registers.r8, env->registers.r9 }; #else env->syscall_no.syscall_no = (unsigned int) env->registers.orig_eax; env->syscall_no.syscall_return = (unsigned int) env->registers.eax; REGISTER_TYPE result[] = { env->registers.ebx, env->registers.ecx, env->registers.edx, env->registers.esi, env->registers.edi, env->registers.ebp }; #endif memcpy(env->syscall_args, result, sizeof(REGISTER_TYPE) * 6); } void doTrace(int pid, const t_param *params) { int status; struct s_sandboxenv sandbox_env; ptrace(PTRACE_ATTACH, pid, 0, 0); kill(pid, SIGTRAP); waitpid(pid, &status, 0); sandbox_env.params = params; sandbox_env.child_pid = pid; //TODO get error output from command-line sandbox_env.errorOutput = stderr; sandbox_env.filetable = sllist_create(); init_syscalls(&sandbox_env); while (1) { if (waitForSyscall(pid, SANDBOX_SYS_ENTER)) break; read_registers(&sandbox_env); if (manageSyscall(&sandbox_env)) ptrace(PTRACE_SETREGS, pid, 0, &(sandbox_env.registers)); if (waitForSyscall(pid, SANDBOX_SYS_EXIT)) break; } prompt_sandbox(&sandbox_env); sllist_destroy(sandbox_env.filetable); } int launch_program(const t_param *params) { int child = fork(); if (child == -1) return -1; else if (child == 0) doExec(getpid(), params); else doTrace(child, params); return 0; }