summaryrefslogtreecommitdiff
path: root/sandbox
diff options
context:
space:
mode:
authorTorne (Richard Coles) <torne@google.com>2014-05-14 12:12:37 +0100
committerTorne (Richard Coles) <torne@google.com>2014-05-14 12:12:37 +0100
commit010d83a9304c5a91596085d917d248abff47903a (patch)
tree41ef1a01862f352f9653c7a9cfa817abefe2cce2 /sandbox
parent08c107de54178bb0990a09adec724924e8bc9486 (diff)
downloadchromium_org-010d83a9304c5a91596085d917d248abff47903a.tar.gz
Merge from Chromium at DEPS revision 269336
This commit was generated by merge_to_master.py. Change-Id: I8b9c77f10eccd2a8b4c7ce373ffda18568af54ff
Diffstat (limited to 'sandbox')
-rw-r--r--sandbox/linux/DEPS25
-rw-r--r--sandbox/linux/sandbox_linux.gypi18
-rw-r--r--sandbox/linux/sandbox_linux_test_sources.gypi3
-rw-r--r--sandbox/linux/seccomp-bpf-helpers/DEPS4
-rw-r--r--sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc4
-rw-r--r--sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc115
-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/seccomp-bpf/DEPS3
-rw-r--r--sandbox/linux/seccomp-bpf/bpf_tester_compatibility_delegate.cc21
-rw-r--r--sandbox/linux/seccomp-bpf/bpf_tester_compatibility_delegate.h81
-rw-r--r--sandbox/linux/seccomp-bpf/bpf_tests.h184
-rw-r--r--sandbox/linux/seccomp-bpf/bpf_tests_unittest.cc156
-rw-r--r--sandbox/linux/seccomp-bpf/sandbox_bpf.cc22
-rw-r--r--sandbox/linux/seccomp-bpf/sandbox_bpf.h1
-rw-r--r--sandbox/linux/seccomp-bpf/sandbox_bpf_compatibility_policy.h42
-rw-r--r--sandbox/linux/seccomp-bpf/sandbox_bpf_test_runner.cc70
-rw-r--r--sandbox/linux/seccomp-bpf/sandbox_bpf_test_runner.h57
-rw-r--r--sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc48
-rw-r--r--sandbox/linux/seccomp-bpf/syscall_unittest.cc22
-rw-r--r--sandbox/linux/suid/client/DEPS3
-rw-r--r--sandbox/linux/suid/client/setuid_sandbox_client.cc59
-rw-r--r--sandbox/linux/suid/client/setuid_sandbox_client.h50
-rw-r--r--sandbox/linux/tests/sandbox_test_runner.h25
-rw-r--r--sandbox/linux/tests/sandbox_test_runner_function_pointer.cc25
-rw-r--r--sandbox/linux/tests/sandbox_test_runner_function_pointer.h26
-rw-r--r--sandbox/linux/tests/unit_tests.cc7
-rw-r--r--sandbox/linux/tests/unit_tests.h25
-rw-r--r--sandbox/sandbox_services.target.darwin-arm.mk2
-rw-r--r--sandbox/sandbox_services.target.darwin-x86.mk2
-rw-r--r--sandbox/sandbox_services.target.darwin-x86_64.mk2
-rw-r--r--sandbox/sandbox_services.target.linux-arm.mk2
-rw-r--r--sandbox/sandbox_services.target.linux-x86.mk2
-rw-r--r--sandbox/sandbox_services.target.linux-x86_64.mk2
-rw-r--r--sandbox/sandbox_services_headers.target.darwin-arm.mk2
-rw-r--r--sandbox/sandbox_services_headers.target.darwin-x86.mk2
-rw-r--r--sandbox/sandbox_services_headers.target.darwin-x86_64.mk2
-rw-r--r--sandbox/sandbox_services_headers.target.linux-arm.mk2
-rw-r--r--sandbox/sandbox_services_headers.target.linux-x86.mk2
-rw-r--r--sandbox/sandbox_services_headers.target.linux-x86_64.mk2
-rw-r--r--sandbox/seccomp_bpf.target.darwin-arm.mk2
-rw-r--r--sandbox/seccomp_bpf.target.darwin-x86.mk2
-rw-r--r--sandbox/seccomp_bpf.target.darwin-x86_64.mk2
-rw-r--r--sandbox/seccomp_bpf.target.linux-arm.mk2
-rw-r--r--sandbox/seccomp_bpf.target.linux-x86.mk2
-rw-r--r--sandbox/seccomp_bpf.target.linux-x86_64.mk2
-rw-r--r--sandbox/seccomp_bpf_helpers.target.darwin-arm.mk2
-rw-r--r--sandbox/seccomp_bpf_helpers.target.darwin-x86.mk2
-rw-r--r--sandbox/seccomp_bpf_helpers.target.darwin-x86_64.mk2
-rw-r--r--sandbox/seccomp_bpf_helpers.target.linux-arm.mk2
-rw-r--r--sandbox/seccomp_bpf_helpers.target.linux-x86.mk2
-rw-r--r--sandbox/seccomp_bpf_helpers.target.linux-x86_64.mk2
52 files changed, 940 insertions, 263 deletions
diff --git a/sandbox/linux/DEPS b/sandbox/linux/DEPS
new file mode 100644
index 0000000000..5c5f476b00
--- /dev/null
+++ b/sandbox/linux/DEPS
@@ -0,0 +1,25 @@
+include_rules = [
+ # First, exclude everything.
+ # Exclude a few dependencies that are included in the root DEPS and that we
+ # don't need.
+ # Sadly, there is no way to exclude all root DEPS since the root has no name.
+ "-ipc",
+ "-library_loaders",
+ "-third_party",
+ "-url",
+ # Make sure that each subdirectory has to declare its dependencies in
+ # sandbox/ explicitly.
+ "-sandbox/linux",
+
+ # Second, add what we want to allow.
+ # Anything included from sandbox/linux must be declared after this line or in
+ # a more specific DEPS file.
+ # base/, build/ and testing/ are already included in the global DEPS file,
+ # but be explicit.
+ "+base",
+ "+build",
+ "+testing",
+ "+sandbox/linux/sandbox_export.h",
+ # Everyone can use tests/
+ "+sandbox/linux/tests",
+]
diff --git a/sandbox/linux/sandbox_linux.gypi b/sandbox/linux/sandbox_linux.gypi
index 0cccd2e9eb..e86345ee60 100644
--- a/sandbox/linux/sandbox_linux.gypi
+++ b/sandbox/linux/sandbox_linux.gypi
@@ -66,11 +66,28 @@
'../..',
],
'sources': [
+ 'tests/sandbox_test_runner.h',
+ 'tests/sandbox_test_runner_function_pointer.cc',
+ 'tests/sandbox_test_runner_function_pointer.h',
'tests/test_utils.cc',
'tests/test_utils.h',
'tests/unit_tests.cc',
'tests/unit_tests.h',
],
+ 'conditions': [
+ [ 'use_seccomp_bpf==1', {
+ 'sources': [
+ 'seccomp-bpf/bpf_tester_compatibility_delegate.cc',
+ 'seccomp-bpf/bpf_tester_compatibility_delegate.h',
+ 'seccomp-bpf/bpf_tests.h',
+ 'seccomp-bpf/sandbox_bpf_test_runner.cc',
+ 'seccomp-bpf/sandbox_bpf_test_runner.h',
+ ],
+ 'dependencies': [
+ 'seccomp_bpf',
+ ]
+ }],
+ ],
},
{
# The main sandboxing test target.
@@ -112,6 +129,7 @@
'seccomp-bpf/linux_seccomp.h',
'seccomp-bpf/sandbox_bpf.cc',
'seccomp-bpf/sandbox_bpf.h',
+ 'seccomp-bpf/sandbox_bpf_compatibility_policy.h',
'seccomp-bpf/sandbox_bpf_policy.h',
'seccomp-bpf/syscall.cc',
'seccomp-bpf/syscall.h',
diff --git a/sandbox/linux/sandbox_linux_test_sources.gypi b/sandbox/linux/sandbox_linux_test_sources.gypi
index 9764830dcc..bf41471213 100644
--- a/sandbox/linux/sandbox_linux_test_sources.gypi
+++ b/sandbox/linux/sandbox_linux_test_sources.gypi
@@ -31,7 +31,8 @@
}],
[ 'use_seccomp_bpf==1', {
'sources': [
- 'seccomp-bpf/bpf_tests.h',
+ 'seccomp-bpf-helpers/baseline_policy_unittest.cc',
+ 'seccomp-bpf/bpf_tests_unittest.cc',
'seccomp-bpf/codegen_unittest.cc',
'seccomp-bpf/errorcode_unittest.cc',
'seccomp-bpf/sandbox_bpf_unittest.cc',
diff --git a/sandbox/linux/seccomp-bpf-helpers/DEPS b/sandbox/linux/seccomp-bpf-helpers/DEPS
new file mode 100644
index 0000000000..e8000d3b32
--- /dev/null
+++ b/sandbox/linux/seccomp-bpf-helpers/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+ "+sandbox/linux/services",
+ "+sandbox/linux/seccomp-bpf",
+]
diff --git a/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc b/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
index 79b5b023da..217bdac679 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 0000000000..9182e076e8
--- /dev/null
+++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
@@ -0,0 +1,115 @@
+// 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/syscall.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 2f4640130b..29c5910359 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 792807ac72..5f8785ea37 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/seccomp-bpf/DEPS b/sandbox/linux/seccomp-bpf/DEPS
new file mode 100644
index 0000000000..15b2b36a3e
--- /dev/null
+++ b/sandbox/linux/seccomp-bpf/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+sandbox/linux/services"
+]
diff --git a/sandbox/linux/seccomp-bpf/bpf_tester_compatibility_delegate.cc b/sandbox/linux/seccomp-bpf/bpf_tester_compatibility_delegate.cc
new file mode 100644
index 0000000000..2fa209b4c7
--- /dev/null
+++ b/sandbox/linux/seccomp-bpf/bpf_tester_compatibility_delegate.cc
@@ -0,0 +1,21 @@
+// 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/bpf_tester_compatibility_delegate.h"
+
+namespace sandbox {
+
+// static
+template <>
+void* BPFTesterCompatibilityDelegate<void>::NewAux() {
+ return NULL;
+}
+
+// static
+template <>
+void BPFTesterCompatibilityDelegate<void>::DeleteAux(void* aux) {
+ CHECK(!aux);
+}
+
+} // namespace sandbox
diff --git a/sandbox/linux/seccomp-bpf/bpf_tester_compatibility_delegate.h b/sandbox/linux/seccomp-bpf/bpf_tester_compatibility_delegate.h
new file mode 100644
index 0000000000..c211d04343
--- /dev/null
+++ b/sandbox/linux/seccomp-bpf/bpf_tester_compatibility_delegate.h
@@ -0,0 +1,81 @@
+// 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 SANDBOX_LINUX_SECCOMP_BPF_BPF_TESTER_COMPATIBILITY_DELEGATE_H_
+#define SANDBOX_LINUX_SECCOMP_BPF_BPF_TESTER_COMPATIBILITY_DELEGATE_H_
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "base/memory/scoped_ptr.h"
+#include "sandbox/linux/seccomp-bpf/sandbox_bpf_compatibility_policy.h"
+#include "sandbox/linux/seccomp-bpf/sandbox_bpf_test_runner.h"
+#include "sandbox/linux/tests/sandbox_test_runner.h"
+#include "sandbox/linux/tests/unit_tests.h"
+
+namespace sandbox {
+
+// This templated class allows building a BPFTesterDelegate from a
+// deprecated-style BPF policy (that is a SyscallEvaluator function pointer,
+// instead of a SandboxBPFPolicy class), specified in |policy_function| and a
+// function pointer to a test in |test_function|.
+// This allows both the policy and the test function to take a pointer to an
+// object of type "Aux" as a parameter. This is used to implement the BPF_TEST
+// macro and should generally not be used directly.
+template <class Aux = void>
+class BPFTesterCompatibilityDelegate : public BPFTesterDelegate {
+ public:
+ typedef Aux AuxType;
+ BPFTesterCompatibilityDelegate(
+ void (*test_function)(AuxType*),
+ typename CompatibilityPolicy<AuxType>::SyscallEvaluator policy_function)
+ : aux_pointer_for_policy_(NULL),
+ test_function_(test_function),
+ policy_function_(policy_function) {
+ // This will be NULL iff AuxType is void.
+ aux_pointer_for_policy_ = NewAux();
+ }
+
+ virtual ~BPFTesterCompatibilityDelegate() {
+ DeleteAux(aux_pointer_for_policy_);
+ }
+
+ virtual scoped_ptr<SandboxBPFPolicy> GetSandboxBPFPolicy() OVERRIDE {
+ // The current method is guaranteed to only run in the child process
+ // running the test. In this process, the current object is guaranteed
+ // to live forever. So it's ok to pass aux_pointer_for_policy_ to
+ // the policy, which could in turn pass it to the kernel via Trap().
+ return scoped_ptr<SandboxBPFPolicy>(new CompatibilityPolicy<AuxType>(
+ policy_function_, aux_pointer_for_policy_));
+ }
+
+ virtual void RunTestFunction() OVERRIDE {
+ // Run the actual test.
+ // The current object is guaranteed to live forever in the child process
+ // where this will run.
+ test_function_(aux_pointer_for_policy_);
+ }
+
+ private:
+ // Allocate an object of type Aux. This is specialized to return NULL when
+ // trying to allocate a void.
+ static Aux* NewAux() { return new Aux(); }
+ static void DeleteAux(Aux* aux) { delete aux; }
+
+ AuxType* aux_pointer_for_policy_;
+ void (*test_function_)(AuxType*);
+ typename CompatibilityPolicy<AuxType>::SyscallEvaluator policy_function_;
+ DISALLOW_COPY_AND_ASSIGN(BPFTesterCompatibilityDelegate);
+};
+
+// Specialization of NewAux that returns NULL;
+template <>
+void* BPFTesterCompatibilityDelegate<void>::NewAux();
+template <>
+void BPFTesterCompatibilityDelegate<void>::DeleteAux(void* aux);
+
+} // namespace sandbox
+
+#endif // SANDBOX_LINUX_SECCOMP_BPF_BPF_TESTER_COMPATIBILITY_DELEGATE_H_
diff --git a/sandbox/linux/seccomp-bpf/bpf_tests.h b/sandbox/linux/seccomp-bpf/bpf_tests.h
index 357e29c731..8fa5579b34 100644
--- a/sandbox/linux/seccomp-bpf/bpf_tests.h
+++ b/sandbox/linux/seccomp-bpf/bpf_tests.h
@@ -5,42 +5,55 @@
#ifndef SANDBOX_LINUX_SECCOMP_BPF_BPF_TESTS_H__
#define SANDBOX_LINUX_SECCOMP_BPF_BPF_TESTS_H__
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
+#include "base/basictypes.h"
#include "build/build_config.h"
+#include "sandbox/linux/seccomp-bpf/bpf_tester_compatibility_delegate.h"
#include "sandbox/linux/tests/unit_tests.h"
-#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
namespace sandbox {
-// A BPF_DEATH_TEST is just the same as a BPF_TEST, but it assumes that the
-// test will fail with a particular known error condition. Use the DEATH_XXX()
-// macros from unit_tests.h to specify the expected error condition.
-// A BPF_DEATH_TEST is always disabled under ThreadSanitizer, see
-// crbug.com/243968.
-#define BPF_DEATH_TEST(test_case_name, test_name, death, policy, aux...) \
- void BPF_TEST_##test_name(sandbox::BPFTests<aux>::AuxType& BPF_AUX); \
- TEST(test_case_name, DISABLE_ON_TSAN(test_name)) { \
- sandbox::BPFTests<aux>::TestArgs arg(BPF_TEST_##test_name, policy); \
- sandbox::BPFTests<aux>::RunTestInProcess( \
- sandbox::BPFTests<aux>::TestWrapper, &arg, death); \
- } \
- void BPF_TEST_##test_name(sandbox::BPFTests<aux>::AuxType& BPF_AUX)
-
-// BPF_TEST() is a special version of SANDBOX_TEST(). It turns into a no-op,
-// if the host does not have kernel support for running BPF filters.
-// Also, it takes advantage of the Die class to avoid calling LOG(FATAL), from
-// inside our tests, as we don't need or even want all the error handling that
-// LOG(FATAL) would do.
-// BPF_TEST() takes a C++ data type as an optional fourth parameter. If
-// present, this sets up a variable that can be accessed as "BPF_AUX". This
-// variable will be passed as an argument to the "policy" function. Policies
-// would typically use it as an argument to SandboxBPF::Trap(), if they want to
-// communicate data between the BPF_TEST() and a Trap() function.
-#define BPF_TEST(test_case_name, test_name, policy, aux...) \
- BPF_DEATH_TEST(test_case_name, test_name, DEATH_SUCCESS(), policy, aux)
+// BPF_TEST_C() is a special version of SANDBOX_TEST(). It runs a test function
+// in a sub-process, under a seccomp-bpf policy specified in
+// |bpf_policy_class_name| without failing on configurations that are allowed
+// to not support seccomp-bpf in their kernels.
+// This is the preferred format for new BPF tests. |bpf_policy_class_name| is a
+// class name (which will be default-constructed) that implements the
+// SandboxBPFPolicy interface.
+// The test function's body can simply follow. Test functions should use
+// the BPF_ASSERT macros defined below, not GTEST's macros. The use of
+// CHECK* macros is supported but less robust.
+#define BPF_TEST_C(test_case_name, test_name, bpf_policy_class_name) \
+ BPF_DEATH_TEST_C( \
+ test_case_name, test_name, DEATH_SUCCESS(), bpf_policy_class_name)
+
+// Identical to BPF_TEST_C but allows to specify the nature of death.
+#define BPF_DEATH_TEST_C( \
+ test_case_name, test_name, death, bpf_policy_class_name) \
+ void BPF_TEST_C_##test_name(); \
+ TEST(test_case_name, DISABLE_ON_TSAN(test_name)) { \
+ sandbox::SandboxBPFTestRunner bpf_test_runner( \
+ new sandbox::BPFTesterSimpleDelegate<bpf_policy_class_name>( \
+ BPF_TEST_C_##test_name)); \
+ sandbox::UnitTests::RunTestInProcess(&bpf_test_runner, death); \
+ } \
+ void BPF_TEST_C_##test_name()
+
+// This form of BPF_TEST is a little verbose and should be reserved for complex
+// tests where a lot of control is required.
+// |bpf_tester_delegate_class| must be a classname implementing the
+// BPFTesterDelegate interface.
+#define BPF_TEST_D(test_case_name, test_name, bpf_tester_delegate_class) \
+ BPF_DEATH_TEST_D( \
+ test_case_name, test_name, DEATH_SUCCESS(), bpf_tester_delegate_class)
+
+// Identical to BPF_TEST_D but allows to specify the nature of death.
+#define BPF_DEATH_TEST_D( \
+ test_case_name, test_name, death, bpf_tester_delegate_class) \
+ TEST(test_case_name, DISABLE_ON_TSAN(test_name)) { \
+ sandbox::SandboxBPFTestRunner bpf_test_runner( \
+ new bpf_tester_delegate_class()); \
+ sandbox::UnitTests::RunTestInProcess(&bpf_test_runner, death); \
+ }
// Assertions are handled exactly the same as with a normal SANDBOX_TEST()
#define BPF_ASSERT SANDBOX_ASSERT
@@ -51,70 +64,61 @@ namespace sandbox {
#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
-// to nothing.
-template <class Aux = int[0]>
-class BPFTests : public UnitTests {
- public:
- typedef Aux AuxType;
-
- class TestArgs {
- public:
- TestArgs(void (*t)(AuxType&), sandbox::SandboxBPF::EvaluateSyscall p)
- : test_(t), policy_(p), aux_() {}
-
- void (*test() const)(AuxType&) { return test_; }
- sandbox::SandboxBPF::EvaluateSyscall policy() const { return policy_; }
-
- private:
- friend class BPFTests;
-
- void (*test_)(AuxType&);
- sandbox::SandboxBPF::EvaluateSyscall policy_;
- AuxType aux_;
- };
-
- static void TestWrapper(void* void_arg) {
- TestArgs* arg = reinterpret_cast<TestArgs*>(void_arg);
- sandbox::Die::EnableSimpleExit();
- if (sandbox::SandboxBPF::SupportsSeccompSandbox(-1) ==
- sandbox::SandboxBPF::STATUS_AVAILABLE) {
- // Ensure the the sandbox is actually available at this time
- int proc_fd;
- BPF_ASSERT((proc_fd = open("/proc", O_RDONLY | O_DIRECTORY)) >= 0);
- BPF_ASSERT(sandbox::SandboxBPF::SupportsSeccompSandbox(proc_fd) ==
- sandbox::SandboxBPF::STATUS_AVAILABLE);
+// This form of BPF_TEST is now discouraged (but still allowed) in favor of
+// BPF_TEST_D and BPF_TEST_C.
+// The |policy| parameter should be a SyscallEvaluator function pointer
+// (which is now a deprecated way of expressing policies).
+// BPF_TEST() takes a C++ data type as an optional fourth parameter. If
+// present, this sets up a variable that can be accessed as "BPF_AUX". This
+// variable will be passed as an argument to the "policy" function. Policies
+// would typically use it as an argument to SandboxBPF::Trap(), if they want to
+// communicate data between the BPF_TEST() and a Trap() function. The life-time
+// of this object is the same as the life-time of the process running under the
+// seccomp-bpf policy.
+// The type specified in |aux| and the last parameter of the policy function
+// must be compatible. If |aux| is not specified, the policy function must
+// take a void* as its last parameter (that is, must have the EvaluateSyscall
+// type).
+#define BPF_TEST(test_case_name, test_name, policy, aux...) \
+ BPF_DEATH_TEST(test_case_name, test_name, DEATH_SUCCESS(), policy, aux)
- // Initialize and then start the sandbox with our custom policy
- sandbox::SandboxBPF sandbox;
- sandbox.set_proc_fd(proc_fd);
- sandbox.SetSandboxPolicyDeprecated(arg->policy(), &arg->aux_);
- BPF_ASSERT(sandbox.StartSandbox(
- sandbox::SandboxBPF::PROCESS_SINGLE_THREADED));
+// A BPF_DEATH_TEST is just the same as a BPF_TEST, but it assumes that the
+// test will fail with a particular known error condition. Use the DEATH_XXX()
+// macros from unit_tests.h to specify the expected error condition.
+#define BPF_DEATH_TEST(test_case_name, test_name, death, policy, aux...) \
+ void BPF_TEST_##test_name( \
+ sandbox::BPFTesterCompatibilityDelegate<aux>::AuxType* BPF_AUX); \
+ TEST(test_case_name, DISABLE_ON_TSAN(test_name)) { \
+ sandbox::SandboxBPFTestRunner bpf_test_runner( \
+ new sandbox::BPFTesterCompatibilityDelegate<aux>(BPF_TEST_##test_name, \
+ policy)); \
+ sandbox::UnitTests::RunTestInProcess(&bpf_test_runner, death); \
+ } \
+ void BPF_TEST_##test_name( \
+ sandbox::BPFTesterCompatibilityDelegate<aux>::AuxType* BPF_AUX)
+
+// This class takes a simple function pointer as a constructor parameter and a
+// class name as a template parameter to implement the BPFTesterDelegate
+// interface which can be used to build BPF unittests with
+// the SandboxBPFTestRunner class.
+template <class PolicyClass>
+class BPFTesterSimpleDelegate : public BPFTesterDelegate {
+ public:
+ explicit BPFTesterSimpleDelegate(void (*test_function)(void))
+ : test_function_(test_function) {}
+ virtual ~BPFTesterSimpleDelegate() {}
- arg->test()(arg->aux_);
- } else {
- printf("This BPF test is not fully running in this configuration!\n");
- // Android and Valgrind are the only configurations where we accept not
- // having kernel BPF support.
- if (!IsAndroid() && !IsRunningOnValgrind()) {
- const bool seccomp_bpf_is_supported = false;
- BPF_ASSERT(seccomp_bpf_is_supported);
- }
- // Call the compiler and verify the policy. That's the least we can do,
- // if we don't have kernel support.
- sandbox::SandboxBPF sandbox;
- sandbox.SetSandboxPolicyDeprecated(arg->policy(), &arg->aux_);
- sandbox::SandboxBPF::Program* program =
- sandbox.AssembleFilter(true /* force_verification */);
- delete program;
- sandbox::UnitTests::IgnoreThisTest();
- }
+ virtual scoped_ptr<SandboxBPFPolicy> GetSandboxBPFPolicy() OVERRIDE {
+ return scoped_ptr<SandboxBPFPolicy>(new PolicyClass());
+ }
+ virtual void RunTestFunction() OVERRIDE {
+ DCHECK(test_function_);
+ test_function_();
}
private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(BPFTests);
+ void (*test_function_)(void);
+ DISALLOW_COPY_AND_ASSIGN(BPFTesterSimpleDelegate);
};
} // namespace sandbox
diff --git a/sandbox/linux/seccomp-bpf/bpf_tests_unittest.cc b/sandbox/linux/seccomp-bpf/bpf_tests_unittest.cc
new file mode 100644
index 0000000000..d83b8eda3e
--- /dev/null
+++ b/sandbox/linux/seccomp-bpf/bpf_tests_unittest.cc
@@ -0,0 +1,156 @@
+// 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/bpf_tests.h"
+
+#include <errno.h>
+#include <sys/ptrace.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "build/build_config.h"
+#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
+#include "sandbox/linux/services/linux_syscalls.h"
+#include "sandbox/linux/tests/unit_tests.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace sandbox {
+
+namespace {
+
+ErrorCode EmptyPolicy(SandboxBPF* sandbox, int sysno, void* aux) {
+ // |aux| should always be NULL since a type was not specified as an argument
+ // to BPF_TEST.
+ BPF_ASSERT(NULL == aux);
+ if (!SandboxBPF::IsValidSyscallNumber(sysno)) {
+ return ErrorCode(ENOSYS);
+ } else {
+ return ErrorCode(ErrorCode::ERR_ALLOWED);
+ }
+}
+
+BPF_TEST(BPFTest, BPFAUXIsNull, EmptyPolicy) {
+ // Check that the implicit BPF_AUX argument is NULL when we
+ // don't specify a fourth parameter to BPF_TEST.
+ BPF_ASSERT(NULL == BPF_AUX);
+}
+
+class FourtyTwo {
+ public:
+ static const int kMagicValue = 42;
+ FourtyTwo() : value_(kMagicValue) {}
+ int value() { return value_; }
+
+ private:
+ int value_;
+ DISALLOW_COPY_AND_ASSIGN(FourtyTwo);
+};
+
+ErrorCode EmptyPolicyTakesClass(SandboxBPF* sandbox,
+ int sysno,
+ FourtyTwo* fourty_two) {
+ // |aux| should point to an instance of FourtyTwo.
+ BPF_ASSERT(fourty_two);
+ BPF_ASSERT(FourtyTwo::kMagicValue == fourty_two->value());
+ if (!SandboxBPF::IsValidSyscallNumber(sysno)) {
+ return ErrorCode(ENOSYS);
+ } else {
+ return ErrorCode(ErrorCode::ERR_ALLOWED);
+ }
+}
+
+BPF_TEST(BPFTest,
+ BPFAUXPointsToClass,
+ EmptyPolicyTakesClass,
+ FourtyTwo /* *BPF_AUX */) {
+ // BPF_AUX should point to an instance of FourtyTwo.
+ BPF_ASSERT(BPF_AUX);
+ BPF_ASSERT(FourtyTwo::kMagicValue == BPF_AUX->value());
+}
+
+void DummyTestFunction(FourtyTwo *fourty_two) {
+}
+
+TEST(BPFTest, BPFTesterCompatibilityDelegateLeakTest) {
+ // Don't do anything, simply gives dynamic tools an opportunity to detect
+ // leaks.
+ {
+ BPFTesterCompatibilityDelegate<FourtyTwo> simple_delegate(
+ DummyTestFunction, EmptyPolicyTakesClass);
+ }
+ {
+ // Test polymorphism.
+ scoped_ptr<BPFTesterDelegate> simple_delegate(
+ new BPFTesterCompatibilityDelegate<FourtyTwo>(DummyTestFunction,
+ EmptyPolicyTakesClass));
+ }
+}
+
+class EnosysPtracePolicy : public SandboxBPFPolicy {
+ public:
+ EnosysPtracePolicy() {
+ my_pid_ = syscall(__NR_getpid);
+ }
+ virtual ~EnosysPtracePolicy() {
+ // Policies should be able to bind with the process on which they are
+ // created. They should never be created in a parent process.
+ BPF_ASSERT_EQ(my_pid_, syscall(__NR_getpid));
+ }
+
+ virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
+ int system_call_number) const OVERRIDE {
+ if (!SandboxBPF::IsValidSyscallNumber(system_call_number)) {
+ return ErrorCode(ENOSYS);
+ } else if (system_call_number == __NR_ptrace) {
+ // The EvaluateSyscall function should run in the process that created
+ // the current object.
+ BPF_ASSERT_EQ(my_pid_, syscall(__NR_getpid));
+ return ErrorCode(ENOSYS);
+ } else {
+ return ErrorCode(ErrorCode::ERR_ALLOWED);
+ }
+ }
+
+ private:
+ pid_t my_pid_;
+ DISALLOW_COPY_AND_ASSIGN(EnosysPtracePolicy);
+};
+
+class BasicBPFTesterDelegate : public BPFTesterDelegate {
+ public:
+ BasicBPFTesterDelegate() {}
+ virtual ~BasicBPFTesterDelegate() {}
+
+ virtual scoped_ptr<SandboxBPFPolicy> GetSandboxBPFPolicy() OVERRIDE {
+ return scoped_ptr<SandboxBPFPolicy>(new EnosysPtracePolicy());
+ }
+ virtual void RunTestFunction() OVERRIDE {
+ errno = 0;
+ int ret = ptrace(PTRACE_TRACEME, -1, NULL, NULL);
+ BPF_ASSERT(-1 == ret);
+ BPF_ASSERT(ENOSYS == errno);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BasicBPFTesterDelegate);
+};
+
+// This is the most powerful and complex way to create a BPF test, but it
+// requires a full class definition (BasicBPFTesterDelegate).
+BPF_TEST_D(BPFTest, BPFTestWithDelegateClass, BasicBPFTesterDelegate);
+
+// This is the simplest form of BPF tests.
+BPF_TEST_C(BPFTest, BPFTestWithInlineTest, EnosysPtracePolicy) {
+ errno = 0;
+ int ret = ptrace(PTRACE_TRACEME, -1, NULL, NULL);
+ BPF_ASSERT(-1 == ret);
+ BPF_ASSERT(ENOSYS == errno);
+}
+
+} // namespace
+
+} // namespace sandbox
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
index 1538fe8347..497c343f28 100644
--- a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
+++ b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
@@ -25,6 +25,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/posix/eintr_wrapper.h"
#include "sandbox/linux/seccomp-bpf/codegen.h"
+#include "sandbox/linux/seccomp-bpf/sandbox_bpf_compatibility_policy.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h"
#include "sandbox/linux/seccomp-bpf/syscall.h"
#include "sandbox/linux/seccomp-bpf/syscall_iterator.h"
@@ -202,25 +203,6 @@ intptr_t BPFFailure(const struct arch_seccomp_data&, void* aux) {
SANDBOX_DIE(static_cast<char*>(aux));
}
-// This class allows compatibility with the old, deprecated SetSandboxPolicy.
-class CompatibilityPolicy : public SandboxBPFPolicy {
- public:
- CompatibilityPolicy(SandboxBPF::EvaluateSyscall syscall_evaluator, void* aux)
- : syscall_evaluator_(syscall_evaluator), aux_(aux) {
- DCHECK(syscall_evaluator_);
- }
-
- virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
- int system_call_number) const OVERRIDE {
- return syscall_evaluator_(sandbox_compiler, system_call_number, aux_);
- }
-
- private:
- SandboxBPF::EvaluateSyscall syscall_evaluator_;
- void* aux_;
- DISALLOW_COPY_AND_ASSIGN(CompatibilityPolicy);
-};
-
} // namespace
SandboxBPF::SandboxBPF()
@@ -498,7 +480,7 @@ void SandboxBPF::SetSandboxPolicyDeprecated(EvaluateSyscall syscall_evaluator,
if (sandbox_has_started_ || !conds_) {
SANDBOX_DIE("Cannot change policy after sandbox has started");
}
- SetSandboxPolicy(new CompatibilityPolicy(syscall_evaluator, aux));
+ SetSandboxPolicy(new CompatibilityPolicy<void>(syscall_evaluator, aux));
}
// Don't take a scoped_ptr here, polymorphism make their use awkward.
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf.h b/sandbox/linux/seccomp-bpf/sandbox_bpf.h
index 67b84b9343..2391c5d7d3 100644
--- a/sandbox/linux/seccomp-bpf/sandbox_bpf.h
+++ b/sandbox/linux/seccomp-bpf/sandbox_bpf.h
@@ -73,7 +73,6 @@ class SANDBOX_EXPORT SandboxBPF {
typedef ErrorCode (*EvaluateSyscall)(SandboxBPF* sandbox_compiler,
int system_call_number,
void* aux);
- typedef std::vector<std::pair<EvaluateSyscall, void*> > Evaluators;
// A vector of BPF instructions that need to be installed as a filter
// program in the kernel.
typedef std::vector<struct sock_filter> Program;
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf_compatibility_policy.h b/sandbox/linux/seccomp-bpf/sandbox_bpf_compatibility_policy.h
new file mode 100644
index 0000000000..bd947ad521
--- /dev/null
+++ b/sandbox/linux/seccomp-bpf/sandbox_bpf_compatibility_policy.h
@@ -0,0 +1,42 @@
+// 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 SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_COMPATIBILITY_POLICY_H_
+#define SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_COMPATIBILITY_POLICY_H_
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
+#include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h"
+
+namespace sandbox {
+
+// This class allows compatibility with the old, deprecated
+// policies that were designed for SetSandboxPolicyDeprecated().
+template <class AuxType>
+class CompatibilityPolicy : public SandboxBPFPolicy {
+ public:
+ typedef ErrorCode (*SyscallEvaluator)(SandboxBPF* sandbox_compiler,
+ int system_call_number,
+ AuxType* aux);
+ CompatibilityPolicy(SyscallEvaluator syscall_evaluator, AuxType* aux)
+ : syscall_evaluator_(syscall_evaluator), aux_(aux) {}
+
+ virtual ~CompatibilityPolicy() {}
+
+ virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
+ int system_call_number) const OVERRIDE {
+ return syscall_evaluator_(sandbox_compiler, system_call_number, aux_);
+ }
+
+ private:
+ SyscallEvaluator syscall_evaluator_;
+ AuxType* aux_;
+ DISALLOW_COPY_AND_ASSIGN(CompatibilityPolicy);
+};
+
+} // namespace sandbox
+
+#endif // SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_COMPATIBILITY_POLICY_H_
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf_test_runner.cc b/sandbox/linux/seccomp-bpf/sandbox_bpf_test_runner.cc
new file mode 100644
index 0000000000..ade1d49d2b
--- /dev/null
+++ b/sandbox/linux/seccomp-bpf/sandbox_bpf_test_runner.cc
@@ -0,0 +1,70 @@
+// 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/sandbox_bpf_test_runner.h"
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
+#include "sandbox/linux/tests/unit_tests.h"
+
+namespace sandbox {
+
+SandboxBPFTestRunner::SandboxBPFTestRunner(
+ BPFTesterDelegate* bpf_tester_delegate)
+ : bpf_tester_delegate_(bpf_tester_delegate) {
+}
+
+SandboxBPFTestRunner::~SandboxBPFTestRunner() {
+}
+
+void SandboxBPFTestRunner::Run() {
+ DCHECK(bpf_tester_delegate_);
+ sandbox::Die::EnableSimpleExit();
+
+ scoped_ptr<SandboxBPFPolicy> policy =
+ bpf_tester_delegate_->GetSandboxBPFPolicy();
+
+ if (sandbox::SandboxBPF::SupportsSeccompSandbox(-1) ==
+ sandbox::SandboxBPF::STATUS_AVAILABLE) {
+ // Ensure the the sandbox is actually available at this time
+ int proc_fd;
+ SANDBOX_ASSERT((proc_fd = open("/proc", O_RDONLY | O_DIRECTORY)) >= 0);
+ SANDBOX_ASSERT(sandbox::SandboxBPF::SupportsSeccompSandbox(proc_fd) ==
+ sandbox::SandboxBPF::STATUS_AVAILABLE);
+
+ // Initialize and then start the sandbox with our custom policy
+ sandbox::SandboxBPF sandbox;
+ sandbox.set_proc_fd(proc_fd);
+ sandbox.SetSandboxPolicy(policy.release());
+ SANDBOX_ASSERT(
+ sandbox.StartSandbox(sandbox::SandboxBPF::PROCESS_SINGLE_THREADED));
+
+ // Run the actual test.
+ bpf_tester_delegate_->RunTestFunction();
+ } else {
+ printf("This BPF test is not fully running in this configuration!\n");
+ // Android and Valgrind are the only configurations where we accept not
+ // having kernel BPF support.
+ if (!IsAndroid() && !IsRunningOnValgrind()) {
+ const bool seccomp_bpf_is_supported = false;
+ SANDBOX_ASSERT(seccomp_bpf_is_supported);
+ }
+ // Call the compiler and verify the policy. That's the least we can do,
+ // if we don't have kernel support.
+ sandbox::SandboxBPF sandbox;
+ sandbox.SetSandboxPolicy(policy.release());
+ sandbox::SandboxBPF::Program* program =
+ sandbox.AssembleFilter(true /* force_verification */);
+ delete program;
+ sandbox::UnitTests::IgnoreThisTest();
+ }
+}
+
+} // namespace sandbox
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf_test_runner.h b/sandbox/linux/seccomp-bpf/sandbox_bpf_test_runner.h
new file mode 100644
index 0000000000..c1beba2e60
--- /dev/null
+++ b/sandbox/linux/seccomp-bpf/sandbox_bpf_test_runner.h
@@ -0,0 +1,57 @@
+// 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 SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_TEST_RUNNER_H_
+#define SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_TEST_RUNNER_H_
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h"
+#include "sandbox/linux/tests/sandbox_test_runner.h"
+
+namespace sandbox {
+
+// To create a SandboxBPFTestRunner object, one needs to implement this
+// interface and pass an instance to the SandboxBPFTestRunner constructor.
+// In the child process running the test, the BPFTesterDelegate object is
+// guaranteed to not be destroyed until the child process terminates.
+class BPFTesterDelegate {
+ public:
+ BPFTesterDelegate() {}
+ virtual ~BPFTesterDelegate() {}
+
+ // This will instanciate a policy suitable for the test we want to run. It is
+ // guaranteed to only be called from the child process that will run the
+ // test.
+ virtual scoped_ptr<SandboxBPFPolicy> GetSandboxBPFPolicy() = 0;
+ // This will be called from a child process with the BPF sandbox turned on.
+ virtual void RunTestFunction() = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BPFTesterDelegate);
+};
+
+// This class implements the SandboxTestRunner interface and Run() will
+// initialize a seccomp-bpf sandbox (specified by |bpf_tester_delegate|) and
+// run a test function (via |bpf_tester_delegate|) if the current kernel
+// configuration allows it. If it can not run the test under seccomp-bpf,
+// Run() will still compile the policy which should allow to get some coverage
+// under tools such as Valgrind.
+class SandboxBPFTestRunner : public SandboxTestRunner {
+ public:
+ // This constructor takes ownership of the |bpf_tester_delegate| object.
+ // (It doesn't take a scoped_ptr since they make polymorphism verbose).
+ explicit SandboxBPFTestRunner(BPFTesterDelegate* bpf_tester_delegate);
+ virtual ~SandboxBPFTestRunner();
+
+ virtual void Run() OVERRIDE;
+
+ private:
+ scoped_ptr<BPFTesterDelegate> bpf_tester_delegate_;
+ DISALLOW_COPY_AND_ASSIGN(SandboxBPFTestRunner);
+};
+
+} // namespace sandbox
+
+#endif // SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_TEST_RUNNER_H_
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc b/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc
index 5c5c6275e8..3b7470b417 100644
--- a/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc
+++ b/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc
@@ -21,6 +21,7 @@
#include <ostream>
#include "base/bind.h"
+#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "build/build_config.h"
#include "sandbox/linux/seccomp-bpf/bpf_tests.h"
@@ -115,7 +116,10 @@ SANDBOX_TEST(SandboxBPF, DISABLE_ON_TSAN(VerboseAPITesting)) {
// A simple blacklist test
-ErrorCode BlacklistNanosleepPolicy(SandboxBPF*, int sysno, void*) {
+ErrorCode BlacklistNanosleepPolicy(SandboxBPF*, int sysno, void* aux) {
+ // Since no type was specified in BPF_TEST as a fourth argument,
+ // |aux| must be NULL here.
+ BPF_ASSERT(NULL == aux);
if (!SandboxBPF::IsValidSyscallNumber(sysno)) {
// FIXME: we should really not have to do that in a trivial policy
return ErrorCode(ENOSYS);
@@ -136,7 +140,6 @@ BPF_TEST(SandboxBPF, ApplyBasicBlacklistPolicy, BlacklistNanosleepPolicy) {
BPF_ASSERT(syscall(__NR_nanosleep, &ts, NULL) == -1);
BPF_ASSERT(errno == EACCES);
}
-
// Now do a simple whitelist test
ErrorCode WhitelistGetpidPolicy(SandboxBPF*, int sysno, void*) {
@@ -161,7 +164,6 @@ BPF_TEST(SandboxBPF, ApplyBasicWhitelistPolicy, WhitelistGetpidPolicy) {
}
// A simple blacklist policy, with a SIGSYS handler
-
intptr_t EnomemHandler(const struct arch_seccomp_data& args, void* aux) {
// We also check that the auxiliary data is correct
SANDBOX_ASSERT(aux);
@@ -171,7 +173,7 @@ intptr_t EnomemHandler(const struct arch_seccomp_data& args, void* aux) {
ErrorCode BlacklistNanosleepPolicySigsys(SandboxBPF* sandbox,
int sysno,
- void* aux) {
+ int* aux) {
if (!SandboxBPF::IsValidSyscallNumber(sysno)) {
// FIXME: we should really not have to do that in a trivial policy
return ErrorCode(ENOSYS);
@@ -188,20 +190,20 @@ ErrorCode BlacklistNanosleepPolicySigsys(SandboxBPF* sandbox,
BPF_TEST(SandboxBPF,
BasicBlacklistWithSigsys,
BlacklistNanosleepPolicySigsys,
- int /* BPF_AUX */) {
+ int /* (*BPF_AUX) */) {
// getpid() should work properly
errno = 0;
BPF_ASSERT(syscall(__NR_getpid) > 0);
BPF_ASSERT(errno == 0);
// Our Auxiliary Data, should be reset by the signal handler
- BPF_AUX = -1;
+ *BPF_AUX = -1;
const struct timespec ts = {0, 0};
BPF_ASSERT(syscall(__NR_nanosleep, &ts, NULL) == -1);
BPF_ASSERT(errno == ENOMEM);
// We expect the signal handler to modify AuxData
- BPF_ASSERT(BPF_AUX == kExpectedReturnValue);
+ BPF_ASSERT(*BPF_AUX == kExpectedReturnValue);
}
// A simple test that verifies we can return arbitrary errno values.
@@ -444,7 +446,7 @@ intptr_t CountSyscalls(const struct arch_seccomp_data& args, void* aux) {
return SandboxBPF::ForwardSyscall(args);
}
-ErrorCode GreyListedPolicy(SandboxBPF* sandbox, int sysno, void* aux) {
+ErrorCode GreyListedPolicy(SandboxBPF* sandbox, int sysno, int* aux) {
// The use of UnsafeTrap() causes us to print a warning message. This is
// generally desirable, but it results in the unittest failing, as it doesn't
// expect any messages on "stderr". So, temporarily disable messages. The
@@ -477,12 +479,12 @@ ErrorCode GreyListedPolicy(SandboxBPF* sandbox, int sysno, void* aux) {
}
}
-BPF_TEST(SandboxBPF, GreyListedPolicy, GreyListedPolicy, int /* BPF_AUX */) {
+BPF_TEST(SandboxBPF, GreyListedPolicy, GreyListedPolicy, int /* (*BPF_AUX) */) {
BPF_ASSERT(syscall(__NR_getpid) == -1);
BPF_ASSERT(errno == EPERM);
- BPF_ASSERT(BPF_AUX == 0);
+ BPF_ASSERT(*BPF_AUX == 0);
BPF_ASSERT(syscall(__NR_geteuid) == syscall(__NR_getuid));
- BPF_ASSERT(BPF_AUX == 2);
+ BPF_ASSERT(*BPF_AUX == 2);
char name[17] = {};
BPF_ASSERT(!syscall(__NR_prctl,
PR_GET_NAME,
@@ -490,7 +492,7 @@ BPF_TEST(SandboxBPF, GreyListedPolicy, GreyListedPolicy, int /* BPF_AUX */) {
(void*)NULL,
(void*)NULL,
(void*)NULL));
- BPF_ASSERT(BPF_AUX == 3);
+ BPF_ASSERT(*BPF_AUX == 3);
BPF_ASSERT(*name);
}
@@ -724,8 +726,9 @@ intptr_t BrokerOpenTrapHandler(const struct arch_seccomp_data& args,
}
}
-ErrorCode DenyOpenPolicy(SandboxBPF* sandbox, int sysno, void* aux) {
- InitializedOpenBroker* iob = static_cast<InitializedOpenBroker*>(aux);
+ErrorCode DenyOpenPolicy(SandboxBPF* sandbox,
+ int sysno,
+ InitializedOpenBroker* iob) {
if (!SandboxBPF::IsValidSyscallNumber(sysno)) {
return ErrorCode(ENOSYS);
}
@@ -752,9 +755,9 @@ ErrorCode DenyOpenPolicy(SandboxBPF* sandbox, int sysno, void* aux) {
BPF_TEST(SandboxBPF,
UseOpenBroker,
DenyOpenPolicy,
- InitializedOpenBroker /* BPF_AUX */) {
- BPF_ASSERT(BPF_AUX.initialized());
- BrokerProcess* broker_process = BPF_AUX.broker_process();
+ InitializedOpenBroker /* (*BPF_AUX) */) {
+ BPF_ASSERT(BPF_AUX->initialized());
+ BrokerProcess* broker_process = BPF_AUX->broker_process();
BPF_ASSERT(broker_process != NULL);
// First, use the broker "manually"
@@ -1161,15 +1164,18 @@ class EqualityStressTest {
static const int kMaxArgs = 6;
};
-ErrorCode EqualityStressTestPolicy(SandboxBPF* sandbox, int sysno, void* aux) {
- return reinterpret_cast<EqualityStressTest*>(aux)->Policy(sandbox, sysno);
+ErrorCode EqualityStressTestPolicy(SandboxBPF* sandbox,
+ int sysno,
+ EqualityStressTest* aux) {
+ DCHECK(aux);
+ return aux->Policy(sandbox, sysno);
}
BPF_TEST(SandboxBPF,
EqualityTests,
EqualityStressTestPolicy,
- EqualityStressTest /* BPF_AUX */) {
- BPF_AUX.VerifyFilter();
+ EqualityStressTest /* (*BPF_AUX) */) {
+ BPF_AUX->VerifyFilter();
}
ErrorCode EqualityArgumentWidthPolicy(SandboxBPF* sandbox, int sysno, void*) {
diff --git a/sandbox/linux/seccomp-bpf/syscall_unittest.cc b/sandbox/linux/seccomp-bpf/syscall_unittest.cc
index 60db69bcd6..bdeee4fe2d 100644
--- a/sandbox/linux/seccomp-bpf/syscall_unittest.cc
+++ b/sandbox/linux/seccomp-bpf/syscall_unittest.cc
@@ -70,7 +70,7 @@ TEST(Syscall, TrivialSyscallOneArg) {
// SIGSYS trap handler that will be called on __NR_uname.
intptr_t CopySyscallArgsToAux(const struct arch_seccomp_data& args, void* aux) {
- // |aux| is a pointer to our BPF_AUX.
+ // |aux| is our BPF_AUX pointer.
std::vector<uint64_t>* const seen_syscall_args =
static_cast<std::vector<uint64_t>*>(aux);
BPF_ASSERT(arraysize(args.args) == 6);
@@ -78,7 +78,9 @@ intptr_t CopySyscallArgsToAux(const struct arch_seccomp_data& args, void* aux) {
return -ENOMEM;
}
-ErrorCode CopyAllArgsOnUnamePolicy(SandboxBPF* sandbox, int sysno, void* aux) {
+ErrorCode CopyAllArgsOnUnamePolicy(SandboxBPF* sandbox,
+ int sysno,
+ std::vector<uint64_t>* aux) {
if (!SandboxBPF::IsValidSyscallNumber(sysno)) {
return ErrorCode(ENOSYS);
}
@@ -94,7 +96,7 @@ ErrorCode CopyAllArgsOnUnamePolicy(SandboxBPF* sandbox, int sysno, void* aux) {
BPF_TEST(Syscall,
SyntheticSixArgs,
CopyAllArgsOnUnamePolicy,
- std::vector<uint64_t> /* BPF_AUX */) {
+ std::vector<uint64_t> /* (*BPF_AUX) */) {
const int kExpectedValue = 42;
// In this test we only pass integers to the kernel. We might want to make
// additional tests to try other types. What we will see depends on
@@ -116,17 +118,17 @@ BPF_TEST(Syscall,
syscall_args[5]) == -ENOMEM);
// We expect the trap handler to have copied the 6 arguments.
- BPF_ASSERT(BPF_AUX.size() == 6);
+ BPF_ASSERT(BPF_AUX->size() == 6);
// Don't loop here so that we can see which argument does cause the failure
// easily from the failing line.
// uint64_t is the type passed to our SIGSYS handler.
- BPF_ASSERT(BPF_AUX[0] == static_cast<uint64_t>(syscall_args[0]));
- BPF_ASSERT(BPF_AUX[1] == static_cast<uint64_t>(syscall_args[1]));
- BPF_ASSERT(BPF_AUX[2] == static_cast<uint64_t>(syscall_args[2]));
- BPF_ASSERT(BPF_AUX[3] == static_cast<uint64_t>(syscall_args[3]));
- BPF_ASSERT(BPF_AUX[4] == static_cast<uint64_t>(syscall_args[4]));
- BPF_ASSERT(BPF_AUX[5] == static_cast<uint64_t>(syscall_args[5]));
+ BPF_ASSERT((*BPF_AUX)[0] == static_cast<uint64_t>(syscall_args[0]));
+ BPF_ASSERT((*BPF_AUX)[1] == static_cast<uint64_t>(syscall_args[1]));
+ BPF_ASSERT((*BPF_AUX)[2] == static_cast<uint64_t>(syscall_args[2]));
+ BPF_ASSERT((*BPF_AUX)[3] == static_cast<uint64_t>(syscall_args[3]));
+ BPF_ASSERT((*BPF_AUX)[4] == static_cast<uint64_t>(syscall_args[4]));
+ BPF_ASSERT((*BPF_AUX)[5] == static_cast<uint64_t>(syscall_args[5]));
}
TEST(Syscall, ComplexSyscallSixArgs) {
diff --git a/sandbox/linux/suid/client/DEPS b/sandbox/linux/suid/client/DEPS
new file mode 100644
index 0000000000..99a337d772
--- /dev/null
+++ b/sandbox/linux/suid/client/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+sandbox/linux/services",
+]
diff --git a/sandbox/linux/suid/client/setuid_sandbox_client.cc b/sandbox/linux/suid/client/setuid_sandbox_client.cc
index 3300cb440f..fc03cdd099 100644
--- a/sandbox/linux/suid/client/setuid_sandbox_client.cc
+++ b/sandbox/linux/suid/client/setuid_sandbox_client.cc
@@ -5,6 +5,8 @@
#include "sandbox/linux/suid/client/setuid_sandbox_client.h"
#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
@@ -136,7 +138,7 @@ namespace sandbox {
SetuidSandboxClient* SetuidSandboxClient::Create() {
base::Environment* environment(base::Environment::Create());
- SetuidSandboxClient* sandbox_client(new(SetuidSandboxClient));
+ SetuidSandboxClient* sandbox_client(new SetuidSandboxClient);
CHECK(environment);
sandbox_client->env_ = environment;
@@ -152,6 +154,21 @@ SetuidSandboxClient::~SetuidSandboxClient() {
delete env_;
}
+void SetuidSandboxClient::CloseDummyFile() {
+ // When we're launched through the setuid sandbox, SetupLaunchOptions
+ // arranges for kZygoteIdFd to be a dummy file descriptor to satisfy an
+ // ancient setuid sandbox ABI requirement. However, the descriptor is no
+ // longer needed, so we can simply close it right away now.
+ CHECK(IsSuidSandboxChild());
+
+ // Sanity check that kZygoteIdFd refers to a pipe.
+ struct stat st;
+ PCHECK(0 == fstat(kZygoteIdFd, &st));
+ CHECK(S_ISFIFO(st.st_mode));
+
+ PCHECK(0 == IGNORE_EINTR(close(kZygoteIdFd)));
+}
+
bool SetuidSandboxClient::ChrootMe() {
int ipc_fd = GetIPCDescriptor(env_);
@@ -226,12 +243,6 @@ bool SetuidSandboxClient::IsDisabledViaEnvironment() {
return false;
}
-int SetuidSandboxClient::GetUniqueToChildFileDescriptor() {
- // The setuid binary is hard-wired to close this in the helper process it
- // creates.
- return kZygoteIdFd;
-}
-
base::FilePath SetuidSandboxClient::GetSandboxBinaryPath() {
base::FilePath sandbox_binary;
base::FilePath exe_dir;
@@ -256,8 +267,7 @@ base::FilePath SetuidSandboxClient::GetSandboxBinaryPath() {
return sandbox_binary;
}
-void SetuidSandboxClient::PrependWrapper(base::CommandLine* cmd_line,
- base::LaunchOptions* options) {
+void SetuidSandboxClient::PrependWrapper(base::CommandLine* cmd_line) {
std::string sandbox_binary(GetSandboxBinaryPath().value());
struct stat st;
if (sandbox_binary.empty() || stat(sandbox_binary.c_str(), &st) != 0) {
@@ -275,15 +285,30 @@ void SetuidSandboxClient::PrependWrapper(base::CommandLine* cmd_line,
<< sandbox_binary << " is owned by root and has mode 4755.";
}
- if (cmd_line) {
- cmd_line->PrependWrapper(sandbox_binary);
- }
+ cmd_line->PrependWrapper(sandbox_binary);
+}
- if (options) {
- // Launching a setuid binary requires PR_SET_NO_NEW_PRIVS to not be used.
- options->allow_new_privs = true;
- UnsetExpectedEnvironmentVariables(&options->environ);
- }
+void SetuidSandboxClient::SetupLaunchOptions(
+ base::LaunchOptions* options,
+ base::FileHandleMappingVector* fds_to_remap,
+ base::ScopedFD* dummy_fd) {
+ DCHECK(options);
+ DCHECK(fds_to_remap);
+
+ // Launching a setuid binary requires PR_SET_NO_NEW_PRIVS to not be used.
+ options->allow_new_privs = true;
+ UnsetExpectedEnvironmentVariables(&options->environ);
+
+ // Set dummy_fd to the reading end of a closed pipe.
+ int pipe_fds[2];
+ PCHECK(0 == pipe(pipe_fds));
+ PCHECK(0 == IGNORE_EINTR(close(pipe_fds[1])));
+ dummy_fd->reset(pipe_fds[0]);
+
+ // We no longer need a dummy socket for discovering the child's PID,
+ // but the sandbox is still hard-coded to expect a file descriptor at
+ // kZygoteIdFd. Fixing this requires a sandbox API change. :(
+ fds_to_remap->push_back(std::make_pair(dummy_fd->get(), kZygoteIdFd));
}
void SetuidSandboxClient::SetupLaunchEnvironment() {
diff --git a/sandbox/linux/suid/client/setuid_sandbox_client.h b/sandbox/linux/suid/client/setuid_sandbox_client.h
index 332c63b69c..2bbad7a8bd 100644
--- a/sandbox/linux/suid/client/setuid_sandbox_client.h
+++ b/sandbox/linux/suid/client/setuid_sandbox_client.h
@@ -8,14 +8,10 @@
#include "base/basictypes.h"
#include "base/callback_forward.h"
#include "base/files/file_path.h"
+#include "base/files/scoped_file.h"
+#include "base/process/launch.h"
#include "sandbox/linux/sandbox_export.h"
-namespace base {
-class CommandLine;
-class Environment;
-struct LaunchOptions;
-}
-
namespace sandbox {
// Helper class to use the setuid sandbox. This class is to be used both
@@ -28,23 +24,21 @@ namespace sandbox {
// 1. A calls SetupLaunchEnvironment()
// 2. A sets up a CommandLine and then amends it with
// PrependWrapper() (or manually, by relying on GetSandboxBinaryPath()).
-// 3. A makes sure that GetUniqueToChildFileDescriptor() is an existing file
-// descriptor that can be closed by the helper process created by the
-// setuid sandbox. (This is the right file descriptor to use for magic
-// "must-be-unique" sockets that are use to identify processes across
-// pid namespaces.)
+// 3. A uses SetupLaunchOptions() to arrange for a dummy descriptor for the
+// setuid sandbox ABI.
// 4. A launches B with base::LaunchProcess, using the amended CommandLine.
-// 5. B performs various initializations that require access to the file
+// 5. B uses CloseDummyFile() to close the dummy file descriptor.
+// 6. B performs various initializations that require access to the file
// system.
-// 5.b (optional) B uses sandbox::Credentials::HasOpenDirectory() to verify
+// 6.b (optional) B uses sandbox::Credentials::HasOpenDirectory() to verify
// that no directory is kept open (which would allow bypassing the setuid
// sandbox).
-// 6. B should be prepared to assume the role of init(1). In particular, B
+// 7. B should be prepared to assume the role of init(1). In particular, B
// cannot receive any signal from any other process, excluding SIGKILL.
// If B dies, all the processes in the namespace will die.
// B can fork() and the parent can assume the role of init(1), by using
// CreateInitProcessReaper().
-// 7. B requests being chroot-ed through ChrootMe() and
+// 8. B requests being chroot-ed through ChrootMe() and
// requests other sandboxing status via the status functions.
class SANDBOX_EXPORT SetuidSandboxClient {
public:
@@ -52,6 +46,8 @@ class SANDBOX_EXPORT SetuidSandboxClient {
static class SetuidSandboxClient* Create();
~SetuidSandboxClient();
+ // Close the dummy file descriptor leftover from the sandbox ABI.
+ void CloseDummyFile();
// Ask the setuid helper over the setuid sandbox IPC channel to chroot() us
// to an empty directory.
// Will only work if we have been launched through the setuid helper.
@@ -76,22 +72,21 @@ class SANDBOX_EXPORT SetuidSandboxClient {
// The setuid sandbox may still be disabled via the environment.
// This is tracked in crbug.com/245376.
bool IsDisabledViaEnvironment();
- // When using the setuid sandbox, an extra helper process is created.
- // Unfortunately, this helper process is hard-wired to close a specific file
- // descriptor.
- // The caller must make sure that GetUniqueToChildFileDescriptor() is an
- // existing file descriptor that can be closed by the helper process. It's ok
- // to make it a dummy, useless file descriptor if needed.
- int GetUniqueToChildFileDescriptor();
// Get the sandbox binary path. This method knows about the
// CHROME_DEVEL_SANDBOX environment variable used for user-managed builds. If
// the sandbox binary cannot be found, it will return an empty FilePath.
base::FilePath GetSandboxBinaryPath();
- // Modify |cmd_line| and |options| to launch via the setuid sandbox. Crash if
- // the setuid sandbox binary cannot be found. Either can be NULL if the caller
- // needs additional control.
- void PrependWrapper(base::CommandLine* cmd_line,
- base::LaunchOptions* options);
+ // Modify |cmd_line| to launch via the setuid sandbox. Crash if the setuid
+ // sandbox binary cannot be found. |cmd_line| must not be NULL.
+ void PrependWrapper(base::CommandLine* cmd_line);
+ // Set-up the launch options for launching via the setuid sandbox. Caller is
+ // responsible for keeping |dummy_fd| alive until LaunchProcess() completes.
+ // |options| and |fds_to_remap| must not be NULL.
+ // (Keeping |dummy_fd| alive is an unfortunate historical artifact of the
+ // chrome-sandbox ABI.)
+ void SetupLaunchOptions(base::LaunchOptions* options,
+ base::FileHandleMappingVector* fds_to_remap,
+ base::ScopedFD* dummy_fd);
// Set-up the environment. This should be done prior to launching the setuid
// helper.
void SetupLaunchEnvironment();
@@ -106,4 +101,3 @@ class SANDBOX_EXPORT SetuidSandboxClient {
} // namespace sandbox
#endif // SANDBOX_LINUX_SUID_SETUID_SANDBOX_CLIENT_H_
-
diff --git a/sandbox/linux/tests/sandbox_test_runner.h b/sandbox/linux/tests/sandbox_test_runner.h
new file mode 100644
index 0000000000..4cb7102ff9
--- /dev/null
+++ b/sandbox/linux/tests/sandbox_test_runner.h
@@ -0,0 +1,25 @@
+// 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 SANDBOX_LINUX_TESTS_SANDBOX_TEST_RUNNER_H_
+#define SANDBOX_LINUX_TESTS_SANDBOX_TEST_RUNNER_H_
+
+#include "base/basictypes.h"
+
+namespace sandbox {
+
+// A simple "runner" class to implement tests.
+class SandboxTestRunner {
+ public:
+ SandboxTestRunner() {}
+ virtual ~SandboxTestRunner() {}
+ virtual void Run() = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SandboxTestRunner);
+};
+
+} // namespace sandbox
+
+#endif // SANDBOX_LINUX_TESTS_SANDBOX_TEST_RUNNER_H_
diff --git a/sandbox/linux/tests/sandbox_test_runner_function_pointer.cc b/sandbox/linux/tests/sandbox_test_runner_function_pointer.cc
new file mode 100644
index 0000000000..69e05ac4e0
--- /dev/null
+++ b/sandbox/linux/tests/sandbox_test_runner_function_pointer.cc
@@ -0,0 +1,25 @@
+// 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/tests/sandbox_test_runner_function_pointer.h"
+
+#include "base/logging.h"
+#include "build/build_config.h"
+
+namespace sandbox {
+
+SandboxTestRunnerFunctionPointer::SandboxTestRunnerFunctionPointer(
+ void (*function_to_run)(void))
+ : function_to_run_(function_to_run) {
+}
+
+SandboxTestRunnerFunctionPointer::~SandboxTestRunnerFunctionPointer() {
+}
+
+void SandboxTestRunnerFunctionPointer::Run() {
+ DCHECK(function_to_run_);
+ function_to_run_();
+}
+
+} // namespace sandbox
diff --git a/sandbox/linux/tests/sandbox_test_runner_function_pointer.h b/sandbox/linux/tests/sandbox_test_runner_function_pointer.h
new file mode 100644
index 0000000000..1cb709f14c
--- /dev/null
+++ b/sandbox/linux/tests/sandbox_test_runner_function_pointer.h
@@ -0,0 +1,26 @@
+// 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 SANDBOX_LINUX_TESTS_SANDBOX_TEST_RUNNER_FUNCTION_POINTER_H_
+#define SANDBOX_LINUX_TESTS_SANDBOX_TEST_RUNNER_FUNCTION_POINTER_H_
+
+#include "base/basictypes.h"
+#include "sandbox/linux/tests/sandbox_test_runner.h"
+
+namespace sandbox {
+
+class SandboxTestRunnerFunctionPointer : public SandboxTestRunner {
+ public:
+ SandboxTestRunnerFunctionPointer(void (*function_to_run)(void));
+ virtual ~SandboxTestRunnerFunctionPointer() OVERRIDE;
+ virtual void Run() OVERRIDE;
+
+ private:
+ void (*function_to_run_)(void);
+ DISALLOW_COPY_AND_ASSIGN(SandboxTestRunnerFunctionPointer);
+};
+
+} // namespace sandbox
+
+#endif // SANDBOX_LINUX_TESTS_SANDBOX_TEST_RUNNER__FUNCTION_POINTER_H_
diff --git a/sandbox/linux/tests/unit_tests.cc b/sandbox/linux/tests/unit_tests.cc
index 42b85a8d6f..d3ee81b36b 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"
@@ -105,10 +106,10 @@ static void SetProcessTimeout(int time_in_seconds) {
// in the BPF sandbox, as it potentially makes global state changes and as
// it also tends to raise fatal errors, if the code has been used in an
// insecure manner.
-void UnitTests::RunTestInProcess(UnitTests::Test test,
- void* arg,
+void UnitTests::RunTestInProcess(SandboxTestRunner* test_runner,
DeathCheck death,
const void* death_aux) {
+ CHECK(test_runner);
// We need to fork(), so we can't be multi-threaded, as threads could hold
// locks.
int num_threads = CountThreads();
@@ -174,7 +175,7 @@ void UnitTests::RunTestInProcess(UnitTests::Test test,
struct rlimit no_core = {0};
setrlimit(RLIMIT_CORE, &no_core);
- test(arg);
+ test_runner->Run();
_exit(kExpectedValue);
}
diff --git a/sandbox/linux/tests/unit_tests.h b/sandbox/linux/tests/unit_tests.h
index bc1939c9a1..9531595009 100644
--- a/sandbox/linux/tests/unit_tests.h
+++ b/sandbox/linux/tests/unit_tests.h
@@ -7,6 +7,7 @@
#include "base/basictypes.h"
#include "build/build_config.h"
+#include "sandbox/linux/tests/sandbox_test_runner_function_pointer.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace sandbox {
@@ -62,12 +63,13 @@ bool IsRunningOnValgrind();
// that the test actually dies. The death test only passes if the death occurs
// in the expected fashion, as specified by "death" and "death_aux". These two
// parameters are typically set to one of the DEATH_XXX() macros.
-#define SANDBOX_DEATH_TEST(test_case_name, test_name, death) \
- void TEST_##test_name(void*); \
- TEST(test_case_name, test_name) { \
- sandbox::UnitTests::RunTestInProcess(TEST_##test_name, NULL, death); \
- } \
- void TEST_##test_name(void*)
+#define SANDBOX_DEATH_TEST(test_case_name, test_name, death) \
+ void TEST_##test_name(void); \
+ TEST(test_case_name, test_name) { \
+ SandboxTestRunnerFunctionPointer sandbox_test_runner(TEST_##test_name); \
+ sandbox::UnitTests::RunTestInProcess(&sandbox_test_runner, death); \
+ } \
+ void TEST_##test_name(void)
// Define a new test case that runs inside of a GTest death test. This is
// necessary, as most of our tests by definition make global and irreversible
@@ -88,9 +90,10 @@ bool IsRunningOnValgrind();
((expr) ? static_cast<void>(0) : sandbox::UnitTests::AssertionFailure( \
SANDBOX_STR(expr), __FILE__, __LINE__))
+// This class allows to run unittests in their own process. The main method is
+// RunTestInProcess().
class UnitTests {
public:
- typedef void (*Test)(void*);
typedef void (*DeathCheck)(int status,
const std::string& msg,
const void* aux);
@@ -99,8 +102,12 @@ class UnitTests {
// directly. It is automatically invoked by SANDBOX_TEST(). Most sandboxing
// functions make global irreversible changes to the execution environment
// and must therefore execute in their own isolated process.
- static void RunTestInProcess(Test test,
- void* arg,
+ // |test_runner| must implement the SandboxTestRunner interface and will run
+ // in a subprocess.
+ // Note: since the child process (created with fork()) will never return from
+ // RunTestInProcess(), |test_runner| is guaranteed to exist for the lifetime
+ // of the child process.
+ static void RunTestInProcess(SandboxTestRunner* test_runner,
DeathCheck death,
const void* death_aux);
diff --git a/sandbox/sandbox_services.target.darwin-arm.mk b/sandbox/sandbox_services.target.darwin-arm.mk
index 3a93b3ea19..248a767a67 100644
--- a/sandbox/sandbox_services.target.darwin-arm.mk
+++ b/sandbox/sandbox_services.target.darwin-arm.mk
@@ -45,7 +45,6 @@ MY_CFLAGS_Debug := \
-pipe \
-fPIC \
-fno-tree-sra \
- -fuse-ld=gold \
-Wno-psabi \
-ffunction-sections \
-funwind-tables \
@@ -133,7 +132,6 @@ MY_CFLAGS_Release := \
-pipe \
-fPIC \
-fno-tree-sra \
- -fuse-ld=gold \
-Wno-psabi \
-ffunction-sections \
-funwind-tables \
diff --git a/sandbox/sandbox_services.target.darwin-x86.mk b/sandbox/sandbox_services.target.darwin-x86.mk
index 47be915aed..3eb1812e00 100644
--- a/sandbox/sandbox_services.target.darwin-x86.mk
+++ b/sandbox/sandbox_services.target.darwin-x86.mk
@@ -47,7 +47,6 @@ MY_CFLAGS_Debug := \
-mfpmath=sse \
-mmmx \
-m32 \
- -fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
-g \
@@ -135,7 +134,6 @@ MY_CFLAGS_Release := \
-mfpmath=sse \
-mmmx \
-m32 \
- -fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
-g \
diff --git a/sandbox/sandbox_services.target.darwin-x86_64.mk b/sandbox/sandbox_services.target.darwin-x86_64.mk
index 5982b2c1fe..ee7ac3d5ed 100644
--- a/sandbox/sandbox_services.target.darwin-x86_64.mk
+++ b/sandbox/sandbox_services.target.darwin-x86_64.mk
@@ -47,7 +47,6 @@ MY_CFLAGS_Debug := \
-Wno-unused-local-typedefs \
-m64 \
-march=x86-64 \
- -fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
-g \
@@ -135,7 +134,6 @@ MY_CFLAGS_Release := \
-Wno-unused-local-typedefs \
-m64 \
-march=x86-64 \
- -fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
-g \
diff --git a/sandbox/sandbox_services.target.linux-arm.mk b/sandbox/sandbox_services.target.linux-arm.mk
index 3a93b3ea19..248a767a67 100644
--- a/sandbox/sandbox_services.target.linux-arm.mk
+++ b/sandbox/sandbox_services.target.linux-arm.mk
@@ -45,7 +45,6 @@ MY_CFLAGS_Debug := \
-pipe \
-fPIC \
-fno-tree-sra \
- -fuse-ld=gold \
-Wno-psabi \
-ffunction-sections \
-funwind-tables \
@@ -133,7 +132,6 @@ MY_CFLAGS_Release := \
-pipe \
-fPIC \
-fno-tree-sra \
- -fuse-ld=gold \
-Wno-psabi \
-ffunction-sections \
-funwind-tables \
diff --git a/sandbox/sandbox_services.target.linux-x86.mk b/sandbox/sandbox_services.target.linux-x86.mk
index 47be915aed..3eb1812e00 100644
--- a/sandbox/sandbox_services.target.linux-x86.mk
+++ b/sandbox/sandbox_services.target.linux-x86.mk
@@ -47,7 +47,6 @@ MY_CFLAGS_Debug := \
-mfpmath=sse \
-mmmx \
-m32 \
- -fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
-g \
@@ -135,7 +134,6 @@ MY_CFLAGS_Release := \
-mfpmath=sse \
-mmmx \
-m32 \
- -fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
-g \
diff --git a/sandbox/sandbox_services.target.linux-x86_64.mk b/sandbox/sandbox_services.target.linux-x86_64.mk
index 5982b2c1fe..ee7ac3d5ed 100644
--- a/sandbox/sandbox_services.target.linux-x86_64.mk
+++ b/sandbox/sandbox_services.target.linux-x86_64.mk
@@ -47,7 +47,6 @@ MY_CFLAGS_Debug := \
-Wno-unused-local-typedefs \
-m64 \
-march=x86-64 \
- -fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
-g \
@@ -135,7 +134,6 @@ MY_CFLAGS_Release := \
-Wno-unused-local-typedefs \
-m64 \
-march=x86-64 \
- -fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
-g \
diff --git a/sandbox/sandbox_services_headers.target.darwin-arm.mk b/sandbox/sandbox_services_headers.target.darwin-arm.mk
index 054f04cd31..d2b380eef7 100644
--- a/sandbox/sandbox_services_headers.target.darwin-arm.mk
+++ b/sandbox/sandbox_services_headers.target.darwin-arm.mk
@@ -40,7 +40,6 @@ MY_CFLAGS_Debug := \
-pipe \
-fPIC \
-fno-tree-sra \
- -fuse-ld=gold \
-Wno-psabi \
-ffunction-sections \
-funwind-tables \
@@ -125,7 +124,6 @@ MY_CFLAGS_Release := \
-pipe \
-fPIC \
-fno-tree-sra \
- -fuse-ld=gold \
-Wno-psabi \
-ffunction-sections \
-funwind-tables \
diff --git a/sandbox/sandbox_services_headers.target.darwin-x86.mk b/sandbox/sandbox_services_headers.target.darwin-x86.mk
index a9f35a99ac..cf8421a11e 100644
--- a/sandbox/sandbox_services_headers.target.darwin-x86.mk
+++ b/sandbox/sandbox_services_headers.target.darwin-x86.mk
@@ -42,7 +42,6 @@ MY_CFLAGS_Debug := \
-mfpmath=sse \
-mmmx \
-m32 \
- -fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
-g \
@@ -127,7 +126,6 @@ MY_CFLAGS_Release := \
-mfpmath=sse \
-mmmx \
-m32 \
- -fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
-g \
diff --git a/sandbox/sandbox_services_headers.target.darwin-x86_64.mk b/sandbox/sandbox_services_headers.target.darwin-x86_64.mk
index bc9fbc3f5e..4d6658efe3 100644
--- a/sandbox/sandbox_services_headers.target.darwin-x86_64.mk
+++ b/sandbox/sandbox_services_headers.target.darwin-x86_64.mk
@@ -42,7 +42,6 @@ MY_CFLAGS_Debug := \
-Wno-unused-local-typedefs \
-m64 \
-march=x86-64 \
- -fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
-g \
@@ -127,7 +126,6 @@ MY_CFLAGS_Release := \
-Wno-unused-local-typedefs \
-m64 \
-march=x86-64 \
- -fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
-g \
diff --git a/sandbox/sandbox_services_headers.target.linux-arm.mk b/sandbox/sandbox_services_headers.target.linux-arm.mk
index 054f04cd31..d2b380eef7 100644
--- a/sandbox/sandbox_services_headers.target.linux-arm.mk
+++ b/sandbox/sandbox_services_headers.target.linux-arm.mk
@@ -40,7 +40,6 @@ MY_CFLAGS_Debug := \
-pipe \
-fPIC \
-fno-tree-sra \
- -fuse-ld=gold \
-Wno-psabi \
-ffunction-sections \
-funwind-tables \
@@ -125,7 +124,6 @@ MY_CFLAGS_Release := \
-pipe \
-fPIC \
-fno-tree-sra \
- -fuse-ld=gold \
-Wno-psabi \
-ffunction-sections \
-funwind-tables \
diff --git a/sandbox/sandbox_services_headers.target.linux-x86.mk b/sandbox/sandbox_services_headers.target.linux-x86.mk
index a9f35a99ac..cf8421a11e 100644
--- a/sandbox/sandbox_services_headers.target.linux-x86.mk
+++ b/sandbox/sandbox_services_headers.target.linux-x86.mk
@@ -42,7 +42,6 @@ MY_CFLAGS_Debug := \
-mfpmath=sse \
-mmmx \
-m32 \
- -fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
-g \
@@ -127,7 +126,6 @@ MY_CFLAGS_Release := \
-mfpmath=sse \
-mmmx \
-m32 \
- -fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
-g \
diff --git a/sandbox/sandbox_services_headers.target.linux-x86_64.mk b/sandbox/sandbox_services_headers.target.linux-x86_64.mk
index bc9fbc3f5e..4d6658efe3 100644
--- a/sandbox/sandbox_services_headers.target.linux-x86_64.mk
+++ b/sandbox/sandbox_services_headers.target.linux-x86_64.mk
@@ -42,7 +42,6 @@ MY_CFLAGS_Debug := \
-Wno-unused-local-typedefs \
-m64 \
-march=x86-64 \
- -fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
-g \
@@ -127,7 +126,6 @@ MY_CFLAGS_Release := \
-Wno-unused-local-typedefs \
-m64 \
-march=x86-64 \
- -fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
-g \
diff --git a/sandbox/seccomp_bpf.target.darwin-arm.mk b/sandbox/seccomp_bpf.target.darwin-arm.mk
index 97a5d03e8d..e232e263fc 100644
--- a/sandbox/seccomp_bpf.target.darwin-arm.mk
+++ b/sandbox/seccomp_bpf.target.darwin-arm.mk
@@ -50,7 +50,6 @@ MY_CFLAGS_Debug := \
-pipe \
-fPIC \
-fno-tree-sra \
- -fuse-ld=gold \
-Wno-psabi \
-ffunction-sections \
-funwind-tables \
@@ -137,7 +136,6 @@ MY_CFLAGS_Release := \
-pipe \
-fPIC \
-fno-tree-sra \
- -fuse-ld=gold \
-Wno-psabi \
-ffunction-sections \
-funwind-tables \
diff --git a/sandbox/seccomp_bpf.target.darwin-x86.mk b/sandbox/seccomp_bpf.target.darwin-x86.mk
index 1feffcddc3..be3488fa02 100644
--- a/sandbox/seccomp_bpf.target.darwin-x86.mk
+++ b/sandbox/seccomp_bpf.target.darwin-x86.mk
@@ -52,7 +52,6 @@ MY_CFLAGS_Debug := \
-mfpmath=sse \
-mmmx \
-m32 \
- -fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
-g \
@@ -139,7 +138,6 @@ MY_CFLAGS_Release := \
-mfpmath=sse \
-mmmx \
-m32 \
- -fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
-g \
diff --git a/sandbox/seccomp_bpf.target.darwin-x86_64.mk b/sandbox/seccomp_bpf.target.darwin-x86_64.mk
index 677a5ef678..6180638e1a 100644
--- a/sandbox/seccomp_bpf.target.darwin-x86_64.mk
+++ b/sandbox/seccomp_bpf.target.darwin-x86_64.mk
@@ -52,7 +52,6 @@ MY_CFLAGS_Debug := \
-Wno-unused-local-typedefs \
-m64 \
-march=x86-64 \
- -fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
-g \
@@ -139,7 +138,6 @@ MY_CFLAGS_Release := \
-Wno-unused-local-typedefs \
-m64 \
-march=x86-64 \
- -fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
-g \
diff --git a/sandbox/seccomp_bpf.target.linux-arm.mk b/sandbox/seccomp_bpf.target.linux-arm.mk
index 97a5d03e8d..e232e263fc 100644
--- a/sandbox/seccomp_bpf.target.linux-arm.mk
+++ b/sandbox/seccomp_bpf.target.linux-arm.mk
@@ -50,7 +50,6 @@ MY_CFLAGS_Debug := \
-pipe \
-fPIC \
-fno-tree-sra \
- -fuse-ld=gold \
-Wno-psabi \
-ffunction-sections \
-funwind-tables \
@@ -137,7 +136,6 @@ MY_CFLAGS_Release := \
-pipe \
-fPIC \
-fno-tree-sra \
- -fuse-ld=gold \
-Wno-psabi \
-ffunction-sections \
-funwind-tables \
diff --git a/sandbox/seccomp_bpf.target.linux-x86.mk b/sandbox/seccomp_bpf.target.linux-x86.mk
index 1feffcddc3..be3488fa02 100644
--- a/sandbox/seccomp_bpf.target.linux-x86.mk
+++ b/sandbox/seccomp_bpf.target.linux-x86.mk
@@ -52,7 +52,6 @@ MY_CFLAGS_Debug := \
-mfpmath=sse \
-mmmx \
-m32 \
- -fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
-g \
@@ -139,7 +138,6 @@ MY_CFLAGS_Release := \
-mfpmath=sse \
-mmmx \
-m32 \
- -fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
-g \
diff --git a/sandbox/seccomp_bpf.target.linux-x86_64.mk b/sandbox/seccomp_bpf.target.linux-x86_64.mk
index 677a5ef678..6180638e1a 100644
--- a/sandbox/seccomp_bpf.target.linux-x86_64.mk
+++ b/sandbox/seccomp_bpf.target.linux-x86_64.mk
@@ -52,7 +52,6 @@ MY_CFLAGS_Debug := \
-Wno-unused-local-typedefs \
-m64 \
-march=x86-64 \
- -fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
-g \
@@ -139,7 +138,6 @@ MY_CFLAGS_Release := \
-Wno-unused-local-typedefs \
-m64 \
-march=x86-64 \
- -fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
-g \
diff --git a/sandbox/seccomp_bpf_helpers.target.darwin-arm.mk b/sandbox/seccomp_bpf_helpers.target.darwin-arm.mk
index 891944d7c7..2f1569a824 100644
--- a/sandbox/seccomp_bpf_helpers.target.darwin-arm.mk
+++ b/sandbox/seccomp_bpf_helpers.target.darwin-arm.mk
@@ -44,7 +44,6 @@ MY_CFLAGS_Debug := \
-pipe \
-fPIC \
-fno-tree-sra \
- -fuse-ld=gold \
-Wno-psabi \
-ffunction-sections \
-funwind-tables \
@@ -131,7 +130,6 @@ MY_CFLAGS_Release := \
-pipe \
-fPIC \
-fno-tree-sra \
- -fuse-ld=gold \
-Wno-psabi \
-ffunction-sections \
-funwind-tables \
diff --git a/sandbox/seccomp_bpf_helpers.target.darwin-x86.mk b/sandbox/seccomp_bpf_helpers.target.darwin-x86.mk
index 9f6a44238d..c537e98163 100644
--- a/sandbox/seccomp_bpf_helpers.target.darwin-x86.mk
+++ b/sandbox/seccomp_bpf_helpers.target.darwin-x86.mk
@@ -46,7 +46,6 @@ MY_CFLAGS_Debug := \
-mfpmath=sse \
-mmmx \
-m32 \
- -fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
-g \
@@ -133,7 +132,6 @@ MY_CFLAGS_Release := \
-mfpmath=sse \
-mmmx \
-m32 \
- -fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
-g \
diff --git a/sandbox/seccomp_bpf_helpers.target.darwin-x86_64.mk b/sandbox/seccomp_bpf_helpers.target.darwin-x86_64.mk
index 1309413df3..59ad6c3983 100644
--- a/sandbox/seccomp_bpf_helpers.target.darwin-x86_64.mk
+++ b/sandbox/seccomp_bpf_helpers.target.darwin-x86_64.mk
@@ -46,7 +46,6 @@ MY_CFLAGS_Debug := \
-Wno-unused-local-typedefs \
-m64 \
-march=x86-64 \
- -fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
-g \
@@ -133,7 +132,6 @@ MY_CFLAGS_Release := \
-Wno-unused-local-typedefs \
-m64 \
-march=x86-64 \
- -fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
-g \
diff --git a/sandbox/seccomp_bpf_helpers.target.linux-arm.mk b/sandbox/seccomp_bpf_helpers.target.linux-arm.mk
index 891944d7c7..2f1569a824 100644
--- a/sandbox/seccomp_bpf_helpers.target.linux-arm.mk
+++ b/sandbox/seccomp_bpf_helpers.target.linux-arm.mk
@@ -44,7 +44,6 @@ MY_CFLAGS_Debug := \
-pipe \
-fPIC \
-fno-tree-sra \
- -fuse-ld=gold \
-Wno-psabi \
-ffunction-sections \
-funwind-tables \
@@ -131,7 +130,6 @@ MY_CFLAGS_Release := \
-pipe \
-fPIC \
-fno-tree-sra \
- -fuse-ld=gold \
-Wno-psabi \
-ffunction-sections \
-funwind-tables \
diff --git a/sandbox/seccomp_bpf_helpers.target.linux-x86.mk b/sandbox/seccomp_bpf_helpers.target.linux-x86.mk
index 9f6a44238d..c537e98163 100644
--- a/sandbox/seccomp_bpf_helpers.target.linux-x86.mk
+++ b/sandbox/seccomp_bpf_helpers.target.linux-x86.mk
@@ -46,7 +46,6 @@ MY_CFLAGS_Debug := \
-mfpmath=sse \
-mmmx \
-m32 \
- -fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
-g \
@@ -133,7 +132,6 @@ MY_CFLAGS_Release := \
-mfpmath=sse \
-mmmx \
-m32 \
- -fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
-g \
diff --git a/sandbox/seccomp_bpf_helpers.target.linux-x86_64.mk b/sandbox/seccomp_bpf_helpers.target.linux-x86_64.mk
index 1309413df3..59ad6c3983 100644
--- a/sandbox/seccomp_bpf_helpers.target.linux-x86_64.mk
+++ b/sandbox/seccomp_bpf_helpers.target.linux-x86_64.mk
@@ -46,7 +46,6 @@ MY_CFLAGS_Debug := \
-Wno-unused-local-typedefs \
-m64 \
-march=x86-64 \
- -fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
-g \
@@ -133,7 +132,6 @@ MY_CFLAGS_Release := \
-Wno-unused-local-typedefs \
-m64 \
-march=x86-64 \
- -fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
-g \