diff options
author | Mike Frysinger <vapier@gentoo.org> | 2012-07-03 00:45:41 -0400 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2012-07-03 14:27:45 -0400 |
commit | 731630b7470b2b7ae3c055779138460d14d9fcd5 (patch) | |
tree | 5f4d373a2f4032789515ca1a608956b76ec17f6d | |
parent | include stdint.h/inttypes.h too (diff) | |
download | sandbox-731630b7470b2b7ae3c055779138460d14d9fcd5.tar.gz sandbox-731630b7470b2b7ae3c055779138460d14d9fcd5.tar.bz2 sandbox-731630b7470b2b7ae3c055779138460d14d9fcd5.zip |
libsandbox: migrate to get/set regs interface for everyone
Newer ports (like x32) limit what is available via the peek/poke user
interface, and instead are pushing people to use the single get/set
regs interface. Since this also simplifies the code a bit (by forcing
all ports to use this), and cuts down on the number of syscalls that
we have to make, switch everyone over to it.
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
-rw-r--r-- | libsandbox/trace.c | 43 | ||||
-rw-r--r-- | libsandbox/trace/common.c | 5 | ||||
-rw-r--r-- | libsandbox/trace/linux/arch.c | 26 | ||||
-rw-r--r-- | libsandbox/trace/linux/bfin.c | 14 | ||||
-rw-r--r-- | libsandbox/trace/linux/common.c | 8 | ||||
-rw-r--r-- | libsandbox/trace/linux/hppa.c | 38 | ||||
-rw-r--r-- | libsandbox/trace/linux/i386.c | 14 | ||||
-rw-r--r-- | libsandbox/trace/linux/sparc.c | 6 | ||||
-rw-r--r-- | libsandbox/trace/linux/x86_64.c | 29 |
9 files changed, 80 insertions, 103 deletions
diff --git a/libsandbox/trace.c b/libsandbox/trace.c index a7b7c02..f2071e0 100644 --- a/libsandbox/trace.c +++ b/libsandbox/trace.c @@ -70,16 +70,6 @@ static long _do_ptrace(enum __ptrace_request request, const char *srequest, void return ret; } -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); @@ -205,10 +195,6 @@ static const struct syscall_entry *lookup_syscall_in_tbl(const struct syscall_en ++tbl; return NULL; } -static const struct syscall_entry *lookup_syscall(int nr) -{ - return lookup_syscall_in_tbl(trace_check_personality(), nr); -} struct syscall_state { void *regs; @@ -382,42 +368,27 @@ static bool trace_check_syscall(const struct syscall_entry *se, void *regs) return ret; } -/* Some arches (like hppa) don't implement PTRACE_GETREGS, while others (like - * sparc) swap the meaning of "addr" and "data. What a bunch of asshats. - */ -#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 ! - */ -#ifndef trace_sysnum_regs -# define trace_sysnum_regs(regs) trace_sysnum() -#endif - static void trace_loop(void) { trace_regs regs; bool before_syscall, fake_syscall_ret; long ret; int nr, exec_state; - const struct syscall_entry *se, *tbl_at_fork; + const struct syscall_entry *se, *tbl_at_fork, *tbl_after_fork; exec_state = 0; before_syscall = true; fake_syscall_ret = false; - tbl_at_fork = NULL; + tbl_at_fork = tbl_after_fork = NULL; do { ret = do_ptrace(PTRACE_SYSCALL, NULL, NULL); waitpid(trace_pid, NULL, 0); - nr = trace_sysnum_regs(®s); + ret = trace_get_regs(®s); + nr = trace_get_sysnum(®s); if (!exec_state) { if (!tbl_at_fork) - tbl_at_fork = trace_check_personality(); + tbl_at_fork = trace_check_personality(®s); se = lookup_syscall_in_tbl(tbl_at_fork, nr); if (!before_syscall || !se || se->sys != SB_NR_EXECVE) { if (before_syscall) @@ -433,7 +404,9 @@ static void trace_loop(void) goto loop_again; } - se = lookup_syscall(nr); + if (!tbl_after_fork) + tbl_after_fork = trace_check_personality(®s); + se = lookup_syscall_in_tbl(tbl_after_fork, nr); ret = trace_get_regs(®s); if (before_syscall) { _sb_debug("%s:%i", se ? se->name : "IDK", nr); diff --git a/libsandbox/trace/common.c b/libsandbox/trace/common.c index 7604440..f426887 100644 --- a/libsandbox/trace/common.c +++ b/libsandbox/trace/common.c @@ -3,8 +3,7 @@ struct syscall_entry { const char *name; }; -static int trace_sysnum(void); -static int trace_sysnum_regs(void *vregs); +static int trace_get_sysnum(void *vregs); static long trace_raw_ret(void *vregs); static unsigned long trace_arg(void *vregs, int num); @@ -15,5 +14,5 @@ static const struct syscall_entry syscall_table[] = { #undef S { SB_NR_UNDEF, SB_NR_UNDEF, NULL }, }; -# define trace_check_personality() syscall_table +# define trace_check_personality(regs) syscall_table #endif diff --git a/libsandbox/trace/linux/arch.c b/libsandbox/trace/linux/arch.c index df2fe5b..5ca1acb 100644 --- a/libsandbox/trace/linux/arch.c +++ b/libsandbox/trace/linux/arch.c @@ -21,17 +21,33 @@ # warning "trace: sorry, no support for your architecture" # define SB_NO_TRACE #else -# ifdef trace_sysnum_puser -static int trace_sysnum(void) +# ifdef trace_reg_sysnum +static int trace_get_sysnum(void *vregs) { - return do_peekuser(trace_sysnum_puser); + trace_regs *regs = vregs; + return regs->trace_reg_sysnum; } - static void trace_set_sysnum(void *vregs, long nr) { - do_pokeuser(trace_sysnum_puser, nr); + trace_regs *regs = vregs; + regs->trace_reg_sysnum = nr; + trace_set_regs(regs); } +# endif +# ifdef trace_reg_ret +static long trace_raw_ret(void *vregs) +{ + trace_regs *regs = vregs; + return regs->trace_reg_ret; +} +static void trace_set_ret(void *vregs, int err) +{ + trace_regs *regs = vregs; + regs->trace_reg_ret = -err; + trace_set_regs(regs); +} # endif + #endif diff --git a/libsandbox/trace/linux/bfin.c b/libsandbox/trace/linux/bfin.c index 60a8ef8..299ab51 100644 --- a/libsandbox/trace/linux/bfin.c +++ b/libsandbox/trace/linux/bfin.c @@ -1,15 +1,5 @@ -#define trace_sysnum_puser PT_ORIG_P0 - -static long trace_raw_ret(void *vregs) -{ - trace_regs *regs = vregs; - return regs->r0; -} - -static void trace_set_ret(void *vregs, int err) -{ - do_pokeuser(PT_R0, -err); -} +#define trace_reg_sysnum orig_p0 +#define trace_reg_ret r0 static unsigned long trace_arg(void *vregs, int num) { diff --git a/libsandbox/trace/linux/common.c b/libsandbox/trace/linux/common.c index de74caf..5ca9491 100644 --- a/libsandbox/trace/linux/common.c +++ b/libsandbox/trace/linux/common.c @@ -1,5 +1,9 @@ -static long do_peekuser(long offset); -static long do_pokeuser(long offset, long val); +/* + * Some arches (like hppa) don't implement PTRACE_GETREGS, while others (like + * sparc) swap the meaning of "addr" and "data. What a bunch of asshats. + */ +#define trace_get_regs(regs) do_ptrace(PTRACE_GETREGS, NULL, regs) +#define trace_set_regs(regs) do_ptrace(PTRACE_SETREGS, NULL, regs) static int trace_errno(long err) { diff --git a/libsandbox/trace/linux/hppa.c b/libsandbox/trace/linux/hppa.c index b7fab1c..d23b0d1 100644 --- a/libsandbox/trace/linux/hppa.c +++ b/libsandbox/trace/linux/hppa.c @@ -1,15 +1,5 @@ -#define trace_sysnum_puser (20 * 4) /* PT_GR20 */ - -static long trace_raw_ret(void *vregs) -{ - trace_regs *regs = vregs; - return regs->gr[28]; -} - -static void trace_set_ret(void *vregs, int err) -{ - do_pokeuser(28 * 4 /* PT_GR28 */, -err); -} +#define trace_reg_sysnum (20 * 4) /* PT_GR20 */ +#define trace_reg_ret (28 * 4) /* PT_GR28 */ static unsigned long trace_arg(void *vregs, int num) { @@ -25,12 +15,32 @@ static unsigned long trace_arg(void *vregs, int num) } } +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); +} + +#undef trace_get_regs static long trace_get_regs(void *vregs) { trace_regs *regs = vregs; size_t i; - for (i = 21; i < 29; ++i) + for (i = 20; i < 29; ++i) regs->gr[i] = do_peekuser(i * 4); return 0; } -#define trace_get_regs trace_get_regs + +#undef trace_set_regs +static long trace_set_regs(void *vregs) +{ + trace_regs *regs = vregs; + size_t i; + for (i = 20; i < 29; ++i) + do_pokeuser(i * 4, regs->gr[i]); + return 0; +} diff --git a/libsandbox/trace/linux/i386.c b/libsandbox/trace/linux/i386.c index 9a3f590..f214026 100644 --- a/libsandbox/trace/linux/i386.c +++ b/libsandbox/trace/linux/i386.c @@ -1,15 +1,5 @@ -#define trace_sysnum_puser (4 * ORIG_EAX) - -static long trace_raw_ret(void *vregs) -{ - trace_regs *regs = vregs; - return regs->eax; -} - -static void trace_set_ret(void *vregs, int err) -{ - do_pokeuser(EAX, -err); -} +#define trace_reg_sysnum orig_eax +#define trace_reg_ret eax static unsigned long trace_arg(void *vregs, int num) { diff --git a/libsandbox/trace/linux/sparc.c b/libsandbox/trace/linux/sparc.c index f1d91e1..f410b73 100644 --- a/libsandbox/trace/linux/sparc.c +++ b/libsandbox/trace/linux/sparc.c @@ -10,11 +10,11 @@ static int trace_sysnum_regs(void *vregs) { trace_regs *regs = vregs; - do_ptrace(PTRACE_GETREGS, regs, NULL); return regs->u_regs[U_REG_G1] ? : SB_SYS_EXECVE; } -#define trace_sysnum_regs(regs) trace_sysnum_regs(regs) -#define trace_get_regs(regs) (0) + +#undef trace_get_regs +#define trace_get_regs(regs) do_ptrace(PTRACE_GETREGS, regs, NULL) static long trace_raw_ret(void *vregs) { diff --git a/libsandbox/trace/linux/x86_64.c b/libsandbox/trace/linux/x86_64.c index 8a214f9..9b7e4ea 100644 --- a/libsandbox/trace/linux/x86_64.c +++ b/libsandbox/trace/linux/x86_64.c @@ -13,54 +13,49 @@ static const struct syscall_entry syscall_table_64[] = { { SB_NR_UNDEF, SB_NR_UNDEF, NULL }, }; -static bool pers_is_32(void) +static bool pers_is_32(trace_regs *regs) { - switch (do_peekuser(8 * CS)) { + switch (regs->cs) { case 0x23: return true; case 0x33: return false; default: sb_ebort("unknown x86_64 personality"); } } -static const struct syscall_entry *trace_check_personality(void) +static const struct syscall_entry *trace_check_personality(void *vregs) { - return pers_is_32() ? syscall_table_32 : syscall_table_64; + trace_regs *regs = vregs; + return pers_is_32(regs) ? syscall_table_32 : syscall_table_64; } #else -static bool pers_is_32(void) +static bool pers_is_32(trace_regs *regs) { return false; } #endif -static int trace_sysnum(void) -{ - return do_peekuser(8 * ORIG_RAX); -} +#define trace_reg_sysnum orig_rax static long trace_raw_ret(void *vregs) { trace_regs *regs = 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); + return pers_is_32(regs) ? (int)regs->rax : regs->rax; } static void trace_set_ret(void *vregs, int err) { - do_pokeuser(8 * RAX, -err); + trace_regs *regs = vregs; + regs->rax = -err; + trace_set_regs(regs); } static unsigned long trace_arg(void *vregs, int num) { trace_regs *regs = vregs; - if (pers_is_32()) + if (pers_is_32(regs)) switch (num) { case 1: return regs->rbx; case 2: return regs->rcx; |