aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libsandbox/trace.c28
-rw-r--r--libsandbox/trace/linux/arch.c14
-rw-r--r--libsandbox/trace/linux/bfin.c10
-rw-r--r--libsandbox/trace/linux/common.c1
-rw-r--r--libsandbox/trace/linux/hppa.c10
-rw-r--r--libsandbox/trace/linux/i386.c10
-rw-r--r--libsandbox/trace/linux/x86_64.c10
7 files changed, 65 insertions, 18 deletions
diff --git a/libsandbox/trace.c b/libsandbox/trace.c
index 45bb5d4..5ccab87 100644
--- a/libsandbox/trace.c
+++ b/libsandbox/trace.c
@@ -76,6 +76,11 @@ 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);
@@ -384,6 +389,9 @@ static bool trace_check_syscall(const struct syscall_entry *se, void *regs)
#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 !
*/
@@ -394,13 +402,14 @@ static bool trace_check_syscall(const struct syscall_entry *se, void *regs)
static void trace_loop(void)
{
trace_regs regs;
- bool before_syscall;
+ bool before_syscall, fake_syscall_ret;
long ret;
int nr, exec_state;
const struct syscall_entry *se, *tbl_at_fork;
exec_state = 0;
before_syscall = true;
+ fake_syscall_ret = false;
tbl_at_fork = NULL;
do {
ret = do_ptrace(PTRACE_SYSCALL, NULL, NULL);
@@ -431,14 +440,21 @@ static void trace_loop(void)
_SB_DEBUG("%s:%i", se ? se->name : "IDK", nr);
if (!trace_check_syscall(se, &regs)) {
if (is_env_on(ENV_SANDBOX_DEBUG))
- SB_EINFO("trace_loop", " destroying after %s\n",
+ SB_EINFO("trace_loop", " forcing EPERM after %s\n",
se->name);
- do_ptrace(PTRACE_KILL, NULL, NULL);
- exit(1);
+ trace_set_sysnum(&regs, -1);
+ fake_syscall_ret = true;
}
} else {
int err;
- ret = trace_result(&regs, &err);
+
+ if (unlikely(fake_syscall_ret)) {
+ ret = -1;
+ err = EPERM;
+ trace_set_ret(&regs, err);
+ fake_syscall_ret = false;
+ } else
+ ret = trace_result(&regs, &err);
__SB_DEBUG(" = %li", ret);
if (err) {
@@ -480,7 +496,7 @@ void trace_main(const char *filename, char *const argv[])
}
trace_pid = fork();
- if (trace_pid == -1) {
+ if (unlikely(trace_pid == -1)) {
SB_EERROR("ISE:trace_main ", "vfork() failed: %s\n",
strerror(errno));
sb_abort();
diff --git a/libsandbox/trace/linux/arch.c b/libsandbox/trace/linux/arch.c
index de86109..df2fe5b 100644
--- a/libsandbox/trace/linux/arch.c
+++ b/libsandbox/trace/linux/arch.c
@@ -20,4 +20,18 @@
#ifdef SB_NO_TRACE_ARCH
# warning "trace: sorry, no support for your architecture"
# define SB_NO_TRACE
+#else
+# ifdef trace_sysnum_puser
+
+static int trace_sysnum(void)
+{
+ return do_peekuser(trace_sysnum_puser);
+}
+
+static void trace_set_sysnum(void *vregs, long nr)
+{
+ do_pokeuser(trace_sysnum_puser, nr);
+}
+
+# endif
#endif
diff --git a/libsandbox/trace/linux/bfin.c b/libsandbox/trace/linux/bfin.c
index 4188034..60a8ef8 100644
--- a/libsandbox/trace/linux/bfin.c
+++ b/libsandbox/trace/linux/bfin.c
@@ -1,7 +1,4 @@
-static int trace_sysnum(void)
-{
- return do_peekuser(PT_ORIG_P0);
-}
+#define trace_sysnum_puser PT_ORIG_P0
static long trace_raw_ret(void *vregs)
{
@@ -9,6 +6,11 @@ static long trace_raw_ret(void *vregs)
return regs->r0;
}
+static void trace_set_ret(void *vregs, int err)
+{
+ do_pokeuser(PT_R0, -err);
+}
+
static unsigned long trace_arg(void *vregs, int num)
{
trace_regs *regs = vregs;
diff --git a/libsandbox/trace/linux/common.c b/libsandbox/trace/linux/common.c
index 287af0a..de74caf 100644
--- a/libsandbox/trace/linux/common.c
+++ b/libsandbox/trace/linux/common.c
@@ -1,4 +1,5 @@
static long do_peekuser(long offset);
+static long do_pokeuser(long offset, long val);
static int trace_errno(long err)
{
diff --git a/libsandbox/trace/linux/hppa.c b/libsandbox/trace/linux/hppa.c
index d98310f..b7fab1c 100644
--- a/libsandbox/trace/linux/hppa.c
+++ b/libsandbox/trace/linux/hppa.c
@@ -1,7 +1,4 @@
-static int trace_sysnum(void)
-{
- return do_peekuser(20 * 4); /* PT_GR20 */
-}
+#define trace_sysnum_puser (20 * 4) /* PT_GR20 */
static long trace_raw_ret(void *vregs)
{
@@ -9,6 +6,11 @@ static long trace_raw_ret(void *vregs)
return regs->gr[28];
}
+static void trace_set_ret(void *vregs, int err)
+{
+ do_pokeuser(28 * 4 /* PT_GR28 */, -err);
+}
+
static unsigned long trace_arg(void *vregs, int num)
{
trace_regs *regs = vregs;
diff --git a/libsandbox/trace/linux/i386.c b/libsandbox/trace/linux/i386.c
index 7508e25..9a3f590 100644
--- a/libsandbox/trace/linux/i386.c
+++ b/libsandbox/trace/linux/i386.c
@@ -1,7 +1,4 @@
-static int trace_sysnum(void)
-{
- return do_peekuser(4 * ORIG_EAX);
-}
+#define trace_sysnum_puser (4 * ORIG_EAX)
static long trace_raw_ret(void *vregs)
{
@@ -9,6 +6,11 @@ static long trace_raw_ret(void *vregs)
return regs->eax;
}
+static void trace_set_ret(void *vregs, int err)
+{
+ do_pokeuser(EAX, -err);
+}
+
static unsigned long trace_arg(void *vregs, int num)
{
trace_regs *regs = vregs;
diff --git a/libsandbox/trace/linux/x86_64.c b/libsandbox/trace/linux/x86_64.c
index b864801..0110302 100644
--- a/libsandbox/trace/linux/x86_64.c
+++ b/libsandbox/trace/linux/x86_64.c
@@ -47,6 +47,16 @@ static long trace_raw_ret(void *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);
+}
+
+static void trace_set_ret(void *vregs, int err)
+{
+ do_pokeuser(8 * RAX, -err);
+}
+
static unsigned long trace_arg(void *vregs, int num)
{
trace_regs *regs = vregs;