]> mj.ucw.cz Git - moe.git/blobdiff - src/box.c
Log a different message when a fatal signal has been delivered before
[moe.git] / src / box.c
index 6eb99b2865aaddfd9043d66aaf60bf00f7edf71e..126452adbe176f9f511e38a47bef1e7f32cc1124 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 */
@@ -78,7 +79,7 @@ die(char *msg, ...)
 }
 
 static void __attribute__((format(printf,1,2)))
-log(char *msg, ...)
+msg(char *msg, ...)
 {
   va_list args;
   va_start(args, msg);
@@ -97,7 +98,7 @@ valid_filename(unsigned long addr)
   static int mem_fd;
 
   if (!file_access)
-    die("File access forbidden.");
+    die("File access forbidden");
   if (file_access >= 9)
     return;
 
@@ -118,21 +119,21 @@ valid_filename(unsigned long addr)
          if (l > remains)
            l = remains;
          if (!l)
-           die("Access to file with name too long.");
+           die("Access to file with name too long");
          if (long_seek(mem_fd, addr, SEEK_SET) < 0)
            die("long_seek(mem): %m");
          remains = read(mem_fd, end, l);
          if (remains < 0)
            die("read(mem): %m");
          if (!remains)
-           die("Access to file with name out of memory.");
+           die("Access to file with name out of memory");
          end += l;
          addr += l;
        }
     }
   while (*p++);
 
-  log("[%s] ", namebuf);
+  msg("[%s] ", namebuf);
   if (file_access >= 3)
     return;
   if (!strchr(namebuf, '/') && strcmp(namebuf, ".."))
@@ -153,7 +154,7 @@ valid_filename(unsigned long addr)
          !strncmp(namebuf, "/usr/share/zoneinfo/", 20))
        return;
     }
-  die("Forbidden access to file `%s'.", namebuf);
+  die("Forbidden access to file `%s'", namebuf);
 }
 
 static int
@@ -161,11 +162,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 +260,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;
@@ -287,7 +283,7 @@ static void
 signal_int(int unused UNUSED)
 {
   /* Interrupts are fatal, so no synchronization requirements. */
-  die("Interrupted.");
+  die("Interrupted");
 }
 
 static void
@@ -389,16 +385,16 @@ boxkeeper(void)
          int total_ms, wall_ms;
          box_pid = 0;
          if (WEXITSTATUS(stat))
-           die("Exited with error status %d.", WEXITSTATUS(stat));
+           die("Exited with error status %d", WEXITSTATUS(stat));
          timeradd(&rus.ru_utime, &rus.ru_stime, &total);
          total_ms = total.tv_sec*1000 + total.tv_usec/1000;
          gettimeofday(&now, NULL);
          timersub(&now, &start_time, &wall);
          wall_ms = wall.tv_sec*1000 + wall.tv_usec/1000;
          if (timeout && total_ms > timeout)
-           die("Time limit exceeded.");
+           die("Time limit exceeded");
          if (wall_timeout && wall_ms > wall_timeout)
-           die("Time limit exceeded (wall clock.");
+           die("Time limit exceeded (wall clock)");
          fprintf(stderr, "OK (%d.%03d sec real, %d.%03d sec wall, %d syscalls)\n",
              (int) total.tv_sec, (int) total.tv_usec/1000,
              (int) wall.tv_sec, (int) wall.tv_usec/1000,
@@ -408,7 +404,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))
        {
@@ -421,12 +417,19 @@ boxkeeper(void)
                die("ptrace(PTRACE_GETREGS): %m");
              stop_count++;
              if (!stop_count)                  /* Traceme request */
-               log(">> Traceme request caught\n");
+               msg(">> Traceme request caught\n");
              else if (stop_count & 1)          /* Syscall entry */
                {
-                 log(">> Syscall %3ld (%08lx,%08lx,%08lx) ", u.regs.orig_eax, u.regs.ebx, u.regs.ecx, u.regs.edx);
-                 syscall_count++;
-                 if (!valid_syscall(&u))
+                 msg(">> Syscall %3ld (%08lx,%08lx,%08lx) ", u.regs.orig_eax, 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,20 +440,20 @@ 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 %d", sys);
                    }
                }
              else                                      /* Syscall return */
-               log("= %ld\n", u.regs.eax);
+               msg("= %ld\n", u.regs.eax);
              ptrace(PTRACE_SYSCALL, box_pid, 0, 0);
            }
          else if (sig != SIGSTOP && sig != SIGXCPU && sig != SIGXFSZ)
            {
-             log(">> Signal %d\n", sig);
+             msg(">> Signal %d\n", sig);
              ptrace(PTRACE_SYSCALL, box_pid, 0, sig);
            }
          else
-           die("Received signal %d.", sig);
+           die("Received signal %d", sig);
        }
       else
        die("wait4: unknown status %x, giving up!", stat);
@@ -462,7 +465,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 +494,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]);
 }