aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2009-03-31 21:39:16 -0400
committerMike Frysinger <vapier@gentoo.org>2009-04-05 03:53:58 -0400
commit8528e918e24c22779e6bf802794e99f1418ec4ba (patch)
tree4f8c45858e980a4a4f34fee82b3a96fc27aafc65 /libsandbox/trace
parentbump to sandbox-1.8 (diff)
downloadsandbox-8528e918e24c22779e6bf802794e99f1418ec4ba.tar.gz
sandbox-8528e918e24c22779e6bf802794e99f1418ec4ba.tar.bz2
sandbox-8528e918e24c22779e6bf802794e99f1418ec4ba.zip
libsandbox: enable tracing for multiple personalities
Initial support for tracing non-default personalities. For example, tracing a 32bit binary from a 64bit environment. URL: http://bugs.gentoo.org/264399 Signed-off-by: Mike Frysinger <vapier@gentoo.org> Reported-by: Patrick Lauer <patrick@gentoo.org>
Diffstat (limited to 'libsandbox/trace')
-rw-r--r--libsandbox/trace/common.c15
-rw-r--r--libsandbox/trace/linux/x86_64.c87
2 files changed, 92 insertions, 10 deletions
diff --git a/libsandbox/trace/common.c b/libsandbox/trace/common.c
index 20fcb7e..390e343 100644
--- a/libsandbox/trace/common.c
+++ b/libsandbox/trace/common.c
@@ -1,3 +1,18 @@
+struct syscall_entry {
+ const int nr, sys;
+ const char *name;
+};
+
static int trace_sysnum(void);
static long trace_raw_ret(void *vregs);
static unsigned long trace_arg(void *vregs, int num);
+
+#ifndef SB_SCHIZO
+static const struct syscall_entry syscall_table[] = {
+#define S(s) { SB_SYS_##s, SB_NR_##s, #s },
+#include "trace_syscalls.h"
+#undef S
+ { SB_NR_UNDEF, SB_NR_UNDEF, NULL },
+};
+# define trace_check_personality() syscall_table
+#endif
diff --git a/libsandbox/trace/linux/x86_64.c b/libsandbox/trace/linux/x86_64.c
index 1f40036..96e732e 100644
--- a/libsandbox/trace/linux/x86_64.c
+++ b/libsandbox/trace/linux/x86_64.c
@@ -1,3 +1,41 @@
+#ifdef SB_SCHIZO
+
+static const struct syscall_entry syscall_table_32[] = {
+#define S(s) { SB_SYS_x86_##s, SB_NR_##s, #s },
+#include "trace_syscalls_x86.h"
+#undef S
+ { SB_NR_UNDEF, SB_NR_UNDEF, NULL },
+};
+static const struct syscall_entry syscall_table_64[] = {
+#define S(s) { SB_SYS_x86_64_##s, SB_NR_##s, #s },
+#include "trace_syscalls_x86_64.h"
+#undef S
+ { SB_NR_UNDEF, SB_NR_UNDEF, NULL },
+};
+
+static bool pers_is_32(void)
+{
+ switch (do_peekuser(8 * CS)) {
+ case 0x23: return true;
+ case 0x33: return false;
+ default: sb_abort();
+ }
+}
+
+static const struct syscall_entry *trace_check_personality(void)
+{
+ return pers_is_32() ? syscall_table_32 : syscall_table_64;
+}
+
+#else
+
+static bool pers_is_32(void)
+{
+ return false;
+}
+
+#endif
+
static int trace_sysnum(void)
{
return do_peekuser(8 * ORIG_RAX);
@@ -6,19 +44,48 @@ static int trace_sysnum(void)
static long trace_raw_ret(void *vregs)
{
struct user_regs_struct *regs = vregs;
- return regs->rax;
+ return pers_is_32() ? (int)regs->rax : regs->rax;
}
static unsigned long trace_arg(void *vregs, int num)
{
struct user_regs_struct *regs = vregs;
- switch (num) {
- case 1: return regs->rdi;
- case 2: return regs->rsi;
- case 3: return regs->rdx;
- case 4: return regs->r10;
- case 5: return regs->r8;
- case 6: return regs->r9;
- default: return -1;
- }
+ if (pers_is_32())
+ switch (num) {
+ case 1: return regs->rbx;
+ case 2: return regs->rcx;
+ case 3: return regs->rdx;
+ case 4: return regs->rsi;
+ case 5: return regs->rdi;
+ case 6: return regs->rbp;
+ default: return -1;
+ }
+ else
+ switch (num) {
+ case 1: return regs->rdi;
+ case 2: return regs->rsi;
+ case 3: return regs->rdx;
+ case 4: return regs->r10;
+ case 5: return regs->r8;
+ case 6: return regs->r9;
+ default: return -1;
+ }
+}
+
+#ifdef DEBUG
+static void trace_dump_regs(void *vregs)
+{
+ struct user_regs_struct *regs = vregs;
+ sb_printf("{ ");
+#define D(r) sb_printf(#r":%lu ", regs->r)
+ D(rax);
+ D(rdi);
+ D(rsi);
+ D(rdx);
+ D(r10);
+ D(r8);
+ D(r9);
+#undef D
+ sb_printf("}");
}
+#endif