summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhamaji@chromium.org <hamaji@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-17 01:55:08 +0000
committerhamaji@chromium.org <hamaji@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-17 01:55:08 +0000
commitf918ba5c07ebdee7a9b3cfa3f30c13f8bb88dce8 (patch)
tree4cb0e4a24cf889eceec7d8fe0ed5155753c67858
parent0460b695737beaa0a7bd98bfc191a257aa5e1fda (diff)
downloadchromium_src-f918ba5c07ebdee7a9b3cfa3f30c13f8bb88dce8.zip
chromium_src-f918ba5c07ebdee7a9b3cfa3f30c13f8bb88dce8.tar.gz
chromium_src-f918ba5c07ebdee7a9b3cfa3f30c13f8bb88dce8.tar.bz2
Add seccomp sandbox for non-SFI NaCl
All syscalls except whitelisted ones will cause SIGSYS. We test the sandbox with BPF_TEST and BPF_TEST_DEATH, which appropriately fork the process so the main process of the test will never enable the sandbox. TEST=Our app works with this sandbox on i686 and ARM TEST=Build chrome and nacl_helper on i686, x86-64, and ARM TEST=./out/Release/components_unittests --gtest_filter='NaClNonSfi*' # on i686, x86-64, and ARM TEST=SFI NaCl apps still work TEST=trybots BUG=359285 Review URL: https://codereview.chromium.org/196793023 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@264383 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--components/components_tests.gyp10
-rw-r--r--components/nacl.gyp40
-rw-r--r--components/nacl/loader/nacl_helper_linux.cc3
-rw-r--r--components/nacl/loader/nonsfi/DEPS1
-rw-r--r--components/nacl/loader/nonsfi/nonsfi_sandbox.cc315
-rw-r--r--components/nacl/loader/nonsfi/nonsfi_sandbox.h39
-rw-r--r--components/nacl/loader/nonsfi/nonsfi_sandbox_sigsys_unittest.cc609
-rw-r--r--components/nacl/loader/nonsfi/nonsfi_sandbox_unittest.cc461
-rw-r--r--sandbox/linux/sandbox_linux.gypi16
-rw-r--r--sandbox/linux/sandbox_linux_test_sources.gypi5
-rw-r--r--sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc29
-rw-r--r--sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h7
-rw-r--r--sandbox/linux/seccomp-bpf/bpf_tests.h6
13 files changed, 1519 insertions, 22 deletions
diff --git a/components/components_tests.gyp b/components/components_tests.gyp
index 828c9abb..d9d3a31 100644
--- a/components/components_tests.gyp
+++ b/components/components_tests.gyp
@@ -350,6 +350,16 @@
'nacl.gyp:nacl_common',
],
}],
+ ['disable_nacl==0 and OS=="linux"', {
+ 'sources': [
+ 'nacl/loader/nonsfi/nonsfi_sandbox_unittest.cc',
+ 'nacl/loader/nonsfi/nonsfi_sandbox_sigsys_unittest.cc',
+ ],
+ 'dependencies': [
+ 'nacl.gyp:nacl_loader',
+ '../sandbox/sandbox.gyp:sandbox_linux_test_utils',
+ ],
+ }],
['OS == "mac"', {
'link_settings': {
'libraries': [
diff --git a/components/nacl.gyp b/components/nacl.gyp
index ccf9db4..fe95adf 100644
--- a/components/nacl.gyp
+++ b/components/nacl.gyp
@@ -189,15 +189,22 @@
'include_dirs': [
'..',
],
+ 'sources': [
+ 'nacl/loader/nacl_helper_linux.cc',
+ 'nacl/loader/nacl_helper_linux.h',
+ ],
'dependencies': [
- 'nacl',
- 'nacl_common',
- 'nacl_switches',
- '../components/tracing.gyp:tracing',
- '../crypto/crypto.gyp:crypto',
- '../sandbox/sandbox.gyp:libc_urandom_override',
- '../sandbox/sandbox.gyp:sandbox',
- '../ppapi/ppapi_internal.gyp:ppapi_proxy',
+ 'nacl_loader',
+ ],
+ 'cflags': ['-fPIE'],
+ 'link_settings': {
+ 'ldflags': ['-pie'],
+ },
+ }, {
+ 'target_name': 'nacl_loader',
+ 'type': 'static_library',
+ 'include_dirs': [
+ '..',
],
'ldflags!': [
# Do not pick the default ASan options from
@@ -212,8 +219,6 @@
'IN_NACL_HELPER=1',
],
'sources': [
- 'nacl/loader/nacl_helper_linux.cc',
- 'nacl/loader/nacl_helper_linux.h',
'nacl/loader/nacl_sandbox_linux.cc',
'nacl/loader/nonsfi/abi_conversion.cc',
'nacl/loader/nonsfi/abi_conversion.h',
@@ -232,6 +237,8 @@
'nacl/loader/nonsfi/irt_util.h',
'nacl/loader/nonsfi/nonsfi_main.cc',
'nacl/loader/nonsfi/nonsfi_main.h',
+ 'nacl/loader/nonsfi/nonsfi_sandbox.cc',
+ 'nacl/loader/nonsfi/nonsfi_sandbox.h',
'../ppapi/nacl_irt/plugin_main.cc',
'../ppapi/nacl_irt/plugin_main.h',
'../ppapi/nacl_irt/plugin_startup.cc',
@@ -239,6 +246,16 @@
'../ppapi/nacl_irt/ppapi_dispatcher.cc',
'../ppapi/nacl_irt/ppapi_dispatcher.h',
],
+ 'dependencies': [
+ 'nacl',
+ 'nacl_common',
+ 'nacl_switches',
+ '../components/tracing.gyp:tracing',
+ '../crypto/crypto.gyp:crypto',
+ '../sandbox/sandbox.gyp:libc_urandom_override',
+ '../sandbox/sandbox.gyp:sandbox',
+ '../ppapi/ppapi_internal.gyp:ppapi_proxy',
+ ],
'conditions': [
['toolkit_uses_gtk == 1', {
'dependencies': [
@@ -270,9 +287,6 @@
}],
],
'cflags': ['-fPIE'],
- 'link_settings': {
- 'ldflags': ['-pie'],
- },
},
],
}],
diff --git a/components/nacl/loader/nacl_helper_linux.cc b/components/nacl/loader/nacl_helper_linux.cc
index b03c885..1026feb 100644
--- a/components/nacl/loader/nacl_helper_linux.cc
+++ b/components/nacl/loader/nacl_helper_linux.cc
@@ -32,6 +32,7 @@
#include "components/nacl/common/nacl_switches.h"
#include "components/nacl/loader/nacl_listener.h"
#include "components/nacl/loader/nacl_sandbox_linux.h"
+#include "components/nacl/loader/nonsfi/nonsfi_sandbox.h"
#include "content/public/common/zygote_fork_delegate_linux.h"
#include "crypto/nss_util.h"
#include "ipc/ipc_descriptors.h"
@@ -92,7 +93,7 @@ void InitializeLayerTwoSandbox(bool uses_nonsfi_mode) {
else
LOG(FATAL) << "SUID sandbox is mandatory for non-SFI NaCl";
}
- const bool bpf_sandbox_initialized = InitializeBPFSandbox();
+ const bool bpf_sandbox_initialized = nacl::nonsfi::InitializeBPFSandbox();
if (!bpf_sandbox_initialized) {
if (can_be_no_sandbox) {
LOG(ERROR)
diff --git a/components/nacl/loader/nonsfi/DEPS b/components/nacl/loader/nonsfi/DEPS
index fa6de5d..18f97f5 100644
--- a/components/nacl/loader/nonsfi/DEPS
+++ b/components/nacl/loader/nonsfi/DEPS
@@ -1,3 +1,4 @@
include_rules = [
"+ppapi/nacl_irt",
+ "+sandbox/linux/seccomp-bpf-helpers",
]
diff --git a/components/nacl/loader/nonsfi/nonsfi_sandbox.cc b/components/nacl/loader/nonsfi/nonsfi_sandbox.cc
new file mode 100644
index 0000000..a58ba84
--- /dev/null
+++ b/components/nacl/loader/nonsfi/nonsfi_sandbox.cc
@@ -0,0 +1,315 @@
+// Copyright 2014 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 "components/nacl/loader/nonsfi/nonsfi_sandbox.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/net.h>
+#include <sys/prctl.h>
+#include <sys/ptrace.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/syscall.h>
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "build/build_config.h"
+#include "content/public/common/sandbox_init.h"
+#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
+#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
+#include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h"
+#include "sandbox/linux/seccomp-bpf/trap.h"
+#include "sandbox/linux/services/linux_syscalls.h"
+
+#if defined(__arm__) && !defined(MAP_STACK)
+// Chrome OS Daisy (ARM) build environment has old headers.
+#define MAP_STACK 0x20000
+#endif
+
+using sandbox::ErrorCode;
+using sandbox::SandboxBPF;
+
+namespace nacl {
+namespace nonsfi {
+namespace {
+
+ErrorCode RestrictFcntlCommands(SandboxBPF* sb) {
+ ErrorCode::ArgType mask_long_type;
+ if (sizeof(long) == 8) {
+ mask_long_type = ErrorCode::TP_64BIT;
+ } else if (sizeof(long) == 4) {
+ mask_long_type = ErrorCode::TP_32BIT;
+ } else {
+ NOTREACHED();
+ }
+ // We allow following cases:
+ // 1. F_SETFD + FD_CLOEXEC: libevent's epoll_init uses this.
+ // 2. F_GETFL: Used by SetNonBlocking in
+ // message_pump_libevent.cc and Channel::ChannelImpl::CreatePipe
+ // in ipc_channel_posix.cc. Note that the latter does not work
+ // with EPERM.
+ // 3. F_SETFL: Used by evutil_make_socket_nonblocking in
+ // libevent and SetNonBlocking. As the latter mix O_NONBLOCK to
+ // the return value of F_GETFL, so we need to allow O_ACCMODE in
+ // addition to O_NONBLOCK.
+ const unsigned long denied_mask = ~(O_ACCMODE | O_NONBLOCK);
+ return sb->Cond(1, ErrorCode::TP_32BIT,
+ ErrorCode::OP_EQUAL, F_SETFD,
+ sb->Cond(2, mask_long_type,
+ ErrorCode::OP_EQUAL, FD_CLOEXEC,
+ ErrorCode(ErrorCode::ERR_ALLOWED),
+ sb->Trap(sandbox::CrashSIGSYS_Handler, NULL)),
+ sb->Cond(1, ErrorCode::TP_32BIT,
+ ErrorCode::OP_EQUAL, F_GETFL,
+ ErrorCode(ErrorCode::ERR_ALLOWED),
+ sb->Cond(1, ErrorCode::TP_32BIT,
+ ErrorCode::OP_EQUAL, F_SETFL,
+ sb->Cond(2, mask_long_type,
+ ErrorCode::OP_HAS_ANY_BITS, denied_mask,
+ sb->Trap(sandbox::CrashSIGSYS_Handler, NULL),
+ ErrorCode(ErrorCode::ERR_ALLOWED)),
+ sb->Trap(sandbox::CrashSIGSYS_Handler, NULL))));
+}
+
+ErrorCode RestrictClone(SandboxBPF* sb) {
+ // We allow clone only for new thread creation.
+ return sb->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
+ CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
+ CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS |
+ CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID,
+ ErrorCode(ErrorCode::ERR_ALLOWED),
+ sb->Trap(sandbox::SIGSYSCloneFailure, NULL));
+}
+
+ErrorCode RestrictPrctl(SandboxBPF* sb) {
+ // base::PlatformThread::SetName() uses PR_SET_NAME so we return
+ // EPERM for it. Otherwise, we will raise SIGSYS.
+ return sb->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
+ PR_SET_NAME, ErrorCode(EPERM),
+ sb->Trap(sandbox::SIGSYSPrctlFailure, NULL));
+}
+
+#if defined(__i386__)
+ErrorCode RestrictSocketcall(SandboxBPF* sb) {
+ // We only allow socketpair, sendmsg, and recvmsg.
+ return sb->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
+ SYS_SOCKETPAIR,
+ ErrorCode(ErrorCode::ERR_ALLOWED),
+ sb->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
+ SYS_SENDMSG,
+ ErrorCode(ErrorCode::ERR_ALLOWED),
+ sb->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
+ SYS_RECVMSG,
+ ErrorCode(ErrorCode::ERR_ALLOWED),
+ sb->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
+ SYS_SHUTDOWN,
+ ErrorCode(ErrorCode::ERR_ALLOWED),
+ sb->Trap(sandbox::CrashSIGSYS_Handler, NULL)))));
+}
+#endif
+
+ErrorCode RestrictMemoryProtection(SandboxBPF* sb, int argno) {
+ // TODO(jln, keescook, drewry): Limit the use of mmap/mprotect by
+ // adding some features to linux kernel.
+ const uint32_t denied_mask = ~(PROT_READ | PROT_WRITE | PROT_EXEC);
+ return sb->Cond(argno, ErrorCode::TP_32BIT,
+ ErrorCode::OP_HAS_ANY_BITS,
+ denied_mask,
+ sb->Trap(sandbox::CrashSIGSYS_Handler, NULL),
+ ErrorCode(ErrorCode::ERR_ALLOWED));
+}
+
+ErrorCode RestrictMmap(SandboxBPF* sb) {
+ const uint32_t denied_flag_mask = ~(MAP_SHARED | MAP_PRIVATE |
+ MAP_ANONYMOUS | MAP_STACK | MAP_FIXED);
+ // TODO(hamaji): Disallow RWX mmap.
+ return sb->Cond(3, ErrorCode::TP_32BIT,
+ ErrorCode::OP_HAS_ANY_BITS,
+ denied_flag_mask,
+ sb->Trap(sandbox::CrashSIGSYS_Handler, NULL),
+ RestrictMemoryProtection(sb, 2));
+}
+
+ErrorCode RestrictSocketpair(SandboxBPF* sb) {
+ // Only allow AF_UNIX, PF_UNIX. Crash if anything else is seen.
+ COMPILE_ASSERT(AF_UNIX == PF_UNIX, af_unix_pf_unix_different);
+ return sb->Cond(0, ErrorCode::TP_32BIT,
+ ErrorCode::OP_EQUAL, AF_UNIX,
+ ErrorCode(ErrorCode::ERR_ALLOWED),
+ sb->Trap(sandbox::CrashSIGSYS_Handler, NULL));
+}
+
+bool IsGracefullyDenied(int sysno) {
+ switch (sysno) {
+ // third_party/libevent uses them, but we can just return -1 from
+ // them as it is just checking getuid() != geteuid() and
+ // getgid() != getegid()
+#if defined(__i386__) || defined(__arm__)
+ case __NR_getegid32:
+ case __NR_geteuid32:
+ case __NR_getgid32:
+ case __NR_getuid32:
+#elif defined(__x86_64__)
+ case __NR_getegid:
+ case __NR_geteuid:
+ case __NR_getgid:
+ case __NR_getuid:
+#endif
+ // tcmalloc calls madvise in TCMalloc_SystemRelease.
+ case __NR_madvise:
+ // EPERM instead of SIGSYS as glibc tries to open files in /proc.
+ // TODO(hamaji): Remove this when we switch to newlib.
+ case __NR_open:
+ // For RunSandboxSanityChecks().
+ case __NR_ptrace:
+ // glibc uses this for its pthread implementation. If we return
+ // EPERM for this, glibc will stop using this.
+ // TODO(hamaji): newlib does not use this. Make this SIGTRAP once
+ // we have switched to newlib.
+ case __NR_set_robust_list:
+ // This is obsolete in ARM EABI, but x86 glibc indirectly calls
+ // this in sysconf.
+#if defined(__i386__) || defined(__x86_64__)
+ case __NR_time:
+#endif
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+void RunSandboxSanityChecks() {
+ errno = 0;
+ // Make a ptrace request with an invalid PID.
+ long ptrace_ret = ptrace(PTRACE_PEEKUSER, -1 /* pid */, NULL, NULL);
+ CHECK_EQ(-1, ptrace_ret);
+ // Without the sandbox on, this ptrace call would ESRCH instead.
+ CHECK_EQ(EPERM, errno);
+}
+
+} // namespace
+
+ErrorCode NaClNonSfiBPFSandboxPolicy::EvaluateSyscall(
+ SandboxBPF* sb, int sysno) const {
+ return EvaluateSyscallImpl(sb, sysno, NULL);
+}
+
+ErrorCode NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl(
+ SandboxBPF* sb, int sysno, void*) {
+ switch (sysno) {
+ // Allowed syscalls.
+#if defined(__i386__) || defined(__arm__)
+ case __NR__llseek:
+#elif defined(__x86_64__)
+ case __NR_lseek:
+#endif
+ // NaCl runtime exposes clock_gettime and clock_getres to untrusted code.
+ case __NR_clock_getres:
+ case __NR_clock_gettime:
+ case __NR_close:
+ case __NR_dup:
+ case __NR_dup2:
+ case __NR_epoll_create:
+ case __NR_epoll_ctl:
+ case __NR_epoll_wait:
+ case __NR_exit:
+ case __NR_exit_group:
+#if defined(__i386__) || defined(__arm__)
+ case __NR_fstat64:
+#elif defined(__x86_64__)
+ case __NR_fstat:
+#endif
+ // TODO(hamaji): Allow only FUTEX_PRIVATE_FLAG.
+ case __NR_futex:
+ // TODO(hamaji): Remove the need of gettid. Currently, this is
+ // called from PlatformThread::CurrentId().
+ case __NR_gettid:
+ case __NR_gettimeofday:
+ case __NR_munmap:
+ case __NR_nanosleep:
+ // TODO(hamaji): Remove the need of pipe. Currently, this is
+ // called from base::MessagePumpLibevent::Init().
+ case __NR_pipe:
+ case __NR_pread64:
+ case __NR_pwrite64:
+ case __NR_read:
+ case __NR_restart_syscall:
+ case __NR_sched_yield:
+ // __NR_times needed as clock() is called by CommandBufferHelper, which is
+ // used by NaCl applications that use Pepper's 3D interfaces.
+ // See crbug.com/264856 for details.
+ case __NR_times:
+ case __NR_write:
+#if defined(__arm__)
+ case __ARM_NR_cacheflush:
+#endif
+ return ErrorCode(ErrorCode::ERR_ALLOWED);
+
+ case __NR_clone:
+ return RestrictClone(sb);
+
+#if defined(__x86_64__)
+ case __NR_fcntl:
+#endif
+#if defined(__i386__) || defined(__arm__)
+ case __NR_fcntl64:
+#endif
+ return RestrictFcntlCommands(sb);
+
+#if defined(__x86_64__)
+ case __NR_mmap:
+#endif
+#if defined(__i386__) || defined(__arm__)
+ case __NR_mmap2:
+#endif
+ return RestrictMmap(sb);
+ case __NR_mprotect:
+ return RestrictMemoryProtection(sb, 2);
+
+ case __NR_prctl:
+ return RestrictPrctl(sb);
+
+#if defined(__i386__)
+ case __NR_socketcall:
+ return RestrictSocketcall(sb);
+#endif
+#if defined(__x86_64__) || defined(__arm__)
+ case __NR_recvmsg:
+ case __NR_sendmsg:
+ case __NR_shutdown:
+ return ErrorCode(ErrorCode::ERR_ALLOWED);
+ case __NR_socketpair:
+ return RestrictSocketpair(sb);
+#endif
+
+ case __NR_brk:
+ // The behavior of brk on Linux is different from other system
+ // calls. It does not return errno but the current break on
+ // failure. glibc thinks brk failed if the return value of brk
+ // is less than the requested address (i.e., brk(addr) < addr).
+ // So, glibc thinks brk succeeded if we return -EPERM and we
+ // need to return zero instead.
+ return ErrorCode(0);
+
+ default:
+ if (IsGracefullyDenied(sysno))
+ return ErrorCode(EPERM);
+ return sb->Trap(sandbox::CrashSIGSYS_Handler, NULL);
+ }
+}
+
+bool InitializeBPFSandbox() {
+ bool sandbox_is_initialized = content::InitializeSandbox(
+ scoped_ptr<sandbox::SandboxBPFPolicy>(
+ new nacl::nonsfi::NaClNonSfiBPFSandboxPolicy()));
+ if (!sandbox_is_initialized)
+ return false;
+ RunSandboxSanityChecks();
+ return true;
+}
+
+} // namespace nonsfi
+} // namespace nacl
diff --git a/components/nacl/loader/nonsfi/nonsfi_sandbox.h b/components/nacl/loader/nonsfi/nonsfi_sandbox.h
new file mode 100644
index 0000000..28e9cff
--- /dev/null
+++ b/components/nacl/loader/nonsfi/nonsfi_sandbox.h
@@ -0,0 +1,39 @@
+// Copyright 2014 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.
+
+#ifndef COMPONENTS_NACL_LOADER_NONSFI_NONSFI_SANDBOX_H_
+#define COMPONENTS_NACL_LOADER_NONSFI_NONSFI_SANDBOX_H_
+
+#include "base/basictypes.h"
+#include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h"
+
+namespace nacl {
+namespace nonsfi {
+
+// The seccomp sandbox policy for NaCl non-SFI mode. Note that this
+// policy must be as strong as possible, as non-SFI mode heavily
+// depends on seccomp sandbox.
+class NaClNonSfiBPFSandboxPolicy : public sandbox::SandboxBPFPolicy {
+ public:
+ explicit NaClNonSfiBPFSandboxPolicy() {}
+ virtual ~NaClNonSfiBPFSandboxPolicy() {}
+
+ virtual sandbox::ErrorCode EvaluateSyscall(sandbox::SandboxBPF* sb,
+ int sysno) const OVERRIDE;
+
+ static sandbox::ErrorCode EvaluateSyscallImpl(sandbox::SandboxBPF* sb,
+ int sysno, void*);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NaClNonSfiBPFSandboxPolicy);
+};
+
+// Initializes seccomp-bpf sandbox for non-SFI NaCl. Returns false on
+// failure.
+bool InitializeBPFSandbox();
+
+} // namespace nonsfi
+} // namespace nacl
+
+#endif // COMPONENTS_NACL_LOADER_NONSFI_NONSFI_SANDBOX_H_
diff --git a/components/nacl/loader/nonsfi/nonsfi_sandbox_sigsys_unittest.cc b/components/nacl/loader/nonsfi/nonsfi_sandbox_sigsys_unittest.cc
new file mode 100644
index 0000000..ad31b89
--- /dev/null
+++ b/components/nacl/loader/nonsfi/nonsfi_sandbox_sigsys_unittest.cc
@@ -0,0 +1,609 @@
+// Copyright 2014 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 "components/nacl/loader/nonsfi/nonsfi_sandbox.h"
+
+#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
+#include "sandbox/linux/seccomp-bpf/bpf_tests.h"
+
+namespace {
+
+// Test cases in this file just make sure not-whitelisted syscalls
+// are appropriately disallowed. They should raise SIGSYS regardless
+// of arguments. We always pass five zeros not to pass uninitialized
+// values to syscalls.
+#define RESTRICT_SYSCALL_DEATH_TEST_IMPL(name, sysno) \
+ BPF_DEATH_TEST( \
+ NaClNonSfiSandboxSIGSYSTest, name, \
+ DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()), \
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) { \
+ syscall(sysno, 0, 0, 0, 0, 0); \
+ }
+
+#define RESTRICT_SYSCALL_DEATH_TEST(name) \
+ RESTRICT_SYSCALL_DEATH_TEST_IMPL(name, __NR_ ## name)
+
+#define RESTRICT_ARM_SYSCALL_DEATH_TEST(name) \
+ RESTRICT_SYSCALL_DEATH_TEST_IMPL(ARM_ ## name, __ARM_NR_ ## name)
+
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(_newselect);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(_sysctl);
+#if defined(__x86_64__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(accept);
+#endif
+#if defined(__x86_64__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(accept4);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(access);
+RESTRICT_SYSCALL_DEATH_TEST(acct);
+RESTRICT_SYSCALL_DEATH_TEST(add_key);
+RESTRICT_SYSCALL_DEATH_TEST(adjtimex);
+#if defined(__i386__) || defined(__x86_64__)
+RESTRICT_SYSCALL_DEATH_TEST(afs_syscall);
+#endif
+#if defined(__i386__) || defined(__x86_64__)
+RESTRICT_SYSCALL_DEATH_TEST(alarm);
+#endif
+#if defined(__x86_64__)
+RESTRICT_SYSCALL_DEATH_TEST(arch_prctl);
+#endif
+#if defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(arm_fadvise64_64);
+#endif
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(bdflush);
+#endif
+#if defined(__x86_64__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(bind);
+#endif
+#if defined(__i386__)
+RESTRICT_SYSCALL_DEATH_TEST(break);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(capget);
+RESTRICT_SYSCALL_DEATH_TEST(capset);
+RESTRICT_SYSCALL_DEATH_TEST(chdir);
+RESTRICT_SYSCALL_DEATH_TEST(chmod);
+RESTRICT_SYSCALL_DEATH_TEST(chown);
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(chown32);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(chroot);
+RESTRICT_SYSCALL_DEATH_TEST(clock_adjtime);
+RESTRICT_SYSCALL_DEATH_TEST(clock_nanosleep);
+RESTRICT_SYSCALL_DEATH_TEST(clock_settime);
+#if defined(__x86_64__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(connect);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(creat);
+#if defined(__i386__) || defined(__x86_64__)
+RESTRICT_SYSCALL_DEATH_TEST(create_module);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(delete_module);
+RESTRICT_SYSCALL_DEATH_TEST(dup3);
+RESTRICT_SYSCALL_DEATH_TEST(epoll_create1);
+#if defined(__x86_64__)
+RESTRICT_SYSCALL_DEATH_TEST(epoll_ctl_old);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(epoll_pwait);
+#if defined(__x86_64__)
+RESTRICT_SYSCALL_DEATH_TEST(epoll_wait_old);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(eventfd);
+RESTRICT_SYSCALL_DEATH_TEST(eventfd2);
+RESTRICT_SYSCALL_DEATH_TEST(execve);
+RESTRICT_SYSCALL_DEATH_TEST(faccessat);
+#if defined(__i386__) || defined(__x86_64__)
+RESTRICT_SYSCALL_DEATH_TEST(fadvise64);
+#endif
+#if defined(__i386__)
+RESTRICT_SYSCALL_DEATH_TEST(fadvise64_64);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(fallocate);
+RESTRICT_SYSCALL_DEATH_TEST(fanotify_init);
+RESTRICT_SYSCALL_DEATH_TEST(fanotify_mark);
+RESTRICT_SYSCALL_DEATH_TEST(fchdir);
+RESTRICT_SYSCALL_DEATH_TEST(fchmod);
+RESTRICT_SYSCALL_DEATH_TEST(fchmodat);
+RESTRICT_SYSCALL_DEATH_TEST(fchown);
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(fchown32);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(fchownat);
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(fcntl);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(fdatasync);
+RESTRICT_SYSCALL_DEATH_TEST(fgetxattr);
+RESTRICT_SYSCALL_DEATH_TEST(flistxattr);
+RESTRICT_SYSCALL_DEATH_TEST(flock);
+RESTRICT_SYSCALL_DEATH_TEST(fork);
+RESTRICT_SYSCALL_DEATH_TEST(fremovexattr);
+RESTRICT_SYSCALL_DEATH_TEST(fsetxattr);
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(fstat);
+#endif
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(fstatat64);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(fstatfs);
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(fstatfs64);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(fsync);
+#if defined(__i386__)
+RESTRICT_SYSCALL_DEATH_TEST(ftime);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(ftruncate);
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(ftruncate64);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(futimesat);
+#if defined(__i386__) || defined(__x86_64__)
+RESTRICT_SYSCALL_DEATH_TEST(get_kernel_syms);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(get_mempolicy);
+RESTRICT_SYSCALL_DEATH_TEST(get_robust_list);
+#if defined(__i386__) || defined(__x86_64__)
+RESTRICT_SYSCALL_DEATH_TEST(get_thread_area);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(getcpu);
+RESTRICT_SYSCALL_DEATH_TEST(getcwd);
+RESTRICT_SYSCALL_DEATH_TEST(getdents);
+RESTRICT_SYSCALL_DEATH_TEST(getdents64);
+RESTRICT_SYSCALL_DEATH_TEST(getgroups);
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(getgroups32);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(getitimer);
+#if defined(__x86_64__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(getpeername);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(getpgid);
+RESTRICT_SYSCALL_DEATH_TEST(getpgrp);
+RESTRICT_SYSCALL_DEATH_TEST(getpid);
+#if defined(__i386__) || defined(__x86_64__)
+RESTRICT_SYSCALL_DEATH_TEST(getpmsg);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(getppid);
+RESTRICT_SYSCALL_DEATH_TEST(getpriority);
+RESTRICT_SYSCALL_DEATH_TEST(getresgid);
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(getresgid32);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(getresuid);
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(getresuid32);
+#endif
+#if defined(__i386__) || defined(__x86_64__)
+RESTRICT_SYSCALL_DEATH_TEST(getrlimit);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(getrusage);
+RESTRICT_SYSCALL_DEATH_TEST(getsid);
+#if defined(__x86_64__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(getsockname);
+#endif
+#if defined(__x86_64__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(getsockopt);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(getxattr);
+#if defined(__i386__)
+RESTRICT_SYSCALL_DEATH_TEST(gtty);
+#endif
+#if defined(__i386__)
+RESTRICT_SYSCALL_DEATH_TEST(idle);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(init_module);
+RESTRICT_SYSCALL_DEATH_TEST(inotify_add_watch);
+RESTRICT_SYSCALL_DEATH_TEST(inotify_init);
+RESTRICT_SYSCALL_DEATH_TEST(inotify_init1);
+RESTRICT_SYSCALL_DEATH_TEST(inotify_rm_watch);
+RESTRICT_SYSCALL_DEATH_TEST(io_cancel);
+RESTRICT_SYSCALL_DEATH_TEST(io_destroy);
+RESTRICT_SYSCALL_DEATH_TEST(io_getevents);
+RESTRICT_SYSCALL_DEATH_TEST(io_setup);
+RESTRICT_SYSCALL_DEATH_TEST(io_submit);
+RESTRICT_SYSCALL_DEATH_TEST(ioctl);
+#if defined(__i386__) || defined(__x86_64__)
+RESTRICT_SYSCALL_DEATH_TEST(ioperm);
+#endif
+#if defined(__i386__) || defined(__x86_64__)
+RESTRICT_SYSCALL_DEATH_TEST(iopl);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(ioprio_get);
+RESTRICT_SYSCALL_DEATH_TEST(ioprio_set);
+#if defined(__i386__)
+RESTRICT_SYSCALL_DEATH_TEST(ipc);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(kexec_load);
+RESTRICT_SYSCALL_DEATH_TEST(keyctl);
+RESTRICT_SYSCALL_DEATH_TEST(kill);
+RESTRICT_SYSCALL_DEATH_TEST(lchown);
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(lchown32);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(lgetxattr);
+RESTRICT_SYSCALL_DEATH_TEST(link);
+RESTRICT_SYSCALL_DEATH_TEST(linkat);
+#if defined(__x86_64__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(listen);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(listxattr);
+RESTRICT_SYSCALL_DEATH_TEST(llistxattr);
+#if defined(__i386__)
+RESTRICT_SYSCALL_DEATH_TEST(lock);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(lookup_dcookie);
+RESTRICT_SYSCALL_DEATH_TEST(lremovexattr);
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(lseek);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(lsetxattr);
+RESTRICT_SYSCALL_DEATH_TEST(lstat);
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(lstat64);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(mbind);
+#if defined(__i386__) || defined(__x86_64__)
+RESTRICT_SYSCALL_DEATH_TEST(migrate_pages);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(mincore);
+RESTRICT_SYSCALL_DEATH_TEST(mkdir);
+RESTRICT_SYSCALL_DEATH_TEST(mkdirat);
+RESTRICT_SYSCALL_DEATH_TEST(mknod);
+RESTRICT_SYSCALL_DEATH_TEST(mknodat);
+RESTRICT_SYSCALL_DEATH_TEST(mlock);
+RESTRICT_SYSCALL_DEATH_TEST(mlockall);
+#if defined(__i386__)
+RESTRICT_SYSCALL_DEATH_TEST(mmap);
+#endif
+#if defined(__i386__) || defined(__x86_64__)
+RESTRICT_SYSCALL_DEATH_TEST(modify_ldt);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(mount);
+RESTRICT_SYSCALL_DEATH_TEST(move_pages);
+#if defined(__i386__)
+RESTRICT_SYSCALL_DEATH_TEST(mpx);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(mq_getsetattr);
+RESTRICT_SYSCALL_DEATH_TEST(mq_notify);
+RESTRICT_SYSCALL_DEATH_TEST(mq_open);
+RESTRICT_SYSCALL_DEATH_TEST(mq_timedreceive);
+RESTRICT_SYSCALL_DEATH_TEST(mq_timedsend);
+RESTRICT_SYSCALL_DEATH_TEST(mq_unlink);
+RESTRICT_SYSCALL_DEATH_TEST(mremap);
+#if defined(__x86_64__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(msgctl);
+#endif
+#if defined(__x86_64__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(msgget);
+#endif
+#if defined(__x86_64__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(msgrcv);
+#endif
+#if defined(__x86_64__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(msgsnd);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(msync);
+RESTRICT_SYSCALL_DEATH_TEST(munlock);
+RESTRICT_SYSCALL_DEATH_TEST(munlockall);
+RESTRICT_SYSCALL_DEATH_TEST(name_to_handle_at);
+#if defined(__x86_64__)
+RESTRICT_SYSCALL_DEATH_TEST(newfstatat);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(nfsservctl);
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(nice);
+#endif
+#if defined(__i386__)
+RESTRICT_SYSCALL_DEATH_TEST(oldfstat);
+#endif
+#if defined(__i386__)
+RESTRICT_SYSCALL_DEATH_TEST(oldlstat);
+#endif
+#if defined(__i386__)
+RESTRICT_SYSCALL_DEATH_TEST(oldolduname);
+#endif
+#if defined(__i386__)
+RESTRICT_SYSCALL_DEATH_TEST(oldstat);
+#endif
+#if defined(__i386__)
+RESTRICT_SYSCALL_DEATH_TEST(olduname);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(open_by_handle_at);
+RESTRICT_SYSCALL_DEATH_TEST(openat);
+RESTRICT_SYSCALL_DEATH_TEST(pause);
+#if defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(pciconfig_iobase);
+#endif
+#if defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(pciconfig_read);
+#endif
+#if defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(pciconfig_write);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(perf_event_open);
+RESTRICT_SYSCALL_DEATH_TEST(personality);
+RESTRICT_SYSCALL_DEATH_TEST(pipe2);
+RESTRICT_SYSCALL_DEATH_TEST(pivot_root);
+RESTRICT_SYSCALL_DEATH_TEST(poll);
+RESTRICT_SYSCALL_DEATH_TEST(ppoll);
+RESTRICT_SYSCALL_DEATH_TEST(preadv);
+RESTRICT_SYSCALL_DEATH_TEST(prlimit64);
+RESTRICT_SYSCALL_DEATH_TEST(process_vm_readv);
+RESTRICT_SYSCALL_DEATH_TEST(process_vm_writev);
+#if defined(__i386__)
+RESTRICT_SYSCALL_DEATH_TEST(prof);
+#endif
+#if defined(__i386__)
+RESTRICT_SYSCALL_DEATH_TEST(profil);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(pselect6);
+#if defined(__i386__) || defined(__x86_64__)
+RESTRICT_SYSCALL_DEATH_TEST(putpmsg);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(pwritev);
+#if defined(__i386__) || defined(__x86_64__)
+RESTRICT_SYSCALL_DEATH_TEST(query_module);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(quotactl);
+RESTRICT_SYSCALL_DEATH_TEST(readahead);
+#if defined(__i386__)
+RESTRICT_SYSCALL_DEATH_TEST(readdir);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(readlink);
+RESTRICT_SYSCALL_DEATH_TEST(readlinkat);
+RESTRICT_SYSCALL_DEATH_TEST(readv);
+RESTRICT_SYSCALL_DEATH_TEST(reboot);
+#if defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(recv);
+#endif
+#if defined(__x86_64__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(recvfrom);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(recvmmsg);
+RESTRICT_SYSCALL_DEATH_TEST(remap_file_pages);
+RESTRICT_SYSCALL_DEATH_TEST(removexattr);
+RESTRICT_SYSCALL_DEATH_TEST(rename);
+RESTRICT_SYSCALL_DEATH_TEST(renameat);
+RESTRICT_SYSCALL_DEATH_TEST(request_key);
+RESTRICT_SYSCALL_DEATH_TEST(rmdir);
+RESTRICT_SYSCALL_DEATH_TEST(rt_sigaction);
+RESTRICT_SYSCALL_DEATH_TEST(rt_sigpending);
+RESTRICT_SYSCALL_DEATH_TEST(rt_sigprocmask);
+RESTRICT_SYSCALL_DEATH_TEST(rt_sigqueueinfo);
+RESTRICT_SYSCALL_DEATH_TEST(rt_sigreturn);
+RESTRICT_SYSCALL_DEATH_TEST(rt_sigsuspend);
+RESTRICT_SYSCALL_DEATH_TEST(rt_sigtimedwait);
+RESTRICT_SYSCALL_DEATH_TEST(rt_tgsigqueueinfo);
+RESTRICT_SYSCALL_DEATH_TEST(sched_get_priority_max);
+RESTRICT_SYSCALL_DEATH_TEST(sched_get_priority_min);
+RESTRICT_SYSCALL_DEATH_TEST(sched_getaffinity);
+RESTRICT_SYSCALL_DEATH_TEST(sched_getparam);
+RESTRICT_SYSCALL_DEATH_TEST(sched_getscheduler);
+RESTRICT_SYSCALL_DEATH_TEST(sched_rr_get_interval);
+RESTRICT_SYSCALL_DEATH_TEST(sched_setaffinity);
+RESTRICT_SYSCALL_DEATH_TEST(sched_setparam);
+RESTRICT_SYSCALL_DEATH_TEST(sched_setscheduler);
+#if defined(__x86_64__)
+RESTRICT_SYSCALL_DEATH_TEST(security);
+#endif
+#if defined(__i386__) || defined(__x86_64__)
+RESTRICT_SYSCALL_DEATH_TEST(select);
+#endif
+#if defined(__x86_64__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(semctl);
+#endif
+#if defined(__x86_64__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(semget);
+#endif
+#if defined(__x86_64__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(semop);
+#endif
+#if defined(__x86_64__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(semtimedop);
+#endif
+#if defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(send);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(sendfile);
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(sendfile64);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(sendmmsg);
+#if defined(__x86_64__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(sendto);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(set_mempolicy);
+#if defined(__i386__) || defined(__x86_64__)
+RESTRICT_SYSCALL_DEATH_TEST(set_thread_area);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(set_tid_address);
+RESTRICT_SYSCALL_DEATH_TEST(setdomainname);
+RESTRICT_SYSCALL_DEATH_TEST(setfsgid);
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(setfsgid32);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(setfsuid);
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(setfsuid32);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(setgid);
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(setgid32);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(setgroups);
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(setgroups32);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(sethostname);
+RESTRICT_SYSCALL_DEATH_TEST(setitimer);
+RESTRICT_SYSCALL_DEATH_TEST(setns);
+RESTRICT_SYSCALL_DEATH_TEST(setpgid);
+RESTRICT_SYSCALL_DEATH_TEST(setpriority);
+RESTRICT_SYSCALL_DEATH_TEST(setregid);
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(setregid32);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(setresgid);
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(setresgid32);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(setresuid);
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(setresuid32);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(setreuid);
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(setreuid32);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(setrlimit);
+RESTRICT_SYSCALL_DEATH_TEST(setsid);
+#if defined(__x86_64__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(setsockopt);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(settimeofday);
+RESTRICT_SYSCALL_DEATH_TEST(setuid);
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(setuid32);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(setxattr);
+#if defined(__i386__)
+RESTRICT_SYSCALL_DEATH_TEST(sgetmask);
+#endif
+#if defined(__x86_64__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(shmat);
+#endif
+#if defined(__x86_64__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(shmctl);
+#endif
+#if defined(__x86_64__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(shmdt);
+#endif
+#if defined(__x86_64__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(shmget);
+#endif
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(sigaction);
+#endif
+#if defined(__i386__)
+RESTRICT_SYSCALL_DEATH_TEST(signal);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(signalfd);
+RESTRICT_SYSCALL_DEATH_TEST(signalfd4);
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(sigpending);
+#endif
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(sigprocmask);
+#endif
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(sigreturn);
+#endif
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(sigsuspend);
+#endif
+#if defined(__x86_64__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(socket);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(splice);
+#if defined(__i386__)
+RESTRICT_SYSCALL_DEATH_TEST(ssetmask);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(stat);
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(stat64);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(statfs);
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(statfs64);
+#endif
+#if defined(__i386__)
+RESTRICT_SYSCALL_DEATH_TEST(stime);
+#endif
+#if defined(__i386__)
+RESTRICT_SYSCALL_DEATH_TEST(stty);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(swapoff);
+RESTRICT_SYSCALL_DEATH_TEST(swapon);
+RESTRICT_SYSCALL_DEATH_TEST(symlink);
+RESTRICT_SYSCALL_DEATH_TEST(symlinkat);
+RESTRICT_SYSCALL_DEATH_TEST(sync);
+#if defined(__i386__) || defined(__x86_64__)
+RESTRICT_SYSCALL_DEATH_TEST(sync_file_range);
+#endif
+#if defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(sync_file_range2);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(syncfs);
+RESTRICT_SYSCALL_DEATH_TEST(sysfs);
+RESTRICT_SYSCALL_DEATH_TEST(sysinfo);
+RESTRICT_SYSCALL_DEATH_TEST(syslog);
+RESTRICT_SYSCALL_DEATH_TEST(tee);
+RESTRICT_SYSCALL_DEATH_TEST(tgkill);
+RESTRICT_SYSCALL_DEATH_TEST(timer_create);
+RESTRICT_SYSCALL_DEATH_TEST(timer_delete);
+RESTRICT_SYSCALL_DEATH_TEST(timer_getoverrun);
+RESTRICT_SYSCALL_DEATH_TEST(timer_gettime);
+RESTRICT_SYSCALL_DEATH_TEST(timer_settime);
+RESTRICT_SYSCALL_DEATH_TEST(timerfd_create);
+RESTRICT_SYSCALL_DEATH_TEST(timerfd_gettime);
+RESTRICT_SYSCALL_DEATH_TEST(timerfd_settime);
+RESTRICT_SYSCALL_DEATH_TEST(tkill);
+RESTRICT_SYSCALL_DEATH_TEST(truncate);
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(truncate64);
+#endif
+#if defined(__x86_64__)
+RESTRICT_SYSCALL_DEATH_TEST(tuxcall);
+#endif
+#if defined(__i386__) || defined(__arm__)
+RESTRICT_SYSCALL_DEATH_TEST(ugetrlimit);
+#endif
+#if defined(__i386__)
+RESTRICT_SYSCALL_DEATH_TEST(ulimit);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(umask);
+#if defined(__i386__)
+RESTRICT_SYSCALL_DEATH_TEST(umount);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(umount2);
+RESTRICT_SYSCALL_DEATH_TEST(uname);
+RESTRICT_SYSCALL_DEATH_TEST(unlink);
+RESTRICT_SYSCALL_DEATH_TEST(unlinkat);
+RESTRICT_SYSCALL_DEATH_TEST(unshare);
+RESTRICT_SYSCALL_DEATH_TEST(uselib);
+RESTRICT_SYSCALL_DEATH_TEST(ustat);
+#if defined(__i386__) || defined(__x86_64__)
+RESTRICT_SYSCALL_DEATH_TEST(utime);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(utimensat);
+RESTRICT_SYSCALL_DEATH_TEST(utimes);
+RESTRICT_SYSCALL_DEATH_TEST(vfork);
+RESTRICT_SYSCALL_DEATH_TEST(vhangup);
+#if defined(__i386__)
+RESTRICT_SYSCALL_DEATH_TEST(vm86);
+#endif
+#if defined(__i386__)
+RESTRICT_SYSCALL_DEATH_TEST(vm86old);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(vmsplice);
+RESTRICT_SYSCALL_DEATH_TEST(vserver);
+RESTRICT_SYSCALL_DEATH_TEST(wait4);
+RESTRICT_SYSCALL_DEATH_TEST(waitid);
+#if defined(__i386__)
+RESTRICT_SYSCALL_DEATH_TEST(waitpid);
+#endif
+RESTRICT_SYSCALL_DEATH_TEST(writev);
+
+// ARM specific syscalls.
+#if defined(__arm__)
+RESTRICT_ARM_SYSCALL_DEATH_TEST(breakpoint);
+RESTRICT_ARM_SYSCALL_DEATH_TEST(usr26);
+RESTRICT_ARM_SYSCALL_DEATH_TEST(usr32);
+RESTRICT_ARM_SYSCALL_DEATH_TEST(set_tls);
+#endif
+
+} // namespace
diff --git a/components/nacl/loader/nonsfi/nonsfi_sandbox_unittest.cc b/components/nacl/loader/nonsfi/nonsfi_sandbox_unittest.cc
new file mode 100644
index 0000000..5b62ce6
--- /dev/null
+++ b/components/nacl/loader/nonsfi/nonsfi_sandbox_unittest.cc
@@ -0,0 +1,461 @@
+// Copyright 2014 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 "components/nacl/loader/nonsfi/nonsfi_sandbox.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <sched.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/prctl.h>
+#include <sys/ptrace.h>
+#include <sys/socket.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/compiler_specific.h"
+#include "base/files/scoped_file.h"
+#include "base/logging.h"
+#include "base/posix/eintr_wrapper.h"
+#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
+#include "sandbox/linux/seccomp-bpf/bpf_tests.h"
+
+namespace {
+
+void DoPipe(base::ScopedFD* fds) {
+ int tmp_fds[2];
+ BPF_ASSERT_EQ(0, pipe(tmp_fds));
+ fds[0].reset(tmp_fds[0]);
+ fds[1].reset(tmp_fds[1]);
+}
+
+void DoSocketpair(base::ScopedFD* fds) {
+ int tmp_fds[2];
+ BPF_ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, tmp_fds));
+ fds[0].reset(tmp_fds[0]);
+ fds[1].reset(tmp_fds[1]);
+}
+
+TEST(NaClNonSfiSandboxTest, BPFIsSupported) {
+ bool seccomp_bpf_supported = false;
+ // Seccomp-BPF tests die under TSAN v2. See http://crbug.com/356588
+#if !defined(THREAD_SANITIZER)
+ seccomp_bpf_supported = (
+ sandbox::SandboxBPF::SupportsSeccompSandbox(-1) ==
+ sandbox::SandboxBPF::STATUS_AVAILABLE);
+#endif
+
+ if (!seccomp_bpf_supported) {
+ LOG(ERROR) << "Seccomp BPF is not supported, these tests "
+ << "will pass without running";
+ }
+}
+
+BPF_DEATH_TEST(NaClNonSfiSandboxTest, invalid_sysno,
+ DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ syscall(999);
+}
+
+const int kExpectedValue = 123;
+
+void* SetValueInThread(void* test_val_ptr) {
+ *reinterpret_cast<int*>(test_val_ptr) = kExpectedValue;
+ return NULL;
+}
+
+BPF_TEST(NaClNonSfiSandboxTest, clone_by_pthread_create,
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ // clone call for thread creation is allowed.
+ pthread_t th;
+ int test_val = 42;
+ BPF_ASSERT_EQ(0, pthread_create(&th, NULL, &SetValueInThread, &test_val));
+ BPF_ASSERT_EQ(0, pthread_join(th, NULL));
+ BPF_ASSERT_EQ(kExpectedValue, test_val);
+}
+
+int DoFork() {
+ // Call clone() to do a fork().
+ const int pid = syscall(__NR_clone, SIGCHLD, NULL);
+ if (pid == 0)
+ _exit(0);
+ return pid;
+}
+
+// The sanity check for DoFork without the sandbox.
+TEST(NaClNonSfiSandboxTest, DoFork) {
+ const int pid = DoFork();
+ ASSERT_LT(0, pid);
+ int status;
+ ASSERT_EQ(pid, HANDLE_EINTR(waitpid(pid, &status, 0)));
+ ASSERT_TRUE(WIFEXITED(status));
+ ASSERT_EQ(0, WEXITSTATUS(status));
+}
+
+// Then, try this in the sandbox.
+BPF_DEATH_TEST(NaClNonSfiSandboxTest, clone_for_fork,
+ DEATH_MESSAGE(sandbox::GetCloneErrorMessageContentForTests()),
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ DoFork();
+}
+
+BPF_TEST(NaClNonSfiSandboxTest, prctl_SET_NAME,
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ errno = 0;
+ BPF_ASSERT_EQ(-1, syscall(__NR_prctl, PR_SET_NAME, "foo"));
+ BPF_ASSERT_EQ(EPERM, errno);
+}
+
+BPF_DEATH_TEST(NaClNonSfiSandboxTest, prctl_SET_DUMPABLE,
+ DEATH_MESSAGE(sandbox::GetPrctlErrorMessageContentForTests()),
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ syscall(__NR_prctl, PR_SET_DUMPABLE, 1UL);
+}
+
+BPF_TEST(NaClNonSfiSandboxTest, socketcall_allowed,
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ base::ScopedFD fds[2];
+ struct msghdr msg = {};
+ struct iovec iov;
+ std::string payload("foo");
+ iov.iov_base = &payload[0];
+ iov.iov_len = payload.size();
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ DoSocketpair(fds);
+ BPF_ASSERT_EQ(static_cast<int>(payload.size()),
+ HANDLE_EINTR(sendmsg(fds[1].get(), &msg, 0)));
+ BPF_ASSERT_EQ(static_cast<int>(payload.size()),
+ HANDLE_EINTR(recvmsg(fds[0].get(), &msg, 0)));
+ BPF_ASSERT_EQ(0, shutdown(fds[0].get(), SHUT_RDWR));
+}
+
+BPF_DEATH_TEST(NaClNonSfiSandboxTest, accept,
+ DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ accept(0, NULL, NULL);
+}
+
+BPF_DEATH_TEST(NaClNonSfiSandboxTest, bind,
+ DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ bind(0, NULL, 0);
+}
+
+BPF_DEATH_TEST(NaClNonSfiSandboxTest, connect,
+ DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ connect(0, NULL, 0);
+}
+
+BPF_DEATH_TEST(NaClNonSfiSandboxTest, getpeername,
+ DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ getpeername(0, NULL, NULL);
+}
+
+BPF_DEATH_TEST(NaClNonSfiSandboxTest, getsockname,
+ DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ getsockname(0, NULL, NULL);
+}
+
+BPF_DEATH_TEST(NaClNonSfiSandboxTest, getsockopt,
+ DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ getsockopt(0, 0, 0, NULL, NULL);
+}
+
+BPF_DEATH_TEST(NaClNonSfiSandboxTest, listen,
+ DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ listen(0, 0);
+}
+
+BPF_DEATH_TEST(NaClNonSfiSandboxTest, recv,
+ DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ recv(0, NULL, 0, 0);
+}
+
+BPF_DEATH_TEST(NaClNonSfiSandboxTest, recvfrom,
+ DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ recvfrom(0, NULL, 0, 0, NULL, NULL);
+}
+
+BPF_DEATH_TEST(NaClNonSfiSandboxTest, send,
+ DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ send(0, NULL, 0, 0);
+}
+
+BPF_DEATH_TEST(NaClNonSfiSandboxTest, sendto,
+ DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ sendto(0, NULL, 0, 0, NULL, 0);
+}
+
+BPF_DEATH_TEST(NaClNonSfiSandboxTest, setsockopt,
+ DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ setsockopt(0, 0, 0, NULL, 0);
+}
+
+BPF_DEATH_TEST(NaClNonSfiSandboxTest, socket,
+ DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ socket(0, 0, 0);
+}
+
+#if defined(__x86_64__) || defined(__arm__)
+BPF_DEATH_TEST(NaClNonSfiSandboxTest, socketpair,
+ DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ int fds[2];
+ socketpair(AF_INET, SOCK_STREAM, 0, fds);
+}
+#endif
+
+BPF_TEST(NaClNonSfiSandboxTest, fcntl_SETFD_allowed,
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ base::ScopedFD fds[2];
+ DoSocketpair(fds);
+ BPF_ASSERT_EQ(0, fcntl(fds[0].get(), F_SETFD, FD_CLOEXEC));
+}
+
+BPF_DEATH_TEST(NaClNonSfiSandboxTest, fcntl_SETFD,
+ DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ base::ScopedFD fds[2];
+ DoSocketpair(fds);
+ fcntl(fds[0].get(), F_SETFD, 99);
+}
+
+BPF_TEST(NaClNonSfiSandboxTest, fcntl_GETFL_SETFL_allowed,
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ base::ScopedFD fds[2];
+ DoPipe(fds);
+ const int fd = fds[0].get();
+ BPF_ASSERT_EQ(0, fcntl(fd, F_GETFL));
+ BPF_ASSERT_EQ(0, fcntl(fd, F_SETFL, O_RDWR | O_NONBLOCK));
+ BPF_ASSERT_EQ(O_NONBLOCK, fcntl(fd, F_GETFL));
+}
+
+BPF_DEATH_TEST(NaClNonSfiSandboxTest, fcntl_GETFL_SETFL,
+ DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ base::ScopedFD fds[2];
+ DoSocketpair(fds);
+ fcntl(fds[0].get(), F_SETFL, O_APPEND);
+}
+
+BPF_DEATH_TEST(NaClNonSfiSandboxTest, fcntl_DUPFD,
+ DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ fcntl(0, F_DUPFD);
+}
+
+BPF_DEATH_TEST(NaClNonSfiSandboxTest, fcntl_DUPFD_CLOEXEC,
+ DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ fcntl(0, F_DUPFD_CLOEXEC);
+}
+
+void* DoAllowedAnonymousMmap() {
+ return mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE,
+ MAP_ANONYMOUS | MAP_SHARED, -1, 0);
+}
+
+BPF_TEST(NaClNonSfiSandboxTest, mmap_allowed,
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ void* ptr = DoAllowedAnonymousMmap();
+ BPF_ASSERT_NE(MAP_FAILED, ptr);
+ BPF_ASSERT_EQ(0, munmap(ptr, getpagesize()));
+}
+
+BPF_DEATH_TEST(NaClNonSfiSandboxTest, mmap_unallowed_flag,
+ DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE,
+ MAP_ANONYMOUS | MAP_POPULATE, -1, 0);
+}
+
+BPF_DEATH_TEST(NaClNonSfiSandboxTest, mmap_unallowed_prot,
+ DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ mmap(NULL, getpagesize(), PROT_READ | PROT_GROWSDOWN,
+ MAP_ANONYMOUS, -1, 0);
+}
+
+// TODO(hamaji): Disallow RWX mmap.
+#if 0
+BPF_DEATH_TEST(NaClNonSfiSandboxTest, mmap_rwx,
+ DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_ANONYMOUS, -1, 0);
+}
+#endif
+
+BPF_TEST(NaClNonSfiSandboxTest, mprotect_allowed,
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ void* ptr = DoAllowedAnonymousMmap();
+ BPF_ASSERT_NE(MAP_FAILED, ptr);
+ BPF_ASSERT_EQ(0, mprotect(ptr, getpagesize(), PROT_READ));
+ BPF_ASSERT_EQ(0, munmap(ptr, getpagesize()));
+}
+
+BPF_DEATH_TEST(NaClNonSfiSandboxTest, mprotect_unallowed_prot,
+ DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ // We have tested DoAllowedAnonymousMmap is allowed in
+ // mmap_allowed, so we can make sure the following mprotect call
+ // kills the process.
+ void* ptr = DoAllowedAnonymousMmap();
+ BPF_ASSERT_NE(MAP_FAILED, ptr);
+ mprotect(ptr, getpagesize(), PROT_READ | PROT_GROWSDOWN);
+}
+
+BPF_TEST(NaClNonSfiSandboxTest, brk,
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ char* next_brk = static_cast<char*>(sbrk(0)) + getpagesize();
+ // The kernel interface must return zero for brk.
+ BPF_ASSERT_EQ(0, syscall(__NR_brk, next_brk));
+ // The libc wrapper translates it to ENOMEM.
+ errno = 0;
+ BPF_ASSERT_EQ(-1, brk(next_brk));
+ BPF_ASSERT_EQ(ENOMEM, errno);
+}
+
+#if defined(__i386__) || defined(__arm__)
+BPF_TEST(NaClNonSfiSandboxTest, getegid32_EPERM,
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ errno = 0;
+ BPF_ASSERT_EQ(-1, syscall(__NR_getegid32));
+ BPF_ASSERT_EQ(EPERM, errno);
+}
+
+BPF_TEST(NaClNonSfiSandboxTest, geteuid32_EPERM,
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ errno = 0;
+ BPF_ASSERT_EQ(-1, syscall(__NR_geteuid32));
+ BPF_ASSERT_EQ(EPERM, errno);
+}
+
+BPF_TEST(NaClNonSfiSandboxTest, getgid32_EPERM,
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ errno = 0;
+ BPF_ASSERT_EQ(-1, syscall(__NR_getgid32));
+ BPF_ASSERT_EQ(EPERM, errno);
+}
+
+BPF_TEST(NaClNonSfiSandboxTest, getuid32_EPERM,
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ errno = 0;
+ BPF_ASSERT_EQ(-1, syscall(__NR_getuid32));
+ BPF_ASSERT_EQ(EPERM, errno);
+}
+
+BPF_DEATH_TEST(NaClNonSfiSandboxTest, getegid_SIGSYS,
+ DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ syscall(__NR_getegid);
+}
+
+BPF_DEATH_TEST(NaClNonSfiSandboxTest, geteuid_SIGSYS,
+ DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ syscall(__NR_geteuid);
+}
+
+BPF_DEATH_TEST(NaClNonSfiSandboxTest, getgid_SIGSYS,
+ DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ syscall(__NR_getgid);
+}
+
+BPF_DEATH_TEST(NaClNonSfiSandboxTest, getuid_SIGSYS,
+ DEATH_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ syscall(__NR_getuid);
+}
+#endif
+
+#if defined(__x86_64__)
+BPF_TEST(NaClNonSfiSandboxTest, getegid_EPERM,
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ errno = 0;
+ BPF_ASSERT_EQ(-1, syscall(__NR_getegid));
+ BPF_ASSERT_EQ(EPERM, errno);
+}
+
+BPF_TEST(NaClNonSfiSandboxTest, geteuid_EPERM,
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ errno = 0;
+ BPF_ASSERT_EQ(-1, syscall(__NR_geteuid));
+ BPF_ASSERT_EQ(EPERM, errno);
+}
+
+BPF_TEST(NaClNonSfiSandboxTest, getgid_EPERM,
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ errno = 0;
+ BPF_ASSERT_EQ(-1, syscall(__NR_getgid));
+ BPF_ASSERT_EQ(EPERM, errno);
+}
+
+BPF_TEST(NaClNonSfiSandboxTest, getuid_EPERM,
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ errno = 0;
+ BPF_ASSERT_EQ(-1, syscall(__NR_getuid));
+ BPF_ASSERT_EQ(EPERM, errno);
+}
+#endif
+
+BPF_TEST(NaClNonSfiSandboxTest, madvise_EPERM,
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ errno = 0;
+ BPF_ASSERT_EQ(-1, syscall(__NR_madvise));
+ BPF_ASSERT_EQ(EPERM, errno);
+}
+
+BPF_TEST(NaClNonSfiSandboxTest, open_EPERM,
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ errno = 0;
+ BPF_ASSERT_EQ(-1, syscall(__NR_open));
+ BPF_ASSERT_EQ(EPERM, errno);
+}
+
+BPF_TEST(NaClNonSfiSandboxTest, ptrace_EPERM,
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ errno = 0;
+ BPF_ASSERT_EQ(-1, syscall(__NR_ptrace));
+ BPF_ASSERT_EQ(EPERM, errno);
+}
+
+BPF_TEST(NaClNonSfiSandboxTest, set_robust_list_EPERM,
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ errno = 0;
+ BPF_ASSERT_EQ(-1, syscall(__NR_set_robust_list));
+ BPF_ASSERT_EQ(EPERM, errno);
+}
+
+#if defined(__i386__) || defined(__x86_64__)
+BPF_TEST(NaClNonSfiSandboxTest, time_EPERM,
+ nacl::nonsfi::NaClNonSfiBPFSandboxPolicy::EvaluateSyscallImpl) {
+ errno = 0;
+ BPF_ASSERT_EQ(-1, syscall(__NR_time));
+ BPF_ASSERT_EQ(EPERM, errno);
+}
+#endif
+
+} // namespace
diff --git a/sandbox/linux/sandbox_linux.gypi b/sandbox/linux/sandbox_linux.gypi
index 75f37c9..7b516f7 100644
--- a/sandbox/linux/sandbox_linux.gypi
+++ b/sandbox/linux/sandbox_linux.gypi
@@ -57,6 +57,22 @@
],
},
{
+ 'target_name': 'sandbox_linux_test_utils',
+ 'type': 'static_library',
+ 'dependencies': [
+ '../testing/gtest.gyp:gtest',
+ ],
+ 'include_dirs': [
+ '../..',
+ ],
+ 'sources': [
+ 'tests/test_utils.cc',
+ 'tests/test_utils.h',
+ 'tests/unit_tests.cc',
+ 'tests/unit_tests.h',
+ ],
+ },
+ {
# The main sandboxing test target.
'target_name': 'sandbox_linux_unittests',
'includes': [
diff --git a/sandbox/linux/sandbox_linux_test_sources.gypi b/sandbox/linux/sandbox_linux_test_sources.gypi
index 01db0e9..ffbf9c6 100644
--- a/sandbox/linux/sandbox_linux_test_sources.gypi
+++ b/sandbox/linux/sandbox_linux_test_sources.gypi
@@ -7,6 +7,7 @@
{
'dependencies': [
'sandbox',
+ 'sandbox_linux_test_utils',
'../base/base.gyp:base',
'../base/base.gyp:test_support_base',
'../testing/gtest.gyp:gtest',
@@ -16,10 +17,6 @@
],
'sources': [
'tests/main.cc',
- 'tests/test_utils.cc',
- 'tests/test_utils.h',
- 'tests/unit_tests.cc',
- 'tests/unit_tests.h',
'tests/unit_tests_unittest.cc',
'services/broker_process_unittest.cc',
'services/scoped_process_unittest.cc',
diff --git a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc
index 4cefa4c..47c9989 100644
--- a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc
@@ -13,6 +13,11 @@
#include "build/build_config.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
+#define SECCOMP_MESSAGE_COMMON_CONTENT "seccomp-bpf failure"
+#define SECCOMP_MESSAGE_CLONE_CONTENT "clone() failure"
+#define SECCOMP_MESSAGE_PRCTL_CONTENT "prctl() failure"
+#define SECCOMP_MESSAGE_IOCTL_CONTENT "ioctl() failure"
+
namespace {
inline bool IsArchitectureX86_64() {
@@ -54,7 +59,7 @@ void PrintSyscallError(uint32_t sysno) {
sysno_base10[i] = '0' + mod;
}
static const char kSeccompErrorPrefix[] =
- __FILE__":**CRASHING**:seccomp-bpf failure in syscall ";
+ __FILE__":**CRASHING**:" SECCOMP_MESSAGE_COMMON_CONTENT " in syscall ";
static const char kSeccompErrorPostfix[] = "\n";
WriteToStdErr(kSeccompErrorPrefix, sizeof(kSeccompErrorPrefix) - 1);
WriteToStdErr(sysno_base10, sizeof(sysno_base10));
@@ -95,7 +100,7 @@ intptr_t CrashSIGSYS_Handler(const struct arch_seccomp_data& args, void* aux) {
intptr_t SIGSYSCloneFailure(const struct arch_seccomp_data& args, void* aux) {
static const char kSeccompCloneError[] =
- __FILE__":**CRASHING**:clone() failure\n";
+ __FILE__":**CRASHING**:" SECCOMP_MESSAGE_CLONE_CONTENT "\n";
WriteToStdErr(kSeccompCloneError, sizeof(kSeccompCloneError) - 1);
// "flags" is the first argument in the kernel's clone().
// Mark as volatile to be able to find the value on the stack in a minidump.
@@ -115,7 +120,7 @@ intptr_t SIGSYSCloneFailure(const struct arch_seccomp_data& args, void* aux) {
intptr_t SIGSYSPrctlFailure(const struct arch_seccomp_data& args,
void* /* aux */) {
static const char kSeccompPrctlError[] =
- __FILE__":**CRASHING**:prctl() failure\n";
+ __FILE__":**CRASHING**:" SECCOMP_MESSAGE_PRCTL_CONTENT "\n";
WriteToStdErr(kSeccompPrctlError, sizeof(kSeccompPrctlError) - 1);
// Mark as volatile to be able to find the value on the stack in a minidump.
volatile uint64_t option = args.args[0];
@@ -129,7 +134,7 @@ intptr_t SIGSYSPrctlFailure(const struct arch_seccomp_data& args,
intptr_t SIGSYSIoctlFailure(const struct arch_seccomp_data& args,
void* /* aux */) {
static const char kSeccompIoctlError[] =
- __FILE__":**CRASHING**:ioctl() failure\n";
+ __FILE__":**CRASHING**:" SECCOMP_MESSAGE_IOCTL_CONTENT "\n";
WriteToStdErr(kSeccompIoctlError, sizeof(kSeccompIoctlError) - 1);
// Make "request" volatile so that we can see it on the stack in a minidump.
volatile uint64_t request = args.args[1];
@@ -142,4 +147,20 @@ intptr_t SIGSYSIoctlFailure(const struct arch_seccomp_data& args,
_exit(1);
}
+const char* GetErrorMessageContentForTests() {
+ return SECCOMP_MESSAGE_COMMON_CONTENT;
+}
+
+const char* GetCloneErrorMessageContentForTests() {
+ return SECCOMP_MESSAGE_CLONE_CONTENT;
+}
+
+const char* GetPrctlErrorMessageContentForTests() {
+ return SECCOMP_MESSAGE_PRCTL_CONTENT;
+}
+
+const char* GetIoctlErrorMessageContentForTests() {
+ return SECCOMP_MESSAGE_IOCTL_CONTENT;
+}
+
} // namespace sandbox.
diff --git a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h
index 0bada37..b8f626a 100644
--- a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h
+++ b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h
@@ -39,6 +39,13 @@ SANDBOX_EXPORT intptr_t
SANDBOX_EXPORT intptr_t
SIGSYSIoctlFailure(const struct arch_seccomp_data& args, void* aux);
+// Following four functions return substrings of error messages used
+// in the above four functions. They are useful in death tests.
+SANDBOX_EXPORT const char* GetErrorMessageContentForTests();
+SANDBOX_EXPORT const char* GetCloneErrorMessageContentForTests();
+SANDBOX_EXPORT const char* GetPrctlErrorMessageContentForTests();
+SANDBOX_EXPORT const char* GetIoctlErrorMessageContentForTests();
+
} // namespace sandbox.
#endif // SANDBOX_LINUX_SECCOMP_BPF_HELPERS_SIGSYS_HANDLERS_H_
diff --git a/sandbox/linux/seccomp-bpf/bpf_tests.h b/sandbox/linux/seccomp-bpf/bpf_tests.h
index cc3fc25..357e29c 100644
--- a/sandbox/linux/seccomp-bpf/bpf_tests.h
+++ b/sandbox/linux/seccomp-bpf/bpf_tests.h
@@ -44,6 +44,12 @@ namespace sandbox {
// Assertions are handled exactly the same as with a normal SANDBOX_TEST()
#define BPF_ASSERT SANDBOX_ASSERT
+#define BPF_ASSERT_EQ(x, y) BPF_ASSERT((x) == (y))
+#define BPF_ASSERT_NE(x, y) BPF_ASSERT((x) != (y))
+#define BPF_ASSERT_LT(x, y) BPF_ASSERT((x) < (y))
+#define BPF_ASSERT_GT(x, y) BPF_ASSERT((x) > (y))
+#define BPF_ASSERT_LE(x, y) BPF_ASSERT((x) <= (y))
+#define BPF_ASSERT_GE(x, y) BPF_ASSERT((x) >= (y))
// The "Aux" type is optional. We use an "empty" type by default, so that if
// the caller doesn't provide any type, all the BPF_AUX related data compiles