X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=src%2Fbox.c;h=7bff340ce85cbb993c5ebc0e7dba8d8a584f15c7;hb=24a6e512fa3427c0f7f3003723093ff38ec11637;hp=095c8843ebdbe11d8b2342e45ab557339f1ab9d7;hpb=28a5f9efe1f794bd20def0b7a08ed1124629f0ff;p=eval.git diff --git a/src/box.c b/src/box.c index 095c884..7bff340 100644 --- a/src/box.c +++ b/src/box.c @@ -1,7 +1,7 @@ /* * A Simple Testing Sandbox * - * (c) 2001--2004 Martin Mares + * (c) 2001--2007 Martin Mares */ #define _LARGEFILE64_SOURCE @@ -29,9 +29,9 @@ #define UNUSED __attribute__((unused)) static int filter_syscalls; /* 0=off, 1=liberal, 2=totalitarian */ -static int timeout; +static int timeout; /* milliseconds */ +static int wall_timeout; static int pass_environ; -static int use_wall_clock; static int file_access; static int verbose; static int memory_limit; @@ -42,7 +42,7 @@ static char *set_cwd; static pid_t box_pid; static int is_ptraced; static volatile int timer_tick; -static time_t start_time; +static struct timeval start_time; static int ticks_per_sec; #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ > 0 @@ -78,7 +78,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 +97,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 +118,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 +153,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 @@ -264,11 +264,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,20 +287,28 @@ static void signal_int(int unused UNUSED) { /* Interrupts are fatal, so no synchronization requirements. */ - die("Interrupted."); + die("Interrupted"); } static void check_timeout(void) { - int sec; - - if (use_wall_clock) - sec = time(NULL) - start_time; - else + if (wall_timeout) + { + struct timeval now, wall; + int wall_ms; + gettimeofday(&now, NULL); + timersub(&now, &start_time, &wall); + wall_ms = wall.tv_sec*1000 + wall.tv_usec/1000; + if (wall_ms > wall_timeout) + die("Time limit exceeded (wall clock)"); + if (verbose > 1) + fprintf(stderr, "[wall time check: %d msec]\n", wall_ms); + } + if (timeout) { char buf[4096], *x; - int c, utime, stime; + int c, utime, stime, ms; static int proc_status_fd; if (!proc_status_fd) { @@ -328,12 +336,12 @@ check_timeout(void) x++; if (sscanf(x, "%*c %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %d %d", &utime, &stime) != 2) die("proc syntax error 2"); - sec = (utime + stime)/ticks_per_sec; + ms = (utime + stime) * 1000 / ticks_per_sec; + if (verbose > 1) + fprintf(stderr, "[time check: %d msec]\n", ms); + if (ms > timeout) + die("Time limit exceeded"); } - if (verbose > 1) - fprintf(stderr, "[timecheck: %d seconds]\n", sec); - if (sec > timeout) - die("Time limit exceeded."); } static void @@ -346,11 +354,11 @@ boxkeeper(void) bzero(&sa, sizeof(sa)); sa.sa_handler = signal_int; sigaction(SIGINT, &sa, NULL); - start_time = time(NULL); + gettimeofday(&start_time, NULL); ticks_per_sec = sysconf(_SC_CLK_TCK); if (ticks_per_sec <= 0) die("Invalid ticks_per_sec!"); - if (timeout) + if (timeout || wall_timeout) { sa.sa_handler = signal_alarm; sigaction(SIGALRM, &sa, NULL); @@ -377,22 +385,30 @@ boxkeeper(void) die("wait4: unknown pid %d exited!", p); if (WIFEXITED(stat)) { - struct timeval total; - int wall; + struct timeval total, now, wall; + 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); - wall = time(NULL) - start_time; - if ((use_wall_clock ? wall : total.tv_sec) > timeout) - die("Time limit exceeded (after exit)."); - fprintf(stderr, "OK (%d sec real, %d sec wall, %d syscalls)\n", (int) total.tv_sec, wall, syscall_count); + 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"); + if (wall_timeout && wall_ms > wall_timeout) + 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, + syscall_count); exit(0); } if (WIFSIGNALED(stat)) { box_pid = 0; - die("Caught fatal signal %d.", WTERMSIG(stat)); + die("Caught fatal signal %d", WTERMSIG(stat)); } if (WIFSTOPPED(stat)) { @@ -405,10 +421,10 @@ 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); + 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)) { @@ -421,20 +437,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); @@ -446,7 +462,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; @@ -496,10 +512,10 @@ Options:\n\ -i \tRedirect stdin from \n\ -m \tLimit address space to KB\n\ -o \tRedirect stdout to \n\ --t