libsandbox: migrate to get/set regs interface for everyone
authorMike Frysinger <vapier@gentoo.org>
Tue, 3 Jul 2012 04:45:41 +0000 (00:45 -0400)
committerMike Frysinger <vapier@gentoo.org>
Tue, 3 Jul 2012 18:27:45 +0000 (14:27 -0400)
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>
libsandbox/trace.c
libsandbox/trace/common.c
libsandbox/trace/linux/arch.c
libsandbox/trace/linux/bfin.c
libsandbox/trace/linux/common.c
libsandbox/trace/linux/hppa.c
libsandbox/trace/linux/i386.c
libsandbox/trace/linux/sparc.c
libsandbox/trace/linux/x86_64.c

index a7b7c02..f2071e0 100644 (file)
@@ -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);
index 7604440..f426887 100644 (file)
@@ -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
index df2fe5b..5ca1acb 100644 (file)
 # 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
index 60a8ef8..299ab51 100644 (file)
@@ -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)
 {
index de74caf..5ca9491 100644 (file)
@@ -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)
 {
index b7fab1c..d23b0d1 100644 (file)
@@ -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;
+}
index 9a3f590..f214026 100644 (file)
@@ -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)
 {
index f1d91e1..f410b73 100644 (file)
 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)
 {
index 8a214f9..9b7e4ea 100644 (file)
@@ -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;