]> mj.ucw.cz Git - moe.git/blobdiff - src/box.c
Generate a table of all known syscalls and use it to show syscall
[moe.git] / src / box.c
index cc780cd2c174cbc04c622830dc84160b9099bccc..fe1c22f83a7e81bd068a0a0dcab63666666671c2 100644 (file)
--- a/src/box.c
+++ b/src/box.c
@@ -44,6 +44,7 @@ static int is_ptraced;
 static volatile int timer_tick;
 static struct timeval start_time;
 static int ticks_per_sec;
+static int exec_seen;
 
 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ > 0
 /* glibc 2.1 or newer -> has lseek64 */
@@ -90,6 +91,39 @@ msg(char *msg, ...)
   va_end(args);
 }
 
+struct syscall {
+  const char *name;
+  int override;
+};
+
+static struct syscall syscall_tab[] = {
+#include "syscall-table.h"
+};
+#define NUM_SYSCALLS (sizeof(syscall_tab)/sizeof(syscall_tab[0]))
+
+static const char *
+syscall_name(unsigned int id, char *buf)
+{
+  if (id < NUM_SYSCALLS && syscall_tab[id].name)
+    return syscall_tab[id].name;
+  else
+    {
+      sprintf(buf, "#%d", id);
+      return buf;
+    }
+}
+
+#if 0
+static struct syscall *
+syscall_by_name(char *name)
+{
+  for (unsigned int i=0; i<sizeof(syscall_tab)/sizeof(syscall_tab[0]); i++)
+    if (!strcmp(syscall_tab[i].name, name))
+      return &syscall_tab[i];
+  return NULL;
+}
+#endif
+
 static void
 valid_filename(unsigned long addr)
 {
@@ -161,11 +195,6 @@ valid_syscall(struct user *u)
 {
   switch (u->regs.orig_eax)
     {
-    case __NR_execve:
-      {
-       static int exec_counter;
-       return !exec_counter++;
-      }
     case __NR_open:
     case __NR_creat:
     case __NR_unlink:
@@ -264,11 +293,11 @@ valid_syscall(struct user *u)
       return allow_times;
     case __NR_kill:
       if (u->regs.ebx == box_pid)
-       die("Commited suicide by signal %d", (int)u->regs.ecx);
+       die("Committed suicide by signal %d", (int)u->regs.ecx);
       return 0;
     case __NR_tgkill:
       if (u->regs.ebx == box_pid && u->regs.ecx == box_pid)
-       die("Commited suicide by signal %d", (int)u->regs.edx);
+       die("Committed suicide by signal %d", (int)u->regs.edx);
       return 0;
     default:
       return 0;
@@ -408,7 +437,7 @@ boxkeeper(void)
       if (WIFSIGNALED(stat))
        {
          box_pid = 0;
-         die("Caught fatal signal %d", WTERMSIG(stat));
+         die("Caught fatal signal %d%s", WTERMSIG(stat), (syscall_count ? "" : " during startup"));
        }
       if (WIFSTOPPED(stat))
        {
@@ -424,9 +453,17 @@ boxkeeper(void)
                msg(">> Traceme request caught\n");
              else if (stop_count & 1)          /* Syscall entry */
                {
-                 msg(">> Syscall %3ld (%08lx,%08lx,%08lx) ", u.regs.orig_eax, u.regs.ebx, u.regs.ecx, u.regs.edx);
-                 syscall_count++;
-                 if (!valid_syscall(&u))
+                 char namebuf[32];
+                 msg(">> Syscall %-12s (%08lx,%08lx,%08lx) ", syscall_name(u.regs.orig_eax, namebuf), u.regs.ebx, u.regs.ecx, u.regs.edx);
+                 if (!exec_seen)
+                   {
+                     msg("[master] ");
+                     if (u.regs.orig_eax == __NR_execve)
+                       exec_seen = 1;
+                   }
+                 else if (valid_syscall(&u))
+                   syscall_count++;
+                 else
                    {
                      /*
                       * Unfortunately, PTRACE_KILL kills _after_ the syscall completes,
@@ -437,7 +474,7 @@ boxkeeper(void)
                      u.regs.orig_eax = 0xffffffff;
                      if (ptrace(PTRACE_SETREGS, box_pid, NULL, &u) < 0)
                        die("ptrace(PTRACE_SETREGS): %m");
-                     die("Forbidden syscall %d", sys);
+                     die("Forbidden syscall %s", syscall_name(sys, namebuf));
                    }
                }
              else                                      /* Syscall return */
@@ -462,7 +499,7 @@ box_inside(int argc, char **argv)
 {
   struct rlimit rl;
   char *args[argc+1];
-  char *env[1] = { NULL };
+  char *env[] = { "LIBC_FATAL_STDERR_=1", NULL };
 
   memcpy(args, argv, argc * sizeof(char *));
   args[argc] = NULL;
@@ -491,8 +528,14 @@ box_inside(int argc, char **argv)
   rl.rlim_cur = rl.rlim_max = 64;
   if (setrlimit(RLIMIT_NOFILE, &rl) < 0)
     die("setrlimit: %m");
-  if (filter_syscalls && ptrace(PTRACE_TRACEME) < 0)
-    die("ptrace(PTRACE_TRACEME): %m");
+  if (filter_syscalls)
+    {
+      if (ptrace(PTRACE_TRACEME) < 0)
+       die("ptrace(PTRACE_TRACEME): %m");
+      /* Trick: Make sure that we are stopped until the boxkeeper wakes up. */
+      signal(SIGCHLD, SIG_IGN);
+      raise(SIGCHLD);
+    }
   execve(args[0], args, (pass_environ ? environ : env));
   die("execve(\"%s\"): %m", args[0]);
 }