diff options
author | hamaji@chromium.org <hamaji@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-17 01:55:08 +0000 |
---|---|---|
committer | hamaji@chromium.org <hamaji@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-17 01:55:08 +0000 |
commit | f918ba5c07ebdee7a9b3cfa3f30c13f8bb88dce8 (patch) | |
tree | 4cb0e4a24cf889eceec7d8fe0ed5155753c67858 | |
parent | 0460b695737beaa0a7bd98bfc191a257aa5e1fda (diff) | |
download | chromium_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.gyp | 10 | ||||
-rw-r--r-- | components/nacl.gyp | 40 | ||||
-rw-r--r-- | components/nacl/loader/nacl_helper_linux.cc | 3 | ||||
-rw-r--r-- | components/nacl/loader/nonsfi/DEPS | 1 | ||||
-rw-r--r-- | components/nacl/loader/nonsfi/nonsfi_sandbox.cc | 315 | ||||
-rw-r--r-- | components/nacl/loader/nonsfi/nonsfi_sandbox.h | 39 | ||||
-rw-r--r-- | components/nacl/loader/nonsfi/nonsfi_sandbox_sigsys_unittest.cc | 609 | ||||
-rw-r--r-- | components/nacl/loader/nonsfi/nonsfi_sandbox_unittest.cc | 461 | ||||
-rw-r--r-- | sandbox/linux/sandbox_linux.gypi | 16 | ||||
-rw-r--r-- | sandbox/linux/sandbox_linux_test_sources.gypi | 5 | ||||
-rw-r--r-- | sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc | 29 | ||||
-rw-r--r-- | sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h | 7 | ||||
-rw-r--r-- | sandbox/linux/seccomp-bpf/bpf_tests.h | 6 |
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 |