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 */
}
static void __attribute__((format(printf,1,2)))
-log(char *msg, ...)
+msg(char *msg, ...)
{
va_list args;
va_start(args, msg);
static int mem_fd;
if (!file_access)
- die("File access forbidden.");
+ die("File access forbidden");
if (file_access >= 9)
return;
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, ".."))
!strncmp(namebuf, "/usr/share/zoneinfo/", 20))
return;
}
- die("Forbidden access to file `%s'.", namebuf);
+ die("Forbidden access to file `%s'", namebuf);
}
static int
{
switch (u->regs.orig_eax)
{
- case __NR_execve:
- {
- static int exec_counter;
- return !exec_counter++;
- }
case __NR_open:
case __NR_creat:
case __NR_unlink:
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;
signal_int(int unused UNUSED)
{
/* Interrupts are fatal, so no synchronization requirements. */
- die("Interrupted.");
+ die("Interrupted");
}
static 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,
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))
{
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,
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);
{
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;
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]);
}