X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Fbox.c;h=126452adbe176f9f511e38a47bef1e7f32cc1124;hb=a49468009ab979be8444228578def12aa4570527;hp=6eb99b2865aaddfd9043d66aaf60bf00f7edf71e;hpb=325264b9d0d300e7701a8c2df1300508f448ae0e;p=eval.git diff --git a/src/box.c b/src/box.c index 6eb99b2..126452a 100644 --- 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]); }