aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2012-07-03 00:45:41 -0400
committerMike Frysinger <vapier@gentoo.org>2012-07-03 14:27:45 -0400
commit731630b7470b2b7ae3c055779138460d14d9fcd5 (patch)
tree5f4d373a2f4032789515ca1a608956b76ec17f6d /libsandbox
parentinclude stdint.h/inttypes.h too (diff)
downloadsandbox-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>
Diffstat (limited to 'libsandbox')
-rw-r--r--libsandbox/trace.c43
-rw-r--r--libsandbox/trace/common.c5
-rw-r--r--libsandbox/trace/linux/arch.c26
-rw-r--r--libsandbox/trace/linux/bfin.c14
-rw-r--r--libsandbox/trace/linux/common.c8
-rw-r--r--libsandbox/trace/linux/hppa.c38
-rw-r--r--libsandbox/trace/linux/i386.c14
-rw-r--r--libsandbox/trace/linux/sparc.c6
-rw-r--r--libsandbox/trace/linux/x86_64.c29
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(&regs);
+ ret = trace_get_regs(&regs);
+ nr = trace_get_sysnum(&regs);
if (!exec_state) {
if (!tbl_at_fork)
- tbl_at_fork = trace_check_personality();
+ tbl_at_fork = trace_check_personality(&regs);
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(&regs);
+ se = lookup_syscall_in_tbl(tbl_after_fork, nr);
ret = trace_get_regs(&regs);
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;