diff options
author | Mike Frysinger <vapier@gentoo.org> | 2009-03-31 21:39:16 -0400 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2009-04-05 03:53:58 -0400 |
commit | 8528e918e24c22779e6bf802794e99f1418ec4ba (patch) | |
tree | 4f8c45858e980a4a4f34fee82b3a96fc27aafc65 /libsandbox/trace | |
parent | bump to sandbox-1.8 (diff) | |
download | sandbox-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.c | 15 | ||||
-rw-r--r-- | libsandbox/trace/linux/x86_64.c | 87 |
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 |