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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sandbox/linux/seccomp/tests/test_syscalls.cc
===================================================================
--- sandbox/linux/seccomp/tests/test_syscalls.cc (revision 45661)
+++ sandbox/linux/seccomp/tests/test_syscalls.cc (working copy)
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include <assert.h>
+#include <dirent.h>
#include <pthread.h>
#include <pty.h>
#include <sys/types.h>
@@ -14,6 +15,33 @@
// This is basically a marker to grep for.
#define TEST(name) void name()
+TEST(test_dup) {
+ StartSeccompSandbox();
+ // Test a simple syscall that is marked as UNRESTRICTED_SYSCALL.
+ int fd = dup(1);
+ assert(fd >= 0);
+ int rc = close(fd);
+ assert(rc == 0);
+}
+
+// This has an off-by-three error because it counts ".", "..", and the
+// FD for the /proc/self/fd directory. This doesn't matter because it
+// is only used to check for differences in the number of open FDs.
+int count_fds() {
+ DIR *dir = opendir("/proc/self/fd");
+ assert(dir != NULL);
+ int count = 0;
+ while (1) {
+ struct dirent *d = readdir(dir);
+ if (d == NULL)
+ break;
+ count++;
+ }
+ int rc = closedir(dir);
+ assert(rc == 0);
+ return count;
+}
+
void *thread_func(void *x) {
int *ptr = (int *) x;
*ptr = 123;
@@ -23,17 +51,97 @@
TEST(test_thread) {
StartSeccompSandbox();
+ int fd_count1 = count_fds();
pthread_t tid;
- int x;
+ int x = 999;
void *result;
pthread_create(&tid, NULL, thread_func, &x);
printf("Waiting for thread\n");
pthread_join(tid, &result);
assert(result == (void *) 456);
assert(x == 123);
+ // Check that the process has not leaked FDs.
+ int fd_count2 = count_fds();
+ assert(fd_count2 == fd_count1);
}
int clone_func(void *x) {
+ int *ptr = (int *) x;
+ *ptr = 124;
+ printf("In thread\n");
+ // On x86-64, returning from this function calls the __NR_exit_group
+ // syscall instead of __NR_exit.
+ syscall(__NR_exit, 100);
+ // Not reached.
+ return 200;
+}
+
+#if defined(__i386__)
+int get_gs() {
+ int gs;
+ asm volatile("mov %%gs, %0" : "=r"(gs));
+ return gs;
+}
+#endif
+
+void *get_tls_base() {
+ void *base;
+#if defined(__x86_64__)
+ asm volatile("mov %%fs:0, %0" : "=r"(base));
+#elif defined(__i386__)
+ asm volatile("mov %%gs:0, %0" : "=r"(base));
+#else
+#error Unsupported target platform
+#endif
+ return base;
+}
+
+TEST(test_clone) {
+ StartSeccompSandbox();
+ int fd_count1 = count_fds();
+ int stack_size = 0x1000;
+ char *stack = (char *) malloc(stack_size);
+ assert(stack != NULL);
+ int flags = CLONE_VM | CLONE_FS | CLONE_FILES |
+ CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM |
+ CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID;
+ int tid = -1;
+ int x = 999;
+
+ // The sandbox requires us to pass CLONE_TLS. Pass settings that
+ // are enough to copy the parent thread's TLS setup. This allows us
+ // to invoke libc in the child thread.
+#if defined(__x86_64__)
+ void *tls = get_tls_base();
+#elif defined(__i386__)
+ struct user_desc tls_desc, *tls = &tls_desc;
+ tls_desc.entry_number = get_gs() >> 3;
+ tls_desc.base_addr = (long) get_tls_base();
+ tls_desc.limit = 0xfffff;
+ tls_desc.seg_32bit = 1;
+ tls_desc.contents = 0;
+ tls_desc.read_exec_only = 0;
+ tls_desc.limit_in_pages = 1;
+ tls_desc.seg_not_present = 0;
+ tls_desc.useable = 1;
+#else
+#error Unsupported target platform
+#endif
+
+ int rc = clone(clone_func, (void *) (stack + stack_size), flags, &x,
+ &tid, tls, &tid);
+ assert(rc > 0);
+ while (tid == rc) {
+ syscall(__NR_futex, &tid, FUTEX_WAIT, rc, NULL);
+ }
+ assert(tid == 0);
+ assert(x == 124);
+ // Check that the process has not leaked FDs.
+ int fd_count2 = count_fds();
+ assert(fd_count2 == fd_count1);
+}
+
+int uncalled_clone_func(void *x) {
printf("In thread func, which shouldn't happen\n");
return 1;
}
@@ -47,8 +155,8 @@
CLONE_CHILD_CLEARTID, which is disallowed by the sandbox. */
int flags = CLONE_VM | CLONE_FS | CLONE_FILES |
CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM;
- int rc = clone(clone_func, (void *) (stack + stack_size), flags, NULL,
- NULL, NULL, NULL);
+ int rc = clone(uncalled_clone_func, (void *) (stack + stack_size),
+ flags, NULL, NULL, NULL, NULL);
assert(rc == -1);
assert(errno == EPERM);
}
@@ -225,7 +333,7 @@
{ NULL, NULL },
};
-void run_test_forked(struct testcase *test) {
+int run_test_forked(struct testcase *test) {
printf("** %s\n", test->test_name);
int pid = fork();
if (pid == 0) {
@@ -236,8 +344,11 @@
waitpid(pid, &status, 0);
if (status != 0) {
printf("Test failed with exit status %i\n", status);
- exit(1);
+ return 1;
}
+ else {
+ return 0;
+ }
}
int run_test_by_name(const char *name) {
@@ -265,9 +376,17 @@
else {
// Run all tests.
struct testcase *test;
+ int failures = 0;
for (test = all_tests; test->test_name != NULL; test++) {
- run_test_forked(test);
+ failures += run_test_forked(test);
}
+ if (failures == 0) {
+ printf("OK\n");
+ return 0;
+ }
+ else {
+ printf("%i FAILURE(S)\n", failures);
+ return 1;
+ }
}
- return 0;
}
« 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