Description:
added .gitignore to hold empty dirs, fixed deprecation warnings on const char* for box.cc git-svn-id: http://theory.cpe.ku.ac.th/grader/web/trunk@379 6386c4cd-e34a-4fa8-8920-d93eb39b512e
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r177:5f8c24384d1c - - 4 files changed: 6 inserted, 2 deleted

@@ -0,0 +1,2
1 + [^.]*
2 +
@@ -0,0 +1,1
1 + [^.]*
@@ -0,0 +1,1
1 + [^.]*
@@ -1,314 +1,314
1 /*
1 /*
2 * A Simple Testing Sandbox
2 * A Simple Testing Sandbox
3 *
3 *
4 * (c) 2001--2004 Martin Mares <mj@ucw.cz>
4 * (c) 2001--2004 Martin Mares <mj@ucw.cz>
5 */
5 */
6
6
7 #define _LARGEFILE64_SOURCE
7 #define _LARGEFILE64_SOURCE
8 //#define _GNU_SOURCE
8 //#define _GNU_SOURCE
9
9
10 #include <errno.h>
10 #include <errno.h>
11 #include <stdio.h>
11 #include <stdio.h>
12 #include <fcntl.h>
12 #include <fcntl.h>
13 #include <stdlib.h>
13 #include <stdlib.h>
14 #include <string.h>
14 #include <string.h>
15 #include <stdarg.h>
15 #include <stdarg.h>
16 #include <unistd.h>
16 #include <unistd.h>
17 #include <getopt.h>
17 #include <getopt.h>
18 #include <time.h>
18 #include <time.h>
19 #include <sys/wait.h>
19 #include <sys/wait.h>
20 #include <sys/user.h>
20 #include <sys/user.h>
21 #include <sys/time.h>
21 #include <sys/time.h>
22 #include <sys/ptrace.h>
22 #include <sys/ptrace.h>
23 #include <sys/signal.h>
23 #include <sys/signal.h>
24 #include <sys/sysinfo.h>
24 #include <sys/sysinfo.h>
25 #include <sys/syscall.h>
25 #include <sys/syscall.h>
26 #include <sys/resource.h>
26 #include <sys/resource.h>
27
27
28 #define NONRET __attribute__((noreturn))
28 #define NONRET __attribute__((noreturn))
29 #define UNUSED __attribute__((unused))
29 #define UNUSED __attribute__((unused))
30
30
31 static int filter_syscalls; /* 0=off, 1=liberal, 2=totalitarian */
31 static int filter_syscalls; /* 0=off, 1=liberal, 2=totalitarian */
32 static double timeout;
32 static double timeout;
33 static int pass_environ;
33 static int pass_environ;
34 static int use_wall_clock;
34 static int use_wall_clock;
35 static int file_access;
35 static int file_access;
36 static int verbose;
36 static int verbose;
37 static int memory_limit;
37 static int memory_limit;
38 static int allow_times;
38 static int allow_times;
39 static char *redir_stdin, *redir_stdout;
39 static char *redir_stdin, *redir_stdout;
40 static char *set_cwd;
40 static char *set_cwd;
41
41
42 static pid_t box_pid;
42 static pid_t box_pid;
43 static int is_ptraced;
43 static int is_ptraced;
44 static volatile int timer_tick;
44 static volatile int timer_tick;
45 static time_t start_time;
45 static time_t start_time;
46 static int ticks_per_sec;
46 static int ticks_per_sec;
47 static int page_size;
47 static int page_size;
48
48
49 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ > 0
49 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ > 0
50 /* glibc 2.1 or newer -> has lseek64 */
50 /* glibc 2.1 or newer -> has lseek64 */
51 #define long_seek(f,o,w) lseek64(f,o,w)
51 #define long_seek(f,o,w) lseek64(f,o,w)
52 #else
52 #else
53 /* Touching clandestine places in glibc */
53 /* Touching clandestine places in glibc */
54 extern loff_t llseek(int fd, loff_t pos, int whence);
54 extern loff_t llseek(int fd, loff_t pos, int whence);
55 #define long_seek(f,o,w) llseek(f,o,w)
55 #define long_seek(f,o,w) llseek(f,o,w)
56 #endif
56 #endif
57
57
58 int max_mem_used = 0;
58 int max_mem_used = 0;
59
59
60 void print_running_stat(double wall_time,
60 void print_running_stat(double wall_time,
61 double user_time,
61 double user_time,
62 double system_time,
62 double system_time,
63 int mem_usage)
63 int mem_usage)
64 {
64 {
65 fprintf(stderr,"%.4lfr%.4lfu%.4lfs%dm\n",
65 fprintf(stderr,"%.4lfr%.4lfu%.4lfs%dm\n",
66 wall_time, user_time, system_time, mem_usage);
66 wall_time, user_time, system_time, mem_usage);
67 }
67 }
68
68
69 static void NONRET
69 static void NONRET
70 box_exit(void)
70 box_exit(void)
71 {
71 {
72 if (box_pid > 0) {
72 if (box_pid > 0) {
73 if (is_ptraced)
73 if (is_ptraced)
74 ptrace(PTRACE_KILL, box_pid);
74 ptrace(PTRACE_KILL, box_pid);
75 kill(-box_pid, SIGKILL);
75 kill(-box_pid, SIGKILL);
76 kill(box_pid, SIGKILL);
76 kill(box_pid, SIGKILL);
77 }
77 }
78
78
79 struct timeval total;
79 struct timeval total;
80 int wall;
80 int wall;
81 struct rusage rus;
81 struct rusage rus;
82 int stat;
82 int stat;
83 pid_t p;
83 pid_t p;
84
84
85 // wait so that we can get information
85 // wait so that we can get information
86 p = wait4(box_pid, &stat, WUNTRACED, &rus);
86 p = wait4(box_pid, &stat, WUNTRACED, &rus);
87 if (p < 0) {
87 if (p < 0) {
88 fprintf(stderr,"wait4: error\n");
88 fprintf(stderr,"wait4: error\n");
89 print_running_stat(0,0,0,max_mem_used);
89 print_running_stat(0,0,0,max_mem_used);
90 } else if (p != box_pid) {
90 } else if (p != box_pid) {
91 fprintf(stderr,"wait4: unknown pid %d exited!\n", p);
91 fprintf(stderr,"wait4: unknown pid %d exited!\n", p);
92 print_running_stat(0,0,0,max_mem_used);
92 print_running_stat(0,0,0,max_mem_used);
93 } else {
93 } else {
94 if (!WIFEXITED(stat))
94 if (!WIFEXITED(stat))
95 fprintf(stderr,"wait4: unknown status\n");
95 fprintf(stderr,"wait4: unknown status\n");
96 struct timeval total;
96 struct timeval total;
97 int wall;
97 int wall;
98 wall = time(NULL) - start_time;
98 wall = time(NULL) - start_time;
99 timeradd(&rus.ru_utime, &rus.ru_stime, &total);
99 timeradd(&rus.ru_utime, &rus.ru_stime, &total);
100
100
101 print_running_stat((double)wall,
101 print_running_stat((double)wall,
102 (double) rus.ru_utime.tv_sec +
102 (double) rus.ru_utime.tv_sec +
103 ((double) rus.ru_utime.tv_usec/1000000.0),
103 ((double) rus.ru_utime.tv_usec/1000000.0),
104 (double) rus.ru_stime.tv_sec +
104 (double) rus.ru_stime.tv_sec +
105 ((double) rus.ru_stime.tv_usec/1000000.0),
105 ((double) rus.ru_stime.tv_usec/1000000.0),
106 max_mem_used);
106 max_mem_used);
107 }
107 }
108 exit(1);
108 exit(1);
109 }
109 }
110
110
111 static void NONRET __attribute__((format(printf,1,2)))
111 static void NONRET __attribute__((format(printf,1,2)))
112 - die(char *msg, ...)
112 + die(const char *msg, ...)
113 {
113 {
114 va_list args;
114 va_list args;
115 va_start(args, msg);
115 va_start(args, msg);
116 vfprintf(stderr, msg, args);
116 vfprintf(stderr, msg, args);
117 fputc('\n', stderr);
117 fputc('\n', stderr);
118 box_exit();
118 box_exit();
119 }
119 }
120
120
121 static void __attribute__((format(printf,1,2)))
121 static void __attribute__((format(printf,1,2)))
122 - log(char *msg, ...)
122 + log(const char *msg, ...)
123 {
123 {
124 va_list args;
124 va_list args;
125 va_start(args, msg);
125 va_start(args, msg);
126 if (verbose)
126 if (verbose)
127 {
127 {
128 vfprintf(stderr, msg, args);
128 vfprintf(stderr, msg, args);
129 fflush(stderr);
129 fflush(stderr);
130 }
130 }
131 va_end(args);
131 va_end(args);
132 }
132 }
133
133
134 static void
134 static void
135 valid_filename(unsigned long addr)
135 valid_filename(unsigned long addr)
136 {
136 {
137 char namebuf[4096], *p, *end;
137 char namebuf[4096], *p, *end;
138 static int mem_fd;
138 static int mem_fd;
139
139
140 if (!file_access)
140 if (!file_access)
141 die("File access forbidden.");
141 die("File access forbidden.");
142 if (file_access >= 9)
142 if (file_access >= 9)
143 return;
143 return;
144
144
145 if (!mem_fd)
145 if (!mem_fd)
146 {
146 {
147 sprintf(namebuf, "/proc/%d/mem", (int) box_pid);
147 sprintf(namebuf, "/proc/%d/mem", (int) box_pid);
148 mem_fd = open(namebuf, O_RDONLY);
148 mem_fd = open(namebuf, O_RDONLY);
149 if (mem_fd < 0)
149 if (mem_fd < 0)
150 die("open(%s): %m", namebuf);
150 die("open(%s): %m", namebuf);
151 }
151 }
152 p = end = namebuf;
152 p = end = namebuf;
153 do
153 do
154 {
154 {
155 if (p >= end)
155 if (p >= end)
156 {
156 {
157 int remains = PAGE_SIZE - (addr & (PAGE_SIZE-1));
157 int remains = PAGE_SIZE - (addr & (PAGE_SIZE-1));
158 int l = namebuf + sizeof(namebuf) - end;
158 int l = namebuf + sizeof(namebuf) - end;
159 if (l > remains)
159 if (l > remains)
160 l = remains;
160 l = remains;
161 if (!l)
161 if (!l)
162 die("Access to file with name too long.");
162 die("Access to file with name too long.");
163 if (long_seek(mem_fd, addr, SEEK_SET) < 0)
163 if (long_seek(mem_fd, addr, SEEK_SET) < 0)
164 die("long_seek(mem): %m");
164 die("long_seek(mem): %m");
165 remains = read(mem_fd, end, l);
165 remains = read(mem_fd, end, l);
166 if (remains < 0)
166 if (remains < 0)
167 die("read(mem): %m");
167 die("read(mem): %m");
168 if (!remains)
168 if (!remains)
169 die("Access to file with name out of memory.");
169 die("Access to file with name out of memory.");
170 end += l;
170 end += l;
171 addr += l;
171 addr += l;
172 }
172 }
173 }
173 }
174 while (*p++);
174 while (*p++);
175
175
176 log("[%s] ", namebuf);
176 log("[%s] ", namebuf);
177 if (file_access >= 3)
177 if (file_access >= 3)
178 return;
178 return;
179 if (!strchr(namebuf, '/') && strcmp(namebuf, ".."))
179 if (!strchr(namebuf, '/') && strcmp(namebuf, ".."))
180 return;
180 return;
181 if (file_access >= 2)
181 if (file_access >= 2)
182 {
182 {
183 if ((!strncmp(namebuf, "/etc/", 5) ||
183 if ((!strncmp(namebuf, "/etc/", 5) ||
184 !strncmp(namebuf, "/lib/", 5) ||
184 !strncmp(namebuf, "/lib/", 5) ||
185 !strncmp(namebuf, "/usr/lib/", 9))
185 !strncmp(namebuf, "/usr/lib/", 9))
186 && !strstr(namebuf, ".."))
186 && !strstr(namebuf, ".."))
187 return;
187 return;
188 if (!strcmp(namebuf, "/dev/null") ||
188 if (!strcmp(namebuf, "/dev/null") ||
189 !strcmp(namebuf, "/dev/zero") ||
189 !strcmp(namebuf, "/dev/zero") ||
190 !strcmp(namebuf, "/proc/meminfo") ||
190 !strcmp(namebuf, "/proc/meminfo") ||
191 !strcmp(namebuf, "/proc/self/stat") ||
191 !strcmp(namebuf, "/proc/self/stat") ||
192 !strncmp(namebuf, "/usr/share/zoneinfo/", 20))
192 !strncmp(namebuf, "/usr/share/zoneinfo/", 20))
193 return;
193 return;
194 }
194 }
195 die("Forbidden access to file `%s'.", namebuf);
195 die("Forbidden access to file `%s'.", namebuf);
196 }
196 }
197
197
198 static int
198 static int
199 valid_syscall(struct user *u)
199 valid_syscall(struct user *u)
200 {
200 {
201 switch (u->regs.orig_eax)
201 switch (u->regs.orig_eax)
202 {
202 {
203 case __NR_execve:
203 case __NR_execve:
204 {
204 {
205 static int exec_counter;
205 static int exec_counter;
206 return !exec_counter++;
206 return !exec_counter++;
207 }
207 }
208 case __NR_open:
208 case __NR_open:
209 case __NR_creat:
209 case __NR_creat:
210 case __NR_unlink:
210 case __NR_unlink:
211 case __NR_oldstat:
211 case __NR_oldstat:
212 case __NR_access:
212 case __NR_access:
213 case __NR_oldlstat:
213 case __NR_oldlstat:
214 case __NR_truncate:
214 case __NR_truncate:
215 case __NR_stat:
215 case __NR_stat:
216 case __NR_lstat:
216 case __NR_lstat:
217 case __NR_truncate64:
217 case __NR_truncate64:
218 case __NR_stat64:
218 case __NR_stat64:
219 case __NR_lstat64:
219 case __NR_lstat64:
220 valid_filename(u->regs.ebx);
220 valid_filename(u->regs.ebx);
221 return 1;
221 return 1;
222 case __NR_exit:
222 case __NR_exit:
223 case __NR_read:
223 case __NR_read:
224 case __NR_write:
224 case __NR_write:
225 case __NR_close:
225 case __NR_close:
226 case __NR_lseek:
226 case __NR_lseek:
227 case __NR_getpid:
227 case __NR_getpid:
228 case __NR_getuid:
228 case __NR_getuid:
229 case __NR_oldfstat:
229 case __NR_oldfstat:
230 case __NR_dup:
230 case __NR_dup:
231 case __NR_brk:
231 case __NR_brk:
232 case __NR_getgid:
232 case __NR_getgid:
233 case __NR_geteuid:
233 case __NR_geteuid:
234 case __NR_getegid:
234 case __NR_getegid:
235 case __NR_dup2:
235 case __NR_dup2:
236 case __NR_ftruncate:
236 case __NR_ftruncate:
237 case __NR_fstat:
237 case __NR_fstat:
238 case __NR_personality:
238 case __NR_personality:
239 case __NR__llseek:
239 case __NR__llseek:
240 case __NR_readv:
240 case __NR_readv:
241 case __NR_writev:
241 case __NR_writev:
242 case __NR_getresuid:
242 case __NR_getresuid:
243 #ifdef __NR_pread64
243 #ifdef __NR_pread64
244 case __NR_pread64:
244 case __NR_pread64:
245 case __NR_pwrite64:
245 case __NR_pwrite64:
246 #else
246 #else
247 case __NR_pread:
247 case __NR_pread:
248 case __NR_pwrite:
248 case __NR_pwrite:
249 #endif
249 #endif
250 case __NR_ftruncate64:
250 case __NR_ftruncate64:
251 case __NR_fstat64:
251 case __NR_fstat64:
252 case __NR_fcntl:
252 case __NR_fcntl:
253 case __NR_fcntl64:
253 case __NR_fcntl64:
254 case __NR_mmap:
254 case __NR_mmap:
255 case __NR_munmap:
255 case __NR_munmap:
256 case __NR_ioctl:
256 case __NR_ioctl:
257 case __NR_uname:
257 case __NR_uname:
258 case 252:
258 case 252:
259 case 243:
259 case 243:
260 // added for free pascal
260 // added for free pascal
261 case __NR_ugetrlimit:
261 case __NR_ugetrlimit:
262 case __NR_readlink:
262 case __NR_readlink:
263 return 1;
263 return 1;
264 // case __NR_time:
264 // case __NR_time:
265 case __NR_alarm:
265 case __NR_alarm:
266 // case __NR_pause:
266 // case __NR_pause:
267 case __NR_signal:
267 case __NR_signal:
268 case __NR_fchmod:
268 case __NR_fchmod:
269 case __NR_sigaction:
269 case __NR_sigaction:
270 case __NR_sgetmask:
270 case __NR_sgetmask:
271 case __NR_ssetmask:
271 case __NR_ssetmask:
272 case __NR_sigsuspend:
272 case __NR_sigsuspend:
273 case __NR_sigpending:
273 case __NR_sigpending:
274 case __NR_getrlimit:
274 case __NR_getrlimit:
275 case __NR_getrusage:
275 case __NR_getrusage:
276 case __NR_gettimeofday:
276 case __NR_gettimeofday:
277 case __NR_select:
277 case __NR_select:
278 case __NR_readdir:
278 case __NR_readdir:
279 case __NR_setitimer:
279 case __NR_setitimer:
280 case __NR_getitimer:
280 case __NR_getitimer:
281 case __NR_sigreturn:
281 case __NR_sigreturn:
282 case __NR_mprotect:
282 case __NR_mprotect:
283 case __NR_sigprocmask:
283 case __NR_sigprocmask:
284 case __NR_getdents:
284 case __NR_getdents:
285 case __NR_getdents64:
285 case __NR_getdents64:
286 case __NR__newselect:
286 case __NR__newselect:
287 case __NR_fdatasync:
287 case __NR_fdatasync:
288 case __NR_mremap:
288 case __NR_mremap:
289 case __NR_poll:
289 case __NR_poll:
290 case __NR_getcwd:
290 case __NR_getcwd:
291 case __NR_nanosleep:
291 case __NR_nanosleep:
292 case __NR_rt_sigreturn:
292 case __NR_rt_sigreturn:
293 case __NR_rt_sigaction:
293 case __NR_rt_sigaction:
294 case __NR_rt_sigprocmask:
294 case __NR_rt_sigprocmask:
295 case __NR_rt_sigpending:
295 case __NR_rt_sigpending:
296 case __NR_rt_sigtimedwait:
296 case __NR_rt_sigtimedwait:
297 case __NR_rt_sigqueueinfo:
297 case __NR_rt_sigqueueinfo:
298 case __NR_rt_sigsuspend:
298 case __NR_rt_sigsuspend:
299 case __NR_mmap2:
299 case __NR_mmap2:
300 case __NR__sysctl:
300 case __NR__sysctl:
301 return (filter_syscalls == 1);
301 return (filter_syscalls == 1);
302 case __NR_times:
302 case __NR_times:
303 case __NR_time:
303 case __NR_time:
304 return allow_times;
304 return allow_times;
305 case __NR_kill:
305 case __NR_kill:
306 if (u->regs.ebx == box_pid)
306 if (u->regs.ebx == box_pid)
307 die("Commited suicide by signal %d.", (int)u->regs.ecx);
307 die("Commited suicide by signal %d.", (int)u->regs.ecx);
308 return 0;
308 return 0;
309 default:
309 default:
310 return 0;
310 return 0;
311 }
311 }
312 }
312 }
313
313
314 static void
314 static void
You need to be logged in to leave comments. Login now