summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/nacl/loader/sandbox_linux/nacl_bpf_sandbox_linux.cc1
-rw-r--r--content/common/sandbox_linux/android/sandbox_bpf_base_policy_android.cc2
-rw-r--r--content/common/sandbox_linux/bpf_gpu_policy_linux.cc2
-rw-r--r--content/common/sandbox_linux/bpf_ppapi_policy_linux.cc2
-rw-r--r--content/common/sandbox_linux/bpf_renderer_policy_linux.cc2
-rw-r--r--sandbox/linux/sandbox_linux_test_sources.gypi1
-rw-r--r--sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc4
-rw-r--r--sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc114
-rw-r--r--sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc57
-rw-r--r--sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc2
-rw-r--r--sandbox/linux/tests/unit_tests.cc1
11 files changed, 169 insertions, 19 deletions
diff --git a/components/nacl/loader/sandbox_linux/nacl_bpf_sandbox_linux.cc b/components/nacl/loader/sandbox_linux/nacl_bpf_sandbox_linux.cc
index e123523..8071d4f 100644
--- a/components/nacl/loader/sandbox_linux/nacl_bpf_sandbox_linux.cc
+++ b/components/nacl/loader/sandbox_linux/nacl_bpf_sandbox_linux.cc
@@ -74,6 +74,7 @@ ErrorCode NaClBPFSandboxPolicy::EvaluateSyscall(
sandbox::SandboxBPF* sb, int sysno) const {
DCHECK(baseline_policy_);
switch (sysno) {
+ case __NR_clone: // TODO(jln): restrict parameters.
// TODO(jln): NaCl's GDB debug stub uses the following socket system calls,
// see if it can be restricted a bit.
#if defined(__x86_64__) || defined(__arm__)
diff --git a/content/common/sandbox_linux/android/sandbox_bpf_base_policy_android.cc b/content/common/sandbox_linux/android/sandbox_bpf_base_policy_android.cc
index 6335dfc..b7bd3fa 100644
--- a/content/common/sandbox_linux/android/sandbox_bpf_base_policy_android.cc
+++ b/content/common/sandbox_linux/android/sandbox_bpf_base_policy_android.cc
@@ -21,6 +21,8 @@ sandbox::ErrorCode SandboxBPFBasePolicyAndroid::EvaluateSyscall(
bool override_and_allow = false;
switch (sysno) {
+ // TODO(rsesek): restrict clone parameters.
+ case __NR_clone:
case __NR_epoll_pwait:
case __NR_flock:
case __NR_getpriority:
diff --git a/content/common/sandbox_linux/bpf_gpu_policy_linux.cc b/content/common/sandbox_linux/bpf_gpu_policy_linux.cc
index 1570114..2ad07a3 100644
--- a/content/common/sandbox_linux/bpf_gpu_policy_linux.cc
+++ b/content/common/sandbox_linux/bpf_gpu_policy_linux.cc
@@ -166,6 +166,8 @@ GpuProcessPolicy::~GpuProcessPolicy() {}
ErrorCode GpuProcessPolicy::EvaluateSyscall(SandboxBPF* sandbox,
int sysno) const {
switch (sysno) {
+ // TODO(jln): restrict clone.
+ case __NR_clone:
case __NR_ioctl:
#if defined(__i386__) || defined(__x86_64__)
// The Nvidia driver uses flags not in the baseline policy
diff --git a/content/common/sandbox_linux/bpf_ppapi_policy_linux.cc b/content/common/sandbox_linux/bpf_ppapi_policy_linux.cc
index 3a59bfc..4c80622 100644
--- a/content/common/sandbox_linux/bpf_ppapi_policy_linux.cc
+++ b/content/common/sandbox_linux/bpf_ppapi_policy_linux.cc
@@ -24,8 +24,6 @@ PpapiProcessPolicy::~PpapiProcessPolicy() {}
ErrorCode PpapiProcessPolicy::EvaluateSyscall(SandboxBPF* sandbox,
int sysno) const {
switch (sysno) {
- case __NR_clone:
- return sandbox::RestrictCloneToThreadsAndEPERMFork(sandbox);
case __NR_pread64:
case __NR_pwrite64:
case __NR_sched_get_priority_max:
diff --git a/content/common/sandbox_linux/bpf_renderer_policy_linux.cc b/content/common/sandbox_linux/bpf_renderer_policy_linux.cc
index eba2eca..2679778 100644
--- a/content/common/sandbox_linux/bpf_renderer_policy_linux.cc
+++ b/content/common/sandbox_linux/bpf_renderer_policy_linux.cc
@@ -24,8 +24,6 @@ RendererProcessPolicy::~RendererProcessPolicy() {}
ErrorCode RendererProcessPolicy::EvaluateSyscall(SandboxBPF* sandbox,
int sysno) const {
switch (sysno) {
- case __NR_clone:
- return sandbox::RestrictCloneToThreadsAndEPERMFork(sandbox);
case __NR_ioctl:
return sandbox::RestrictIoctl(sandbox);
case __NR_prctl:
diff --git a/sandbox/linux/sandbox_linux_test_sources.gypi b/sandbox/linux/sandbox_linux_test_sources.gypi
index b2ecac5..bf41471 100644
--- a/sandbox/linux/sandbox_linux_test_sources.gypi
+++ b/sandbox/linux/sandbox_linux_test_sources.gypi
@@ -31,6 +31,7 @@
}],
[ 'use_seccomp_bpf==1', {
'sources': [
+ 'seccomp-bpf-helpers/baseline_policy_unittest.cc',
'seccomp-bpf/bpf_tests_unittest.cc',
'seccomp-bpf/codegen_unittest.cc',
'seccomp-bpf/errorcode_unittest.cc',
diff --git a/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc b/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
index 79b5b02..217bdac 100644
--- a/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
@@ -97,6 +97,10 @@ ErrorCode EvaluateSyscallImpl(int fs_denied_errno,
return ErrorCode(ErrorCode::ERR_ALLOWED);
}
+ if (sysno == __NR_clone) {
+ return RestrictCloneToThreadsAndEPERMFork(sandbox);
+ }
+
#if defined(__x86_64__) || defined(__arm__)
if (sysno == __NR_socketpair) {
// Only allow AF_UNIX, PF_UNIX. Crash if anything else is seen.
diff --git a/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
new file mode 100644
index 0000000..281d09a
--- /dev/null
+++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
@@ -0,0 +1,114 @@
+// 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 "sandbox/linux/seccomp-bpf-helpers/baseline_policy.h"
+
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "base/posix/eintr_wrapper.h"
+#include "base/threading/thread.h"
+#include "build/build_config.h"
+#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
+#include "sandbox/linux/seccomp-bpf/bpf_tests.h"
+#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
+#include "sandbox/linux/services/linux_syscalls.h"
+#include "sandbox/linux/services/thread_helpers.h"
+#include "sandbox/linux/tests/unit_tests.h"
+
+namespace sandbox {
+
+namespace {
+
+// |pid| is the return value of a fork()-like call. This
+// makes sure that if fork() succeeded the child exits
+// and the parent waits for it.
+void HandlePostForkReturn(pid_t pid) {
+ const int kChildExitCode = 1;
+ if (pid > 0) {
+ int status = 0;
+ PCHECK(pid == HANDLE_EINTR(waitpid(pid, &status, 0)));
+ CHECK(WIFEXITED(status));
+ CHECK_EQ(kChildExitCode, WEXITSTATUS(status));
+ } else if (pid == 0) {
+ _exit(kChildExitCode);
+ }
+}
+
+// Check that HandlePostForkReturn works.
+TEST(BaselinePolicy, HandlePostForkReturn) {
+ pid_t pid = fork();
+ HandlePostForkReturn(pid);
+}
+
+BPF_TEST_C(BaselinePolicy, FchmodErrno, BaselinePolicy) {
+ int ret = fchmod(-1, 07777);
+ BPF_ASSERT_EQ(-1, ret);
+ // Without the sandbox, this would EBADF instead.
+ BPF_ASSERT_EQ(EPERM, errno);
+}
+
+// TODO(jln): make this work with the sanitizers.
+#if !defined(ADDRESS_SANITIZER) && !defined(THREAD_SANITIZER)
+
+BPF_TEST_C(BaselinePolicy, ForkErrno, BaselinePolicy) {
+ errno = 0;
+ pid_t pid = fork();
+ const int fork_errno = errno;
+ HandlePostForkReturn(pid);
+
+ BPF_ASSERT_EQ(-1, pid);
+ BPF_ASSERT_EQ(EPERM, fork_errno);
+}
+
+pid_t ForkX86Glibc() {
+ return syscall(__NR_clone, CLONE_PARENT_SETTID | SIGCHLD);
+}
+
+BPF_TEST_C(BaselinePolicy, ForkX86Eperm, BaselinePolicy) {
+ errno = 0;
+ pid_t pid = ForkX86Glibc();
+ const int fork_errno = errno;
+ HandlePostForkReturn(pid);
+
+ BPF_ASSERT_EQ(-1, pid);
+ BPF_ASSERT_EQ(EPERM, fork_errno);
+}
+
+pid_t ForkARMGlibc() {
+ return syscall(__NR_clone,
+ CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD);
+}
+
+BPF_TEST_C(BaselinePolicy, ForkArmEperm, BaselinePolicy) {
+ errno = 0;
+ pid_t pid = ForkARMGlibc();
+ const int fork_errno = errno;
+ HandlePostForkReturn(pid);
+
+ BPF_ASSERT_EQ(-1, pid);
+ BPF_ASSERT_EQ(EPERM, fork_errno);
+}
+
+BPF_TEST_C(BaselinePolicy, CreateThread, BaselinePolicy) {
+ base::Thread thread("sandbox_tests");
+ BPF_ASSERT(thread.Start());
+}
+
+BPF_DEATH_TEST_C(BaselinePolicy,
+ DisallowedCloneFlagCrashes,
+ DEATH_MESSAGE(GetCloneErrorMessageContentForTests()),
+ BaselinePolicy) {
+ pid_t pid = syscall(__NR_clone, CLONE_THREAD | SIGCHLD);
+ HandlePostForkReturn(pid);
+}
+
+#endif // !defined(ADDRESS_SANITIZER) && !defined(THREAD_SANITIZER)
+
+} // namespace
+
+} // namespace sandbox
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
index 2f46401..29c5910 100644
--- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
@@ -19,6 +19,7 @@
#include "base/basictypes.h"
#include "base/logging.h"
+#include "build/build_config.h"
#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
#include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
@@ -51,25 +52,53 @@ inline bool IsArchitectureI386() {
#endif
}
+inline bool IsAndroid() {
+#if defined(OS_ANDROID)
+ return true;
+#else
+ return false;
+#endif
+}
+
} // namespace.
namespace sandbox {
+// Allow Glibc's and Android pthread creation flags, crash on any other
+// thread creation attempts and EPERM attempts to use neither
+// CLONE_VM, nor CLONE_THREAD, which includes all fork() implementations.
ErrorCode RestrictCloneToThreadsAndEPERMFork(SandboxBPF* sandbox) {
- // Glibc's pthread.
- return sandbox->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),
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
- CLONE_PARENT_SETTID | SIGCHLD,
- ErrorCode(EPERM),
- // ARM
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
- CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD,
- ErrorCode(EPERM),
- sandbox->Trap(SIGSYSCloneFailure, NULL))));
+ if (!IsAndroid()) {
+ const uint64_t kGlibcPthreadFlags =
+ CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD |
+ CLONE_SYSVSEM | CLONE_SETTLS | CLONE_PARENT_SETTID |
+ CLONE_CHILD_CLEARTID;
+
+ return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
+ kGlibcPthreadFlags,
+ ErrorCode(ErrorCode::ERR_ALLOWED),
+ sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS,
+ CLONE_VM | CLONE_THREAD,
+ sandbox->Trap(SIGSYSCloneFailure, NULL),
+ ErrorCode(EPERM)));
+ } else {
+ const uint64_t kAndroidCloneMask = CLONE_VM | CLONE_FS | CLONE_FILES |
+ CLONE_SIGHAND | CLONE_THREAD |
+ CLONE_SYSVSEM;
+ const uint64_t kObsoleteAndroidCloneMask =
+ kAndroidCloneMask | CLONE_DETACHED;
+
+ return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
+ kAndroidCloneMask,
+ ErrorCode(ErrorCode::ERR_ALLOWED),
+ sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
+ kObsoleteAndroidCloneMask,
+ ErrorCode(ErrorCode::ERR_ALLOWED),
+ sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS,
+ CLONE_VM | CLONE_THREAD,
+ sandbox->Trap(SIGSYSCloneFailure, NULL),
+ ErrorCode(EPERM))));
+ }
}
ErrorCode RestrictPrctl(SandboxBPF* sandbox) {
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
index 792807a..5f8785e 100644
--- a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
@@ -350,7 +350,6 @@ bool SyscallSets::IsKernelInternalApi(int sysno) {
// This should be thought through in conjunction with IsFutex().
bool SyscallSets::IsAllowedProcessStartOrDeath(int sysno) {
switch (sysno) {
- case __NR_clone: // TODO(jln): restrict flags.
case __NR_exit:
case __NR_exit_group:
case __NR_wait4:
@@ -359,6 +358,7 @@ bool SyscallSets::IsAllowedProcessStartOrDeath(int sysno) {
case __NR_waitpid:
#endif
return true;
+ case __NR_clone: // Should be parameter-restricted.
case __NR_setns: // Privileged.
case __NR_fork:
#if defined(__i386__) || defined(__x86_64__)
diff --git a/sandbox/linux/tests/unit_tests.cc b/sandbox/linux/tests/unit_tests.cc
index 282c718..d3ee81b 100644
--- a/sandbox/linux/tests/unit_tests.cc
+++ b/sandbox/linux/tests/unit_tests.cc
@@ -12,6 +12,7 @@
#include <unistd.h>
#include "base/file_util.h"
+#include "base/posix/eintr_wrapper.h"
#include "base/third_party/valgrind/valgrind.h"
#include "build/build_config.h"
#include "sandbox/linux/tests/unit_tests.h"