Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(96)

Side by Side Diff: sandbox/linux/seccomp/tests/test_syscalls.cc

Issue 1756015: Add a couple more tests... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 10 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <assert.h> 5 #include <assert.h>
6 #include <dirent.h>
6 #include <pthread.h> 7 #include <pthread.h>
7 #include <pty.h> 8 #include <pty.h>
8 #include <sys/types.h> 9 #include <sys/types.h>
9 #include <sys/wait.h> 10 #include <sys/wait.h>
10 11
11 #include "sandbox_impl.h" 12 #include "sandbox_impl.h"
12 13
13 14
14 // This is basically a marker to grep for. 15 // This is basically a marker to grep for.
15 #define TEST(name) void name() 16 #define TEST(name) void name()
16 17
18 TEST(test_dup) {
19 StartSeccompSandbox();
20 // Test a simple syscall that is marked as UNRESTRICTED_SYSCALL.
21 int fd = dup(1);
22 assert(fd >= 0);
23 int rc = close(fd);
24 assert(rc == 0);
25 }
26
27 // This has an off-by-three error because it counts ".", "..", and the
28 // FD for the /proc/self/fd directory. This doesn't matter because it
29 // is only used to check for differences in the number of open FDs.
30 int count_fds() {
31 DIR *dir = opendir("/proc/self/fd");
32 assert(dir != NULL);
33 int count = 0;
34 while (1) {
35 struct dirent *d = readdir(dir);
36 if (d == NULL)
37 break;
38 count++;
39 }
40 int rc = closedir(dir);
41 assert(rc == 0);
42 return count;
43 }
44
17 void *thread_func(void *x) { 45 void *thread_func(void *x) {
18 int *ptr = (int *) x; 46 int *ptr = (int *) x;
19 *ptr = 123; 47 *ptr = 123;
20 printf("In new thread\n"); 48 printf("In new thread\n");
21 return (void *) 456; 49 return (void *) 456;
22 } 50 }
23 51
24 TEST(test_thread) { 52 TEST(test_thread) {
25 StartSeccompSandbox(); 53 StartSeccompSandbox();
54 int fd_count1 = count_fds();
26 pthread_t tid; 55 pthread_t tid;
27 int x; 56 int x = 999;
28 void *result; 57 void *result;
29 pthread_create(&tid, NULL, thread_func, &x); 58 pthread_create(&tid, NULL, thread_func, &x);
30 printf("Waiting for thread\n"); 59 printf("Waiting for thread\n");
31 pthread_join(tid, &result); 60 pthread_join(tid, &result);
32 assert(result == (void *) 456); 61 assert(result == (void *) 456);
33 assert(x == 123); 62 assert(x == 123);
63 // Check that the process has not leaked FDs.
64 int fd_count2 = count_fds();
65 assert(fd_count2 == fd_count1);
34 } 66 }
35 67
36 int clone_func(void *x) { 68 int clone_func(void *x) {
69 int *ptr = (int *) x;
70 *ptr = 124;
71 printf("In thread\n");
72 // On x86-64, returning from this function calls the __NR_exit_group
73 // syscall instead of __NR_exit.
74 syscall(__NR_exit, 100);
75 // Not reached.
76 return 200;
77 }
78
79 #if defined(__i386__)
80 int get_gs() {
81 int gs;
82 asm volatile("mov %%gs, %0" : "=r"(gs));
83 return gs;
84 }
85 #endif
86
87 void *get_tls_base() {
88 void *base;
89 #if defined(__x86_64__)
90 asm volatile("mov %%fs:0, %0" : "=r"(base));
91 #elif defined(__i386__)
92 asm volatile("mov %%gs:0, %0" : "=r"(base));
93 #else
94 #error Unsupported target platform
95 #endif
96 return base;
97 }
98
99 TEST(test_clone) {
100 StartSeccompSandbox();
101 int fd_count1 = count_fds();
102 int stack_size = 0x1000;
103 char *stack = (char *) malloc(stack_size);
104 assert(stack != NULL);
105 int flags = CLONE_VM | CLONE_FS | CLONE_FILES |
106 CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM |
107 CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID;
108 int tid = -1;
109 int x = 999;
110
111 // The sandbox requires us to pass CLONE_TLS. Pass settings that
112 // are enough to copy the parent thread's TLS setup. This allows us
113 // to invoke libc in the child thread.
114 #if defined(__x86_64__)
115 void *tls = get_tls_base();
116 #elif defined(__i386__)
117 struct user_desc tls_desc, *tls = &tls_desc;
118 tls_desc.entry_number = get_gs() >> 3;
119 tls_desc.base_addr = (long) get_tls_base();
120 tls_desc.limit = 0xfffff;
121 tls_desc.seg_32bit = 1;
122 tls_desc.contents = 0;
123 tls_desc.read_exec_only = 0;
124 tls_desc.limit_in_pages = 1;
125 tls_desc.seg_not_present = 0;
126 tls_desc.useable = 1;
127 #else
128 #error Unsupported target platform
129 #endif
130
131 int rc = clone(clone_func, (void *) (stack + stack_size), flags, &x,
132 &tid, tls, &tid);
133 assert(rc > 0);
134 while (tid == rc) {
135 syscall(__NR_futex, &tid, FUTEX_WAIT, rc, NULL);
136 }
137 assert(tid == 0);
138 assert(x == 124);
139 // Check that the process has not leaked FDs.
140 int fd_count2 = count_fds();
141 assert(fd_count2 == fd_count1);
142 }
143
144 int uncalled_clone_func(void *x) {
37 printf("In thread func, which shouldn't happen\n"); 145 printf("In thread func, which shouldn't happen\n");
38 return 1; 146 return 1;
39 } 147 }
40 148
41 TEST(test_clone_disallowed_flags) { 149 TEST(test_clone_disallowed_flags) {
42 StartSeccompSandbox(); 150 StartSeccompSandbox();
43 int stack_size = 4096; 151 int stack_size = 4096;
44 char *stack = (char *) malloc(stack_size); 152 char *stack = (char *) malloc(stack_size);
45 assert(stack != NULL); 153 assert(stack != NULL);
46 /* We omit the flags CLONE_SETTLS, CLONE_PARENT_SETTID and 154 /* We omit the flags CLONE_SETTLS, CLONE_PARENT_SETTID and
47 CLONE_CHILD_CLEARTID, which is disallowed by the sandbox. */ 155 CLONE_CHILD_CLEARTID, which is disallowed by the sandbox. */
48 int flags = CLONE_VM | CLONE_FS | CLONE_FILES | 156 int flags = CLONE_VM | CLONE_FS | CLONE_FILES |
49 CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM; 157 CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM;
50 int rc = clone(clone_func, (void *) (stack + stack_size), flags, NULL, 158 int rc = clone(uncalled_clone_func, (void *) (stack + stack_size),
51 NULL, NULL, NULL); 159 flags, NULL, NULL, NULL, NULL);
52 assert(rc == -1); 160 assert(rc == -1);
53 assert(errno == EPERM); 161 assert(errno == EPERM);
54 } 162 }
55 163
56 long long read_tsc() { 164 long long read_tsc() {
57 long long rc; 165 long long rc;
58 asm volatile( 166 asm volatile(
59 "rdtsc\n" 167 "rdtsc\n"
60 "mov %%eax, (%0)\n" 168 "mov %%eax, (%0)\n"
61 "mov %%edx, 4(%0)\n" 169 "mov %%edx, 4(%0)\n"
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 struct testcase { 326 struct testcase {
219 const char *test_name; 327 const char *test_name;
220 void (*test_func)(); 328 void (*test_func)();
221 }; 329 };
222 330
223 struct testcase all_tests[] = { 331 struct testcase all_tests[] = {
224 #include "test-list.h" 332 #include "test-list.h"
225 { NULL, NULL }, 333 { NULL, NULL },
226 }; 334 };
227 335
228 void run_test_forked(struct testcase *test) { 336 int run_test_forked(struct testcase *test) {
229 printf("** %s\n", test->test_name); 337 printf("** %s\n", test->test_name);
230 int pid = fork(); 338 int pid = fork();
231 if (pid == 0) { 339 if (pid == 0) {
232 test->test_func(); 340 test->test_func();
233 _exit(0); 341 _exit(0);
234 } 342 }
235 int status; 343 int status;
236 waitpid(pid, &status, 0); 344 waitpid(pid, &status, 0);
237 if (status != 0) { 345 if (status != 0) {
238 printf("Test failed with exit status %i\n", status); 346 printf("Test failed with exit status %i\n", status);
239 exit(1); 347 return 1;
348 }
349 else {
350 return 0;
240 } 351 }
241 } 352 }
242 353
243 int run_test_by_name(const char *name) { 354 int run_test_by_name(const char *name) {
244 struct testcase *test; 355 struct testcase *test;
245 for (test = all_tests; test->test_name != NULL; test++) { 356 for (test = all_tests; test->test_name != NULL; test++) {
246 if (strcmp(name, test->test_name) == 0) { 357 if (strcmp(name, test->test_name) == 0) {
247 test->test_func(); 358 test->test_func();
248 return 0; 359 return 0;
249 } 360 }
250 } 361 }
251 fprintf(stderr, "Test '%s' not found\n", name); 362 fprintf(stderr, "Test '%s' not found\n", name);
252 return 1; 363 return 1;
253 } 364 }
254 365
255 int main(int argc, char **argv) { 366 int main(int argc, char **argv) {
256 if (argc == 2) { 367 if (argc == 2) {
257 // Run one test without forking, to aid debugging. 368 // Run one test without forking, to aid debugging.
258 return run_test_by_name(argv[1]); 369 return run_test_by_name(argv[1]);
259 } 370 }
260 else if (argc > 2) { 371 else if (argc > 2) {
261 // TODO: run multiple tests. 372 // TODO: run multiple tests.
262 fprintf(stderr, "Too many arguments\n"); 373 fprintf(stderr, "Too many arguments\n");
263 return 1; 374 return 1;
264 } 375 }
265 else { 376 else {
266 // Run all tests. 377 // Run all tests.
267 struct testcase *test; 378 struct testcase *test;
379 int failures = 0;
268 for (test = all_tests; test->test_name != NULL; test++) { 380 for (test = all_tests; test->test_name != NULL; test++) {
269 run_test_forked(test); 381 failures += run_test_forked(test);
382 }
383 if (failures == 0) {
384 printf("OK\n");
385 return 0;
386 }
387 else {
388 printf("%i FAILURE(S)\n", failures);
389 return 1;
270 } 390 }
271 } 391 }
272 return 0;
273 } 392 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698