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

Side by Side Diff: tests/test_syscalls.cc

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