diff options
-rw-r--r-- | libsandbox/trace.c | 28 | ||||
-rw-r--r-- | libsandbox/trace/linux/arch.c | 14 | ||||
-rw-r--r-- | libsandbox/trace/linux/bfin.c | 10 | ||||
-rw-r--r-- | libsandbox/trace/linux/common.c | 1 | ||||
-rw-r--r-- | libsandbox/trace/linux/hppa.c | 10 | ||||
-rw-r--r-- | libsandbox/trace/linux/i386.c | 10 | ||||
-rw-r--r-- | libsandbox/trace/linux/x86_64.c | 10 |
7 files changed, 65 insertions, 18 deletions
diff --git a/libsandbox/trace.c b/libsandbox/trace.c index 45bb5d4..5ccab87 100644 --- a/libsandbox/trace.c +++ b/libsandbox/trace.c @@ -76,6 +76,11 @@ static long do_peekuser(long offset) return do_ptrace(PTRACE_PEEKUSER, (void *)offset, NULL); } +static long do_pokeuser(long offset, long val) +{ + return do_ptrace(PTRACE_POKEUSER, (void *)offset, (void *)val); +} + static long do_peekdata(long offset) { return do_ptrace(PTRACE_PEEKDATA, (void *)offset, NULL); @@ -384,6 +389,9 @@ static bool trace_check_syscall(const struct syscall_entry *se, void *regs) #ifndef trace_get_regs # define trace_get_regs(regs) do_ptrace(PTRACE_GETREGS, NULL, regs) #endif +#ifndef trace_set_regs +# define trace_set_regs(regs) do_ptrace(PTRACE_SETREGS, NULL, regs) +#endif /* Some arches (like sparc) don't implement PTRACE_PEEK* ... * more asshats ! */ @@ -394,13 +402,14 @@ static bool trace_check_syscall(const struct syscall_entry *se, void *regs) static void trace_loop(void) { trace_regs regs; - bool before_syscall; + bool before_syscall, fake_syscall_ret; long ret; int nr, exec_state; const struct syscall_entry *se, *tbl_at_fork; exec_state = 0; before_syscall = true; + fake_syscall_ret = false; tbl_at_fork = NULL; do { ret = do_ptrace(PTRACE_SYSCALL, NULL, NULL); @@ -431,14 +440,21 @@ static void trace_loop(void) _SB_DEBUG("%s:%i", se ? se->name : "IDK", nr); if (!trace_check_syscall(se, ®s)) { if (is_env_on(ENV_SANDBOX_DEBUG)) - SB_EINFO("trace_loop", " destroying after %s\n", + SB_EINFO("trace_loop", " forcing EPERM after %s\n", se->name); - do_ptrace(PTRACE_KILL, NULL, NULL); - exit(1); + trace_set_sysnum(®s, -1); + fake_syscall_ret = true; } } else { int err; - ret = trace_result(®s, &err); + + if (unlikely(fake_syscall_ret)) { + ret = -1; + err = EPERM; + trace_set_ret(®s, err); + fake_syscall_ret = false; + } else + ret = trace_result(®s, &err); __SB_DEBUG(" = %li", ret); if (err) { @@ -480,7 +496,7 @@ void trace_main(const char *filename, char *const argv[]) } trace_pid = fork(); - if (trace_pid == -1) { + if (unlikely(trace_pid == -1)) { SB_EERROR("ISE:trace_main ", "vfork() failed: %s\n", strerror(errno)); sb_abort(); diff --git a/libsandbox/trace/linux/arch.c b/libsandbox/trace/linux/arch.c index de86109..df2fe5b 100644 --- a/libsandbox/trace/linux/arch.c +++ b/libsandbox/trace/linux/arch.c @@ -20,4 +20,18 @@ #ifdef SB_NO_TRACE_ARCH # warning "trace: sorry, no support for your architecture" # define SB_NO_TRACE +#else +# ifdef trace_sysnum_puser + +static int trace_sysnum(void) +{ + return do_peekuser(trace_sysnum_puser); +} + +static void trace_set_sysnum(void *vregs, long nr) +{ + do_pokeuser(trace_sysnum_puser, nr); +} + +# endif #endif diff --git a/libsandbox/trace/linux/bfin.c b/libsandbox/trace/linux/bfin.c index 4188034..60a8ef8 100644 --- a/libsandbox/trace/linux/bfin.c +++ b/libsandbox/trace/linux/bfin.c @@ -1,7 +1,4 @@ -static int trace_sysnum(void) -{ - return do_peekuser(PT_ORIG_P0); -} +#define trace_sysnum_puser PT_ORIG_P0 static long trace_raw_ret(void *vregs) { @@ -9,6 +6,11 @@ static long trace_raw_ret(void *vregs) return regs->r0; } +static void trace_set_ret(void *vregs, int err) +{ + do_pokeuser(PT_R0, -err); +} + static unsigned long trace_arg(void *vregs, int num) { trace_regs *regs = vregs; diff --git a/libsandbox/trace/linux/common.c b/libsandbox/trace/linux/common.c index 287af0a..de74caf 100644 --- a/libsandbox/trace/linux/common.c +++ b/libsandbox/trace/linux/common.c @@ -1,4 +1,5 @@ static long do_peekuser(long offset); +static long do_pokeuser(long offset, long val); static int trace_errno(long err) { diff --git a/libsandbox/trace/linux/hppa.c b/libsandbox/trace/linux/hppa.c index d98310f..b7fab1c 100644 --- a/libsandbox/trace/linux/hppa.c +++ b/libsandbox/trace/linux/hppa.c @@ -1,7 +1,4 @@ -static int trace_sysnum(void) -{ - return do_peekuser(20 * 4); /* PT_GR20 */ -} +#define trace_sysnum_puser (20 * 4) /* PT_GR20 */ static long trace_raw_ret(void *vregs) { @@ -9,6 +6,11 @@ static long trace_raw_ret(void *vregs) return regs->gr[28]; } +static void trace_set_ret(void *vregs, int err) +{ + do_pokeuser(28 * 4 /* PT_GR28 */, -err); +} + static unsigned long trace_arg(void *vregs, int num) { trace_regs *regs = vregs; diff --git a/libsandbox/trace/linux/i386.c b/libsandbox/trace/linux/i386.c index 7508e25..9a3f590 100644 --- a/libsandbox/trace/linux/i386.c +++ b/libsandbox/trace/linux/i386.c @@ -1,7 +1,4 @@ -static int trace_sysnum(void) -{ - return do_peekuser(4 * ORIG_EAX); -} +#define trace_sysnum_puser (4 * ORIG_EAX) static long trace_raw_ret(void *vregs) { @@ -9,6 +6,11 @@ static long trace_raw_ret(void *vregs) return regs->eax; } +static void trace_set_ret(void *vregs, int err) +{ + do_pokeuser(EAX, -err); +} + static unsigned long trace_arg(void *vregs, int num) { trace_regs *regs = vregs; diff --git a/libsandbox/trace/linux/x86_64.c b/libsandbox/trace/linux/x86_64.c index b864801..0110302 100644 --- a/libsandbox/trace/linux/x86_64.c +++ b/libsandbox/trace/linux/x86_64.c @@ -47,6 +47,16 @@ static long trace_raw_ret(void *vregs) return pers_is_32() ? (int)regs->rax : regs->rax; } +static void trace_set_sysnum(void *vregs, long nr) +{ + do_pokeuser(8 * ORIG_RAX, nr); +} + +static void trace_set_ret(void *vregs, int err) +{ + do_pokeuser(8 * RAX, -err); +} + static unsigned long trace_arg(void *vregs, int num) { trace_regs *regs = vregs; |