summaryrefslogtreecommitdiffstats
path: root/sandbox
diff options
context:
space:
mode:
authormarkus@chromium.org <markus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-22 23:20:17 +0000
committermarkus@chromium.org <markus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-22 23:20:17 +0000
commita1170ed12a730f79d4224779b90e35923c7bb729 (patch)
tree5991ab0bc1bf159e16fde015952704c04a9b8277 /sandbox
parent18cec742ac18f7c99a357e57a659eed68397f8c6 (diff)
downloadchromium_src-a1170ed12a730f79d4224779b90e35923c7bb729.zip
chromium_src-a1170ed12a730f79d4224779b90e35923c7bb729.tar.gz
chromium_src-a1170ed12a730f79d4224779b90e35923c7bb729.tar.bz2
Merged Mark Seaborn's changes:
Add some automated tests for seccomp-sandbox This covers some of the syscalls that are proxied by the trusted process. This adds a basic test runner framework. Fix error return code for open() and other syscalls on x86-64 On error, the open() syscall was returning errno & 0xffffffff in %rax on x86-64 instead of -errno. This stops glibc from regarding this as an error, and so its syscall wrapper returns -errno instead of -1 and does not set errno. I have fixed up the other syscalls to use long (64-bit) instead of int (32-bit) as well. Not all of them were affected by the problem: it depends on gcc's code generation. Sometimes casting to int truncates a value, sometimes it doesn't. It seems better to be consistent though. Adds a test for open() and some other syscalls. TODO: Need to figure out how to run the tests automatically BUG=none TEST=none Review URL: http://codereview.chromium.org/1729003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@45379 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sandbox')
-rw-r--r--sandbox/linux/seccomp/Makefile56
-rw-r--r--sandbox/linux/seccomp/access.cc4
-rw-r--r--sandbox/linux/seccomp/clone.cc6
-rw-r--r--sandbox/linux/seccomp/exit.cc2
-rw-r--r--sandbox/linux/seccomp/getpid.cc2
-rw-r--r--sandbox/linux/seccomp/gettid.cc2
-rw-r--r--sandbox/linux/seccomp/ioctl.cc4
-rw-r--r--sandbox/linux/seccomp/ipc.cc16
-rw-r--r--sandbox/linux/seccomp/madvise.cc4
-rw-r--r--sandbox/linux/seccomp/mprotect.cc4
-rw-r--r--sandbox/linux/seccomp/munmap.cc4
-rw-r--r--sandbox/linux/seccomp/open.cc4
-rw-r--r--sandbox/linux/seccomp/sandbox_impl.h50
-rw-r--r--sandbox/linux/seccomp/sigprocmask.cc10
-rw-r--r--sandbox/linux/seccomp/socketcall.cc24
-rw-r--r--sandbox/linux/seccomp/stat.cc16
-rw-r--r--sandbox/linux/seccomp/tests/list_tests.py22
-rw-r--r--sandbox/linux/seccomp/tests/test_syscalls.cc273
18 files changed, 427 insertions, 76 deletions
diff --git a/sandbox/linux/seccomp/Makefile b/sandbox/linux/seccomp/Makefile
new file mode 100644
index 0000000..5fde2d2
--- /dev/null
+++ b/sandbox/linux/seccomp/Makefile
@@ -0,0 +1,56 @@
+# Copyright (c) 2010 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This Makefile temporarily has been checked into the source tree so that
+# we can run the tests. It will be replaced with a proper gyp file.
+
+CFLAGS = -g -O0 -Wall -Werror -Wextra -Wno-missing-field-initializers \
+ -Wno-unused-parameter -I.
+LDFLAGS = -g
+CPPFLAGS =
+MODS := allocator library debug maps x86_decode securemem sandbox \
+ syscall syscall_table trusted_thread trusted_process \
+ access exit clone getpid gettid ioctl ipc madvise mmap mprotect \
+ munmap open sigprocmask socketcall stat
+OBJS64 := $(shell echo ${MODS} | xargs -n 1 | sed -e 's/$$/.o64/')
+OBJS32 := $(shell echo ${MODS} | xargs -n 1 | sed -e 's/$$/.o32/')
+HEADERS:= $(shell for i in ${MODS}; do [ -r "$$i" ] && echo "$$i"; done)
+
+.SUFFIXES: .o64 .o32
+
+all: test
+
+clean:
+ -rm -f *.o *.o32 *.o64 tests/*.o32 tests/*.o.64
+ -rm -f core core.* vgcore vgcore.* strace.log*
+
+test: run_tests_64 run_tests_32
+ ./run_tests_64
+ ./run_tests_32
+
+# TODO: Track header file dependencies properly
+tests/test_syscalls.o64 tests/test_syscalls.o32: tests/test-list.h
+
+tests/test-list.h: tests/list_tests.py tests/test_syscalls.cc
+ python tests/list_tests.py tests/test_syscalls.cc > $@
+
+run_tests_64: $(OBJS64) tests/test_syscalls.o64 tests/test-list.h
+ g++ -m64 tests/test_syscalls.o64 $(OBJS64) -lpthread -lutil -o $@
+run_tests_32: $(OBJS32) tests/test_syscalls.o32 tests/test-list.h
+ g++ -m32 tests/test_syscalls.o32 $(OBJS32) -lpthread -lutil -o $@
+
+.cc.o: ${HEADERS}
+ ${CXX} ${CFLAGS} ${CPPFLAGS} -c -o $@ $<
+
+.cc.o64: ${HEADERS}
+ ${CXX} ${CFLAGS} ${CPPFLAGS} -fPIC -c -o $@ $<
+
+.c.o64: ${HEADERS}
+ ${CC} ${CFLAGS} ${CPPFLAGS} --std=gnu99 -fPIC -c -o $@ $<
+
+.cc.o32: ${HEADERS}
+ ${CXX} ${CFLAGS} ${CPPFLAGS} -m32 -fPIC -c -o $@ $<
+
+.c.o32: ${HEADERS}
+ ${CC} ${CFLAGS} ${CPPFLAGS} -m32 --std=gnu99 -fPIC -c -o $@ $<
diff --git a/sandbox/linux/seccomp/access.cc b/sandbox/linux/seccomp/access.cc
index 50e94bb..a318e92 100644
--- a/sandbox/linux/seccomp/access.cc
+++ b/sandbox/linux/seccomp/access.cc
@@ -7,7 +7,7 @@
namespace playground {
-int Sandbox::sandbox_access(const char *pathname, int mode) {
+long Sandbox::sandbox_access(const char *pathname, int mode) {
long long tm;
Debug::syscall(&tm, __NR_access, "Executing handler");
size_t len = strlen(pathname);
@@ -32,7 +32,7 @@ int Sandbox::sandbox_access(const char *pathname, int mode) {
die("Failed to forward access() request [sandbox]");
}
Debug::elapsed(tm, __NR_access);
- return static_cast<int>(rc);
+ return rc;
}
bool Sandbox::process_access(int parentMapsFd, int sandboxFd, int threadFdPub,
diff --git a/sandbox/linux/seccomp/clone.cc b/sandbox/linux/seccomp/clone.cc
index 0bf91c1..957ae2c 100644
--- a/sandbox/linux/seccomp/clone.cc
+++ b/sandbox/linux/seccomp/clone.cc
@@ -7,8 +7,8 @@
namespace playground {
-int Sandbox::sandbox_clone(int flags, char* stack, int* pid, int* ctid,
- void* tls, void *wrapper_sp) {
+long Sandbox::sandbox_clone(int flags, char* stack, int* pid, int* ctid,
+ void* tls, void *wrapper_sp) {
long long tm;
Debug::syscall(&tm, __NR_clone, "Executing handler");
struct {
@@ -97,7 +97,7 @@ int Sandbox::sandbox_clone(int flags, char* stack, int* pid, int* ctid,
}
}
Debug::elapsed(tm, __NR_clone);
- return static_cast<int>(rc);
+ return rc;
}
bool Sandbox::process_clone(int parentMapsFd, int sandboxFd, int threadFdPub,
diff --git a/sandbox/linux/seccomp/exit.cc b/sandbox/linux/seccomp/exit.cc
index 5da9f97..f4db643 100644
--- a/sandbox/linux/seccomp/exit.cc
+++ b/sandbox/linux/seccomp/exit.cc
@@ -7,7 +7,7 @@
namespace playground {
-int Sandbox::sandbox_exit(int status) {
+long Sandbox::sandbox_exit(int status) {
long long tm;
Debug::syscall(&tm, __NR_exit, "Executing handler");
struct {
diff --git a/sandbox/linux/seccomp/getpid.cc b/sandbox/linux/seccomp/getpid.cc
index 5b4239b..be5449b 100644
--- a/sandbox/linux/seccomp/getpid.cc
+++ b/sandbox/linux/seccomp/getpid.cc
@@ -7,7 +7,7 @@
namespace playground {
-int Sandbox::sandbox_getpid() {
+long Sandbox::sandbox_getpid() {
long long tm;
Debug::syscall(&tm, __NR_getpid, "Executing handler");
Debug::elapsed(tm, __NR_getpid);
diff --git a/sandbox/linux/seccomp/gettid.cc b/sandbox/linux/seccomp/gettid.cc
index 1423383..699774a 100644
--- a/sandbox/linux/seccomp/gettid.cc
+++ b/sandbox/linux/seccomp/gettid.cc
@@ -7,7 +7,7 @@
namespace playground {
-int Sandbox::sandbox_gettid() {
+long Sandbox::sandbox_gettid() {
long long tm;
Debug::syscall(&tm, __NR_gettid, "Executing handler");
pid_t t = tid();
diff --git a/sandbox/linux/seccomp/ioctl.cc b/sandbox/linux/seccomp/ioctl.cc
index 75330e1..07f1aa3 100644
--- a/sandbox/linux/seccomp/ioctl.cc
+++ b/sandbox/linux/seccomp/ioctl.cc
@@ -7,7 +7,7 @@
namespace playground {
-int Sandbox::sandbox_ioctl(int d, int req, void *arg) {
+long Sandbox::sandbox_ioctl(int d, int req, void *arg) {
long long tm;
Debug::syscall(&tm, __NR_ioctl, "Executing handler");
struct {
@@ -29,7 +29,7 @@ int Sandbox::sandbox_ioctl(int d, int req, void *arg) {
die("Failed to forward ioctl() request [sandbox]");
}
Debug::elapsed(tm, __NR_ioctl);
- return static_cast<int>(rc);
+ return rc;
}
bool Sandbox::process_ioctl(int parentMapsFd, int sandboxFd, int threadFdPub,
diff --git a/sandbox/linux/seccomp/ipc.cc b/sandbox/linux/seccomp/ipc.cc
index 3cfcbf0..67a4e34 100644
--- a/sandbox/linux/seccomp/ipc.cc
+++ b/sandbox/linux/seccomp/ipc.cc
@@ -44,7 +44,7 @@ void* Sandbox::sandbox_shmat(int shmid, const void* shmaddr, int shmflg) {
return reinterpret_cast<void *>(rc);
}
-int Sandbox::sandbox_shmctl(int shmid, int cmd, void* buf) {
+long Sandbox::sandbox_shmctl(int shmid, int cmd, void* buf) {
long long tm;
Debug::syscall(&tm, __NR_shmctl, "Executing handler");
@@ -67,10 +67,10 @@ int Sandbox::sandbox_shmctl(int shmid, int cmd, void* buf) {
die("Failed to forward shmctl() request [sandbox]");
}
Debug::elapsed(tm, __NR_shmctl);
- return static_cast<int>(rc);
+ return rc;
}
-int Sandbox::sandbox_shmdt(const void* shmaddr) {
+long Sandbox::sandbox_shmdt(const void* shmaddr) {
long long tm;
Debug::syscall(&tm, __NR_shmdt, "Executing handler");
@@ -91,10 +91,10 @@ int Sandbox::sandbox_shmdt(const void* shmaddr) {
die("Failed to forward shmdt() request [sandbox]");
}
Debug::elapsed(tm, __NR_shmdt);
- return static_cast<int>(rc);
+ return rc;
}
-int Sandbox::sandbox_shmget(int key, size_t size, int shmflg) {
+long Sandbox::sandbox_shmget(int key, size_t size, int shmflg) {
long long tm;
Debug::syscall(&tm, __NR_shmget, "Executing handler");
@@ -117,7 +117,7 @@ int Sandbox::sandbox_shmget(int key, size_t size, int shmflg) {
die("Failed to forward shmget() request [sandbox]");
}
Debug::elapsed(tm, __NR_shmget);
- return static_cast<int>(rc);
+ return rc;
}
bool Sandbox::process_shmat(int parentMapsFd, int sandboxFd, int threadFdPub,
@@ -246,7 +246,7 @@ bool Sandbox::process_shmget(int parentMapsFd, int sandboxFd, int threadFdPub,
#define SHMCTL 24
#endif
-int Sandbox::sandbox_ipc(unsigned call, int first, int second, int third,
+long Sandbox::sandbox_ipc(unsigned call, int first, int second, int third,
void* ptr, long fifth) {
long long tm;
Debug::syscall(&tm, __NR_ipc, "Executing handler", call);
@@ -272,7 +272,7 @@ int Sandbox::sandbox_ipc(unsigned call, int first, int second, int third,
die("Failed to forward ipc() request [sandbox]");
}
Debug::elapsed(tm, __NR_ipc, call);
- return static_cast<int>(rc);
+ return rc;
}
bool Sandbox::process_ipc(int parentMapsFd, int sandboxFd, int threadFdPub,
diff --git a/sandbox/linux/seccomp/madvise.cc b/sandbox/linux/seccomp/madvise.cc
index 0df3be8..70c594f 100644
--- a/sandbox/linux/seccomp/madvise.cc
+++ b/sandbox/linux/seccomp/madvise.cc
@@ -7,7 +7,7 @@
namespace playground {
-int Sandbox::sandbox_madvise(void* start, size_t length, int advice) {
+long Sandbox::sandbox_madvise(void* start, size_t length, int advice) {
long long tm;
Debug::syscall(&tm, __NR_madvise, "Executing handler");
struct {
@@ -29,7 +29,7 @@ int Sandbox::sandbox_madvise(void* start, size_t length, int advice) {
die("Failed to forward madvise() request [sandbox]");
}
Debug::elapsed(tm, __NR_madvise);
- return static_cast<int>(rc);
+ return rc;
}
bool Sandbox::process_madvise(int parentMapsFd, int sandboxFd, int threadFdPub,
diff --git a/sandbox/linux/seccomp/mprotect.cc b/sandbox/linux/seccomp/mprotect.cc
index d079104..548199d 100644
--- a/sandbox/linux/seccomp/mprotect.cc
+++ b/sandbox/linux/seccomp/mprotect.cc
@@ -7,7 +7,7 @@
namespace playground {
-int Sandbox::sandbox_mprotect(const void *addr, size_t len, int prot) {
+long Sandbox::sandbox_mprotect(const void *addr, size_t len, int prot) {
long long tm;
Debug::syscall(&tm, __NR_mprotect, "Executing handler");
struct {
@@ -29,7 +29,7 @@ int Sandbox::sandbox_mprotect(const void *addr, size_t len, int prot) {
die("Failed to forward mprotect() request [sandbox]");
}
Debug::elapsed(tm, __NR_mprotect);
- return static_cast<int>(rc);
+ return rc;
}
bool Sandbox::process_mprotect(int parentMapsFd, int sandboxFd,
diff --git a/sandbox/linux/seccomp/munmap.cc b/sandbox/linux/seccomp/munmap.cc
index 0c1a41c..dde7c7a 100644
--- a/sandbox/linux/seccomp/munmap.cc
+++ b/sandbox/linux/seccomp/munmap.cc
@@ -7,7 +7,7 @@
namespace playground {
-int Sandbox::sandbox_munmap(void* start, size_t length) {
+long Sandbox::sandbox_munmap(void* start, size_t length) {
long long tm;
Debug::syscall(&tm, __NR_munmap, "Executing handler");
struct {
@@ -28,7 +28,7 @@ int Sandbox::sandbox_munmap(void* start, size_t length) {
die("Failed to forward munmap() request [sandbox]");
}
Debug::elapsed(tm, __NR_munmap);
- return static_cast<int>(rc);
+ return rc;
}
bool Sandbox::process_munmap(int parentMapsFd, int sandboxFd, int threadFdPub,
diff --git a/sandbox/linux/seccomp/open.cc b/sandbox/linux/seccomp/open.cc
index 83db243..73263d1 100644
--- a/sandbox/linux/seccomp/open.cc
+++ b/sandbox/linux/seccomp/open.cc
@@ -7,7 +7,7 @@
namespace playground {
-int Sandbox::sandbox_open(const char *pathname, int flags, mode_t mode) {
+long Sandbox::sandbox_open(const char *pathname, int flags, mode_t mode) {
long long tm;
Debug::syscall(&tm, __NR_open, "Executing handler");
size_t len = strlen(pathname);
@@ -33,7 +33,7 @@ int Sandbox::sandbox_open(const char *pathname, int flags, mode_t mode) {
die("Failed to forward open() request [sandbox]");
}
Debug::elapsed(tm, __NR_open);
- return static_cast<int>(rc);
+ return rc;
}
bool Sandbox::process_open(int parentMapsFd, int sandboxFd, int threadFdPub,
diff --git a/sandbox/linux/seccomp/sandbox_impl.h b/sandbox/linux/seccomp/sandbox_impl.h
index 36f01c8..38a1803 100644
--- a/sandbox/linux/seccomp/sandbox_impl.h
+++ b/sandbox/linux/seccomp/sandbox_impl.h
@@ -84,8 +84,8 @@ class Sandbox {
// Clone() is special as it has a wrapper in syscall_table.c. The wrapper
// adds one extra argument (the pointer to the saved registers) and then
// calls playground$sandbox__clone().
- static int sandbox_clone(int flags, char* stack, int* pid, int* ctid,
- void* tls, void* wrapper_sp)
+ static long sandbox_clone(int flags, char* stack, int* pid, int* ctid,
+ void* tls, void* wrapper_sp)
asm("playground$sandbox__clone")
#if defined(__x86_64__)
__attribute__((visibility("internal")))
@@ -96,42 +96,42 @@ class Sandbox {
#define bool int
#define SecureMemArgs void
// This is the wrapper entry point that is found in the syscall_table.
- int sandbox_clone(int flags, char* stack, int* pid, int* ctid, void* tls)
+ long sandbox_clone(int flags, char* stack, int* pid, int* ctid, void* tls)
asm("playground$sandbox_clone");
#endif
// Entry points for sandboxed code that is attempting to make system calls
- STATIC int sandbox_access(const char*, int)
+ STATIC long sandbox_access(const char*, int)
asm("playground$sandbox_access");
- STATIC int sandbox_exit(int status) asm("playground$sandbox_exit");
- STATIC int sandbox_getpid() asm("playground$sandbox_getpid");
+ STATIC long sandbox_exit(int status) asm("playground$sandbox_exit");
+ STATIC long sandbox_getpid() asm("playground$sandbox_getpid");
#if defined(__NR_getsockopt)
- STATIC int sandbox_getsockopt(int, int, int, void*, socklen_t*)
+ STATIC long sandbox_getsockopt(int, int, int, void*, socklen_t*)
asm("playground$sandbox_getsockopt");
#endif
- STATIC int sandbox_gettid() asm("playground$sandbox_gettid");
- STATIC int sandbox_ioctl(int d, int req, void* arg)
+ STATIC long sandbox_gettid() asm("playground$sandbox_gettid");
+ STATIC long sandbox_ioctl(int d, int req, void* arg)
asm("playground$sandbox_ioctl");
#if defined(__NR_ipc)
- STATIC int sandbox_ipc(unsigned, int, int, int, void*, long)
+ STATIC long sandbox_ipc(unsigned, int, int, int, void*, long)
asm("playground$sandbox_ipc");
#endif
- STATIC int sandbox_lstat(const char* path, void* buf)
+ STATIC long sandbox_lstat(const char* path, void* buf)
asm("playground$sandbox_lstat");
#if defined(__NR_lstat64)
- STATIC int sandbox_lstat64(const char *path, void* b)
+ STATIC long sandbox_lstat64(const char *path, void* b)
asm("playground$sandbox_lstat64");
#endif
- STATIC int sandbox_madvise(void*, size_t, int)
+ STATIC long sandbox_madvise(void*, size_t, int)
asm("playground$sandbox_madvise");
STATIC void *sandbox_mmap(void* start, size_t length, int prot, int flags,
int fd, off_t offset)
asm("playground$sandbox_mmap");
- STATIC int sandbox_mprotect(const void*, size_t, int)
+ STATIC long sandbox_mprotect(const void*, size_t, int)
asm("playground$sandbox_mprotect");
- STATIC int sandbox_munmap(void* start, size_t length)
+ STATIC long sandbox_munmap(void* start, size_t length)
asm("playground$sandbox_munmap");
- STATIC int sandbox_open(const char*, int, mode_t)
+ STATIC long sandbox_open(const char*, int, mode_t)
asm("playground$sandbox_open");
#if defined(__NR_recvfrom)
STATIC ssize_t sandbox_recvfrom(int, void*, size_t, int, void*, socklen_t*)
@@ -140,7 +140,7 @@ class Sandbox {
asm("playground$sandbox_recvmsg");
#endif
#if defined(__NR_rt_sigprocmask)
- STATIC int sandbox_rt_sigprocmask(int how, const void*, void*, size_t)
+ STATIC long sandbox_rt_sigprocmask(int how, const void*, void*, size_t)
asm("playground$sandbox_rt_sigprocmask");
#endif
#if defined(__NR_sendmsg)
@@ -152,28 +152,28 @@ class Sandbox {
#if defined(__NR_shmat)
STATIC void* sandbox_shmat(int, const void*, int)
asm("playground$sandbox_shmat");
- STATIC int sandbox_shmctl(int, int, void*)
+ STATIC long sandbox_shmctl(int, int, void*)
asm("playground$sandbox_shmctl");
- STATIC int sandbox_shmdt(const void*) asm("playground$sandbox_shmdt");
- STATIC int sandbox_shmget(int, size_t, int)
+ STATIC long sandbox_shmdt(const void*) asm("playground$sandbox_shmdt");
+ STATIC long sandbox_shmget(int, size_t, int)
asm("playground$sandbox_shmget");
#endif
#if defined(__NR_setsockopt)
- STATIC int sandbox_setsockopt(int, int, int, const void*, socklen_t)
+ STATIC long sandbox_setsockopt(int, int, int, const void*, socklen_t)
asm("playground$sandbox_setsockopt");
#endif
#if defined(__NR_sigprocmask)
- STATIC int sandbox_sigprocmask(int how, const void*, void*)
+ STATIC long sandbox_sigprocmask(int how, const void*, void*)
asm("playground$sandbox_sigprocmask");
#endif
#if defined(__NR_socketcall)
- STATIC int sandbox_socketcall(int call, void* args)
+ STATIC long sandbox_socketcall(int call, void* args)
asm("playground$sandbox_socketcall");
#endif
- STATIC int sandbox_stat(const char* path, void* buf)
+ STATIC long sandbox_stat(const char* path, void* buf)
asm("playground$sandbox_stat");
#if defined(__NR_stat64)
- STATIC int sandbox_stat64(const char *path, void* b)
+ STATIC long sandbox_stat64(const char *path, void* b)
asm("playground$sandbox_stat64");
#endif
diff --git a/sandbox/linux/seccomp/sigprocmask.cc b/sandbox/linux/seccomp/sigprocmask.cc
index f3ad1fb..9ff2922 100644
--- a/sandbox/linux/seccomp/sigprocmask.cc
+++ b/sandbox/linux/seccomp/sigprocmask.cc
@@ -13,7 +13,7 @@ namespace playground {
// we really need this. Masking of synchronous signals is rarely necessary.
#if defined(__NR_sigprocmask)
-int Sandbox::sandbox_sigprocmask(int how, const void* set, void* old_set) {
+long Sandbox::sandbox_sigprocmask(int how, const void* set, void* old_set) {
long long tm;
Debug::syscall(&tm, __NR_sigprocmask, "Executing handler");
@@ -57,13 +57,13 @@ int Sandbox::sandbox_sigprocmask(int how, const void* set, void* old_set) {
Debug::elapsed(tm, __NR_sigprocmask);
- return (int)res;
+ return res;
}
#endif
#if defined(__NR_rt_sigprocmask)
-int Sandbox::sandbox_rt_sigprocmask(int how, const void* set, void* old_set,
- size_t bytes) {
+long Sandbox::sandbox_rt_sigprocmask(int how, const void* set, void* old_set,
+ size_t bytes) {
long long tm;
Debug::syscall(&tm, __NR_rt_sigprocmask, "Executing handler");
@@ -113,7 +113,7 @@ int Sandbox::sandbox_rt_sigprocmask(int how, const void* set, void* old_set,
Debug::elapsed(tm, __NR_rt_sigprocmask);
- return (int)res;
+ return res;
}
#endif
diff --git a/sandbox/linux/seccomp/socketcall.cc b/sandbox/linux/seccomp/socketcall.cc
index 497e5e2..c7b2015 100644
--- a/sandbox/linux/seccomp/socketcall.cc
+++ b/sandbox/linux/seccomp/socketcall.cc
@@ -50,7 +50,7 @@ ssize_t Sandbox::sandbox_recvfrom(int sockfd, void* buf, size_t len, int flags,
die("Failed to forward recvfrom() request [sandbox]");
}
Debug::elapsed(tm, __NR_recvfrom);
- return static_cast<int>(rc);
+ return static_cast<ssize_t>(rc);
}
ssize_t Sandbox::sandbox_recvmsg(int sockfd, struct msghdr* msg, int flags) {
@@ -78,7 +78,7 @@ ssize_t Sandbox::sandbox_recvmsg(int sockfd, struct msghdr* msg, int flags) {
die("Failed to forward recvmsg() request [sandbox]");
}
Debug::elapsed(tm, __NR_recvmsg);
- return static_cast<int>(rc);
+ return static_cast<ssize_t>(rc);
}
size_t Sandbox::sandbox_sendmsg(int sockfd, const struct msghdr* msg,
@@ -119,7 +119,7 @@ size_t Sandbox::sandbox_sendmsg(int sockfd, const struct msghdr* msg,
die("Failed to forward sendmsg() request [sandbox]");
}
Debug::elapsed(tm, __NR_sendmsg);
- return static_cast<int>(rc);
+ return static_cast<ssize_t>(rc);
}
ssize_t Sandbox::sandbox_sendto(int sockfd, const void* buf, size_t len,
@@ -163,11 +163,11 @@ ssize_t Sandbox::sandbox_sendto(int sockfd, const void* buf, size_t len,
die("Failed to forward sendto() request [sandbox]");
}
Debug::elapsed(tm, __NR_sendto);
- return static_cast<int>(rc);
+ return static_cast<ssize_t>(rc);
}
-int Sandbox::sandbox_setsockopt(int sockfd, int level, int optname,
- const void* optval, socklen_t optlen) {
+long Sandbox::sandbox_setsockopt(int sockfd, int level, int optname,
+ const void* optval, socklen_t optlen) {
long long tm;
Debug::syscall(&tm, __NR_setsockopt, "Executing handler");
@@ -192,11 +192,11 @@ int Sandbox::sandbox_setsockopt(int sockfd, int level, int optname,
die("Failed to forward setsockopt() request [sandbox]");
}
Debug::elapsed(tm, __NR_setsockopt);
- return static_cast<int>(rc);
+ return rc;
}
-int Sandbox::sandbox_getsockopt(int sockfd, int level, int optname,
- void* optval, socklen_t* optlen) {
+long Sandbox::sandbox_getsockopt(int sockfd, int level, int optname,
+ void* optval, socklen_t* optlen) {
long long tm;
Debug::syscall(&tm, __NR_getsockopt, "Executing handler");
@@ -221,7 +221,7 @@ int Sandbox::sandbox_getsockopt(int sockfd, int level, int optname,
die("Failed to forward getsockopt() request [sandbox]");
}
Debug::elapsed(tm, __NR_getsockopt);
- return static_cast<int>(rc);
+ return rc;
}
bool Sandbox::process_recvfrom(int parentMapsFd, int sandboxFd,
@@ -567,7 +567,7 @@ const struct Sandbox::SocketCallArgInfo Sandbox::socketCallArgInfo[] = {
#undef OFF
};
-int Sandbox::sandbox_socketcall(int call, void* args) {
+long Sandbox::sandbox_socketcall(int call, void* args) {
long long tm;
Debug::syscall(&tm, __NR_socketcall, "Executing handler", call);
@@ -730,7 +730,7 @@ int Sandbox::sandbox_socketcall(int call, void* args) {
die("Failed to forward socketcall() request [sandbox]");
}
Debug::elapsed(tm, __NR_socketcall, call);
- return static_cast<int>(rc);
+ return rc;
}
bool Sandbox::process_socketcall(int parentMapsFd, int sandboxFd,
diff --git a/sandbox/linux/seccomp/stat.cc b/sandbox/linux/seccomp/stat.cc
index 53e7e14..9277663 100644
--- a/sandbox/linux/seccomp/stat.cc
+++ b/sandbox/linux/seccomp/stat.cc
@@ -7,7 +7,7 @@
namespace playground {
-int Sandbox::sandbox_stat(const char *path, void *buf) {
+long Sandbox::sandbox_stat(const char *path, void *buf) {
long long tm;
Debug::syscall(&tm, __NR_stat, "Executing handler");
size_t len = strlen(path);
@@ -33,10 +33,10 @@ int Sandbox::sandbox_stat(const char *path, void *buf) {
die("Failed to forward stat() request [sandbox]");
}
Debug::elapsed(tm, __NR_stat);
- return static_cast<int>(rc);
+ return rc;
}
-int Sandbox::sandbox_lstat(const char *path, void *buf) {
+long Sandbox::sandbox_lstat(const char *path, void *buf) {
long long tm;
Debug::syscall(&tm, __NR_lstat, "Executing handler");
size_t len = strlen(path);
@@ -62,11 +62,11 @@ int Sandbox::sandbox_lstat(const char *path, void *buf) {
die("Failed to forward lstat() request [sandbox]");
}
Debug::elapsed(tm, __NR_lstat);
- return static_cast<int>(rc);
+ return rc;
}
#if defined(__NR_stat64)
-int Sandbox::sandbox_stat64(const char *path, void *buf) {
+long Sandbox::sandbox_stat64(const char *path, void *buf) {
long long tm;
Debug::syscall(&tm, __NR_stat64, "Executing handler");
size_t len = strlen(path);
@@ -92,10 +92,10 @@ int Sandbox::sandbox_stat64(const char *path, void *buf) {
die("Failed to forward stat64() request [sandbox]");
}
Debug::elapsed(tm, __NR_stat64);
- return static_cast<int>(rc);
+ return rc;
}
-int Sandbox::sandbox_lstat64(const char *path, void *buf) {
+long Sandbox::sandbox_lstat64(const char *path, void *buf) {
long long tm;
Debug::syscall(&tm, __NR_lstat64, "Executing handler");
size_t len = strlen(path);
@@ -121,7 +121,7 @@ int Sandbox::sandbox_lstat64(const char *path, void *buf) {
die("Failed to forward lstat64() request [sandbox]");
}
Debug::elapsed(tm, __NR_lstat64);
- return static_cast<int>(rc);
+ return rc;
}
#endif
diff --git a/sandbox/linux/seccomp/tests/list_tests.py b/sandbox/linux/seccomp/tests/list_tests.py
new file mode 100644
index 0000000..011a52e
--- /dev/null
+++ b/sandbox/linux/seccomp/tests/list_tests.py
@@ -0,0 +1,22 @@
+# Copyright (c) 2010 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import re
+import sys
+
+
+def get_tests(filename):
+ for line in open(filename):
+ match = re.match(r"TEST\((\w+)\)", line)
+ if match is not None:
+ yield match.group(1)
+
+
+def main(args):
+ for name in get_tests(args[0]):
+ print ' { "%s", %s },' % (name, name)
+
+
+if __name__ == "__main__":
+ main(sys.argv[1:])
diff --git a/sandbox/linux/seccomp/tests/test_syscalls.cc b/sandbox/linux/seccomp/tests/test_syscalls.cc
new file mode 100644
index 0000000..917ffa5
--- /dev/null
+++ b/sandbox/linux/seccomp/tests/test_syscalls.cc
@@ -0,0 +1,273 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <assert.h>
+#include <pthread.h>
+#include <pty.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "sandbox_impl.h"
+
+
+// This is basically a marker to grep for.
+#define TEST(name) void name()
+
+void *thread_func(void *x) {
+ int *ptr = (int *) x;
+ *ptr = 123;
+ printf("In new thread\n");
+ return (void *) 456;
+}
+
+TEST(test_thread) {
+ StartSeccompSandbox();
+ pthread_t tid;
+ int x;
+ 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);
+}
+
+int clone_func(void *x) {
+ printf("In thread func, which shouldn't happen\n");
+ return 1;
+}
+
+TEST(test_clone_disallowed_flags) {
+ StartSeccompSandbox();
+ int stack_size = 4096;
+ char *stack = (char *) malloc(stack_size);
+ assert(stack != NULL);
+ /* We omit the flags CLONE_SETTLS, CLONE_PARENT_SETTID and
+ 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);
+ assert(rc == -1);
+ assert(errno == EPERM);
+}
+
+long long read_tsc() {
+ long long rc;
+ asm volatile(
+ "rdtsc\n"
+ "mov %%eax, (%0)\n"
+ "mov %%edx, 4(%0)\n"
+ :
+ : "c"(&rc), "a"(-1), "d"(-1));
+ return rc;
+}
+
+TEST(test_rdtsc) {
+ StartSeccompSandbox();
+ // Just check that we can do the instruction.
+ read_tsc();
+}
+
+TEST(test_getpid) {
+ int pid1 = getpid();
+ StartSeccompSandbox();
+ int pid2 = getpid();
+ assert(pid1 == pid2);
+ // Bypass any caching that glibc's getpid() wrapper might do.
+ int pid3 = syscall(__NR_getpid);
+ assert(pid1 == pid3);
+}
+
+TEST(test_gettid) {
+ // glibc doesn't provide a gettid() wrapper.
+ int tid1 = syscall(__NR_gettid);
+ assert(tid1 > 0);
+ StartSeccompSandbox();
+ int tid2 = syscall(__NR_gettid);
+ assert(tid1 == tid2);
+}
+
+void *map_something() {
+ void *addr = mmap(NULL, 0x1000, PROT_READ,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ assert(addr != MAP_FAILED);
+ return addr;
+}
+
+TEST(test_mmap_disallows_remapping) {
+ void *addr = map_something();
+ StartSeccompSandbox();
+ // Overwriting a mapping that was created before the sandbox was
+ // enabled is not allowed.
+ void *result = mmap(addr, 0x1000, PROT_READ,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
+ assert(result == MAP_FAILED);
+ assert(errno == EINVAL);
+}
+
+TEST(test_mmap_disallows_low_address) {
+ StartSeccompSandbox();
+ // Mapping pages at low addresses is not allowed because this helps
+ // with exploiting buggy kernels.
+ void *result = mmap(NULL, 0x1000, PROT_READ,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
+ assert(result == MAP_FAILED);
+ assert(errno == EINVAL);
+}
+
+TEST(test_munmap_allowed) {
+ StartSeccompSandbox();
+ void *addr = map_something();
+ int result = munmap(addr, 0x1000);
+ assert(result == 0);
+}
+
+TEST(test_munmap_disallowed) {
+ void *addr = map_something();
+ StartSeccompSandbox();
+ int result = munmap(addr, 0x1000);
+ assert(result == -1);
+ assert(errno == EINVAL);
+}
+
+TEST(test_mprotect_allowed) {
+ StartSeccompSandbox();
+ void *addr = map_something();
+ int result = mprotect(addr, 0x1000, PROT_READ | PROT_WRITE);
+ assert(result == 0);
+}
+
+TEST(test_mprotect_disallowed) {
+ void *addr = map_something();
+ StartSeccompSandbox();
+ int result = mprotect(addr, 0x1000, PROT_READ | PROT_WRITE);
+ assert(result == -1);
+ assert(errno == EINVAL);
+}
+
+int get_tty_fd() {
+ int master_fd, tty_fd;
+ int rc = openpty(&master_fd, &tty_fd, NULL, NULL, NULL);
+ assert(rc == 0);
+ return tty_fd;
+}
+
+TEST(test_ioctl_tiocgwinsz_allowed) {
+ int tty_fd = get_tty_fd();
+ StartSeccompSandbox();
+ int size[2];
+ // Get terminal width and height.
+ int result = ioctl(tty_fd, TIOCGWINSZ, size);
+ assert(result == 0);
+}
+
+TEST(test_ioctl_disallowed) {
+ int tty_fd = get_tty_fd();
+ StartSeccompSandbox();
+ // This ioctl call inserts a character into the tty's input queue,
+ // which provides a way to send commands to an interactive shell.
+ char c = 'x';
+ int result = ioctl(tty_fd, TIOCSTI, &c);
+ assert(result == -1);
+ assert(errno == EINVAL);
+}
+
+TEST(test_socket) {
+ StartSeccompSandbox();
+ int fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ assert(fd == -1);
+ // TODO: Make it consistent between i386 and x86-64.
+ assert(errno == EINVAL || errno == ENOSYS);
+}
+
+TEST(test_open) {
+ StartSeccompSandbox();
+ int fd = open("/dev/null", O_RDONLY);
+ assert(fd >= 0);
+ int rc = close(fd);
+ assert(rc == 0);
+ fd = open("/dev/null", O_WRONLY);
+ assert(fd == -1);
+ assert(errno == EACCES);
+}
+
+TEST(test_access) {
+ StartSeccompSandbox();
+ int rc = access("/dev/null", R_OK);
+ assert(rc == 0);
+ rc = access("path-that-does-not-exist", R_OK);
+ assert(rc == -1);
+ assert(errno == ENOENT);
+}
+
+TEST(test_stat) {
+ StartSeccompSandbox();
+ struct stat st;
+ // All file accesses are denied. TODO: Update if the sandbox gets a more
+ // fine-grained policy
+ int rc = stat("/dev/null", &st);
+ assert(rc == -1);
+ rc = stat("path-that-does-not-exist", &st);
+ assert(rc == -1);
+ assert(errno == EACCES);
+}
+
+
+struct testcase {
+ const char *test_name;
+ void (*test_func)();
+};
+
+struct testcase all_tests[] = {
+#include "test-list.h"
+ { NULL, NULL },
+};
+
+void run_test_forked(struct testcase *test) {
+ printf("** %s\n", test->test_name);
+ int pid = fork();
+ if (pid == 0) {
+ test->test_func();
+ _exit(0);
+ }
+ int status;
+ waitpid(pid, &status, 0);
+ if (status != 0) {
+ printf("Test failed with exit status %i\n", status);
+ exit(1);
+ }
+}
+
+int run_test_by_name(const char *name) {
+ struct testcase *test;
+ for (test = all_tests; test->test_name != NULL; test++) {
+ if (strcmp(name, test->test_name) == 0) {
+ test->test_func();
+ return 0;
+ }
+ }
+ fprintf(stderr, "Test '%s' not found\n", name);
+ return 1;
+}
+
+int main(int argc, char **argv) {
+ if (argc == 2) {
+ // Run one test without forking, to aid debugging.
+ return run_test_by_name(argv[1]);
+ }
+ else if (argc > 2) {
+ // TODO: run multiple tests.
+ fprintf(stderr, "Too many arguments\n");
+ return 1;
+ }
+ else {
+ // Run all tests.
+ struct testcase *test;
+ for (test = all_tests; test->test_name != NULL; test++) {
+ run_test_forked(test);
+ }
+ }
+ return 0;
+}