summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhidehiko <hidehiko@chromium.org>2015-04-30 22:16:05 -0700
committerCommit bot <commit-bot@chromium.org>2015-05-01 05:16:34 +0000
commitaca25fdd9772e974b0399c24590fd864cebfcbab (patch)
tree04504d176310117a6a6f2c214a56587d3f5468ee
parent7f841930479d87f5c65082d26cc764883c1cd5dc (diff)
downloadchromium_src-aca25fdd9772e974b0399c24590fd864cebfcbab.zip
chromium_src-aca25fdd9772e974b0399c24590fd864cebfcbab.tar.gz
chromium_src-aca25fdd9772e974b0399c24590fd864cebfcbab.tar.bz2
Non-SFI mode: Enable seccomp-bpf sandbox on nacl_helper_nonsfi.
This CL enables seccomp-bpf sandbox on nacl_helper_nonsfi. In codegen.cc, static_cast is added as implicit narrowing triggers compiler warning (= error with -Werror), with PNaCl toolchain. TEST=Ran bots. Ran ./sandbox_linux_unittests and ./nacl_loader_unittests locally with {Debug,Release} * {clang,gcc,msan,tsan} combinations. Ran ./browser_tests --gtest_filter=*NaCl*:*PPAPI* locally with {Release} * {clang,gcc,msan} combinations. Test an app using Non-SFI mode already with --use-nacl-helper-nonsfi. BUG=358465 Review URL: https://codereview.chromium.org/1104993002 Cr-Commit-Position: refs/heads/master@{#327880}
-rw-r--r--components/nacl/loader/nacl_helper_linux.cc4
-rw-r--r--components/nacl/loader/nonsfi/nonsfi_sandbox.cc32
-rw-r--r--components/nacl/loader/sandbox_linux/nacl_sandbox_linux.cc32
-rw-r--r--components/nacl_nonsfi.gyp1
-rw-r--r--content/common/sandbox_linux/sandbox_init_linux.cc2
-rw-r--r--content/common/sandbox_linux/sandbox_seccomp_bpf_linux.cc40
-rw-r--r--content/content_nacl_nonsfi.gyp6
-rw-r--r--content/public/common/sandbox_init.h4
-rw-r--r--sandbox/linux/bpf_dsl/codegen.cc3
-rw-r--r--sandbox/linux/bpf_dsl/policy_compiler.cc1
-rw-r--r--sandbox/linux/bpf_dsl/seccomp_macros.h18
-rw-r--r--sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc38
-rw-r--r--sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h18
-rw-r--r--sandbox/linux/seccomp-bpf/syscall.cc12
-rw-r--r--sandbox/linux/seccomp-bpf/trap.cc21
-rw-r--r--sandbox/linux/seccomp-bpf/trap.h2
-rw-r--r--sandbox/linux/services/syscall_wrappers.cc11
-rw-r--r--sandbox/linux/system_headers/linux_futex.h2
-rw-r--r--sandbox/sandbox_nacl_nonsfi.gyp18
19 files changed, 166 insertions, 99 deletions
diff --git a/components/nacl/loader/nacl_helper_linux.cc b/components/nacl/loader/nacl_helper_linux.cc
index e7e75fb..8206eca 100644
--- a/components/nacl/loader/nacl_helper_linux.cc
+++ b/components/nacl/loader/nacl_helper_linux.cc
@@ -108,11 +108,7 @@ void BecomeNaClLoader(base::ScopedFD browser_fd,
// Finish layer-1 sandbox initialization and initialize the layer-2 sandbox.
CHECK(!nacl_sandbox->HasOpenDirectory());
-#if !defined(OS_NACL_NONSFI)
- // Currently Layer-two sandbox is not yet supported on nacl_helper_nonsfi.
- // TODO(hidehiko): Enable the sandbox.
nacl_sandbox->InitializeLayerTwoSandbox(uses_nonsfi_mode);
-#endif
nacl_sandbox->SealLayerOneSandbox();
nacl_sandbox->CheckSandboxingStateWithPolicy();
diff --git a/components/nacl/loader/nonsfi/nonsfi_sandbox.cc b/components/nacl/loader/nonsfi/nonsfi_sandbox.cc
index 2a6d5bc9..25493d6 100644
--- a/components/nacl/loader/nonsfi/nonsfi_sandbox.cc
+++ b/components/nacl/loader/nonsfi/nonsfi_sandbox.cc
@@ -6,7 +6,6 @@
#include <errno.h>
#include <fcntl.h>
-#include <linux/futex.h>
#include <linux/net.h>
#include <sys/mman.h>
#include <sys/prctl.h>
@@ -22,12 +21,21 @@
#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
+#include "sandbox/linux/system_headers/linux_futex.h"
#include "sandbox/linux/system_headers/linux_syscalls.h"
-#if defined(__arm__) && !defined(MAP_STACK)
-// Chrome OS Daisy (ARM) build environment has old headers.
-#define MAP_STACK 0x20000
-#endif
+// Chrome OS Daisy (ARM) build environment and PNaCl toolchain do not define
+// MAP_STACK.
+#if !defined(MAP_STACK)
+# if defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARM_FAMILY)
+# define MAP_STACK 0x20000
+# else
+// Note that, on other architecture, MAP_STACK has different value (e.g. mips'
+// MAP_STACK is 0x40000), though Non-SFI is not supported on such
+// architectures.
+# error "Unknown platform."
+# endif
+#endif // !defined(MAP_STACK)
#define CASES SANDBOX_BPF_DSL_CASES
@@ -68,11 +76,14 @@ ResultExpr RestrictFcntlCommands() {
ResultExpr RestrictClone() {
// We allow clone only for new thread creation.
+ int clone_flags =
+ CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
+ CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS;
+#if !defined(OS_NACL_NONSFI)
+ clone_flags |= CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID;
+#endif
const Arg<int> flags(0);
- return If(flags == (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
- CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS |
- CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID),
- Allow()).Else(CrashSIGSYSClone());
+ return If(flags == clone_flags, Allow()).Else(CrashSIGSYSClone());
}
ResultExpr RestrictFutexOperation() {
@@ -131,7 +142,10 @@ ResultExpr RestrictMmap() {
#if defined(__x86_64__) || defined(__arm__)
ResultExpr RestrictSocketpair() {
// Only allow AF_UNIX, PF_UNIX. Crash if anything else is seen.
+ // Note: PNaCl toolchain does not define PF_UNIX.
+#if !defined(OS_NACL_NONSFI)
static_assert(AF_UNIX == PF_UNIX, "AF_UNIX must equal PF_UNIX.");
+#endif
const Arg<int> domain(0);
return If(domain == AF_UNIX, Allow()).Else(CrashSIGSYS());
}
diff --git a/components/nacl/loader/sandbox_linux/nacl_sandbox_linux.cc b/components/nacl/loader/sandbox_linux/nacl_sandbox_linux.cc
index 17b7b84..869658f 100644
--- a/components/nacl/loader/sandbox_linux/nacl_sandbox_linux.cc
+++ b/components/nacl/loader/sandbox_linux/nacl_sandbox_linux.cc
@@ -30,13 +30,10 @@
#include "sandbox/linux/services/credentials.h"
#include "sandbox/linux/services/namespace_sandbox.h"
#include "sandbox/linux/services/proc_util.h"
+#include "sandbox/linux/services/resource_limits.h"
#include "sandbox/linux/services/thread_helpers.h"
#include "sandbox/linux/suid/client/setuid_sandbox_client.h"
-#if !defined(OS_NACL_NONSFI)
-#include "sandbox/linux/services/resource_limits.h"
-#endif
-
namespace nacl {
namespace {
@@ -66,10 +63,6 @@ bool MaybeSetProcessNonDumpable() {
return prctl(PR_GET_DUMPABLE) == 0;
}
-#if !defined(OS_NACL_NONSFI)
-// Currently Layer-two sandbox is not yet supported on nacl_helper_nonsfi.
-// This function is used only in InitializeLayerTwoSandbox().
-// TODO(hidehiko): Enable the sandbox.
void RestrictAddressSpaceUsage() {
#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
defined(THREAD_SANITIZER)
@@ -100,7 +93,6 @@ void RestrictAddressSpaceUsage() {
#endif
CHECK(sandbox::ResourceLimits::Lower(RLIMIT_AS, kNewAddressSpaceLimit));
}
-#endif // !OS_NACL_NONSFI
} // namespace
@@ -156,11 +148,6 @@ void NaClSandbox::InitializeLayerOneSandbox() {
}
}
-#if !defined(OS_NACL_NONSFI)
-// Currently Layer-two sandbox is not yet supported on nacl_helper_nonsfi.
-// TODO(hidehiko): Enable the sandbox.
-// Note that CheckForExpectedNumberOfOpenFds() is just referred from
-// InitializeLayerTwoSandbox(). Enable them together.
void NaClSandbox::CheckForExpectedNumberOfOpenFds() {
// We expect to have the following FDs open:
// 1-3) stdin, stdout, stderr.
@@ -198,10 +185,13 @@ void NaClSandbox::InitializeLayerTwoSandbox(bool uses_nonsfi_mode) {
layer_two_enabled_ = nacl::nonsfi::InitializeBPFSandbox(proc_fd_.Pass());
layer_two_is_nonsfi_ = true;
} else {
+#if defined(OS_NACL_NONSFI)
+ LOG(FATAL) << "nacl_helper_nonsfi can run only Non-SFI plugin.";
+#else
layer_two_enabled_ = nacl::InitializeBPFSandbox(proc_fd_.Pass());
+#endif
}
}
-#endif // OS_NACL_NONSFI
void NaClSandbox::SealLayerOneSandbox() {
if (proc_fd_.is_valid() && !layer_two_enabled_) {
@@ -219,8 +209,16 @@ void NaClSandbox::CheckSandboxingStateWithPolicy() {
" this is not allowed in this configuration.";
const bool no_sandbox_for_nonsfi_ok =
+#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) || \
+ defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER)
+ // Sanitizer tests run with --no-sandbox, but without
+ // --nacl-dangerous-no-sandbox-nonsfi. Allow that case.
+ true;
+#else
base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kNaClDangerousNoSandboxNonSfi);
+#endif
+
const bool can_be_no_sandbox =
!layer_two_is_nonsfi_ || no_sandbox_for_nonsfi_ok;
@@ -233,9 +231,6 @@ void NaClSandbox::CheckSandboxingStateWithPolicy() {
LOG(FATAL) << kNoSuidMsg << kItIsNotAllowedMsg;
}
-#if !defined(OS_NACL_NONSFI)
- // Currently Layer-two sandbox is not yet supported on nacl_helper_nonsfi.
- // TODO(hidehiko): Enable the sandbox.
if (!layer_two_enabled_) {
static const char kNoBpfMsg[] =
"The seccomp-bpf sandbox is not engaged for NaCl:";
@@ -244,7 +239,6 @@ void NaClSandbox::CheckSandboxingStateWithPolicy() {
else
LOG(FATAL) << kNoBpfMsg << kItIsNotAllowedMsg;
}
-#endif
}
} // namespace nacl
diff --git a/components/nacl_nonsfi.gyp b/components/nacl_nonsfi.gyp
index 3df9c45..53ff394 100644
--- a/components/nacl_nonsfi.gyp
+++ b/components/nacl_nonsfi.gyp
@@ -56,6 +56,7 @@
'nacl/loader/nacl_trusted_listener.cc',
'nacl/loader/nonsfi/nonsfi_listener.cc',
'nacl/loader/nonsfi/nonsfi_main.cc',
+ 'nacl/loader/nonsfi/nonsfi_sandbox.cc',
'nacl/loader/sandbox_linux/nacl_sandbox_linux.cc',
],
diff --git a/content/common/sandbox_linux/sandbox_init_linux.cc b/content/common/sandbox_linux/sandbox_init_linux.cc
index b6f1f7c..146b352 100644
--- a/content/common/sandbox_linux/sandbox_init_linux.cc
+++ b/content/common/sandbox_linux/sandbox_init_linux.cc
@@ -17,8 +17,10 @@ bool InitializeSandbox(scoped_ptr<sandbox::bpf_dsl::Policy> policy,
proc_fd.Pass());
}
+#if !defined(OS_NACL_NONSFI)
scoped_ptr<sandbox::bpf_dsl::Policy> GetBPFSandboxBaselinePolicy() {
return SandboxSeccompBPF::GetBaselinePolicy().Pass();
}
+#endif // !defined(OS_NACL_NONSFI)
} // namespace content
diff --git a/content/common/sandbox_linux/sandbox_seccomp_bpf_linux.cc b/content/common/sandbox_linux/sandbox_seccomp_bpf_linux.cc
index 2f24b62..79adbee 100644
--- a/content/common/sandbox_linux/sandbox_seccomp_bpf_linux.cc
+++ b/content/common/sandbox_linux/sandbox_seccomp_bpf_linux.cc
@@ -28,7 +28,6 @@
#include "content/common/sandbox_linux/bpf_renderer_policy_linux.h"
#include "content/common/sandbox_linux/bpf_utility_policy_linux.h"
#include "content/common/sandbox_linux/sandbox_bpf_base_policy_linux.h"
-#include "content/common/sandbox_linux/sandbox_linux.h"
#include "sandbox/linux/seccomp-bpf-helpers/baseline_policy.h"
#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
@@ -38,7 +37,7 @@
#if !defined(IN_NACL_HELPER)
#include "ui/gl/gl_switches.h"
-#endif
+#endif // !defined(IN_NACL_HELPER)
using sandbox::BaselinePolicy;
using sandbox::SandboxBPF;
@@ -61,8 +60,21 @@ namespace content {
#if defined(USE_SECCOMP_BPF)
namespace {
+// This function takes ownership of |policy|.
void StartSandboxWithPolicy(sandbox::bpf_dsl::Policy* policy,
- base::ScopedFD proc_fd);
+ base::ScopedFD proc_fd) {
+ // Starting the sandbox is a one-way operation. The kernel doesn't allow
+ // us to unload a sandbox policy after it has been started. Nonetheless,
+ // in order to make the use of the "Sandbox" object easier, we allow for
+ // the object to be destroyed after the sandbox has been started. Note that
+ // doing so does not stop the sandbox.
+ SandboxBPF sandbox(policy);
+
+ sandbox.SetProcFd(proc_fd.Pass());
+ CHECK(sandbox.StartSandbox(SandboxBPF::SeccompLevel::SINGLE_THREADED));
+}
+
+#if !defined(OS_NACL_NONSFI)
inline bool IsChromeOS() {
#if defined(OS_CHROMEOS)
@@ -145,21 +157,6 @@ void RunSandboxSanityChecks(const std::string& process_type) {
}
}
-
-// This function takes ownership of |policy|.
-void StartSandboxWithPolicy(sandbox::bpf_dsl::Policy* policy,
- base::ScopedFD proc_fd) {
- // Starting the sandbox is a one-way operation. The kernel doesn't allow
- // us to unload a sandbox policy after it has been started. Nonetheless,
- // in order to make the use of the "Sandbox" object easier, we allow for
- // the object to be destroyed after the sandbox has been started. Note that
- // doing so does not stop the sandbox.
- SandboxBPF sandbox(policy);
-
- sandbox.SetProcFd(proc_fd.Pass());
- CHECK(sandbox.StartSandbox(SandboxBPF::SeccompLevel::SINGLE_THREADED));
-}
-
// nacl_helper needs to be tiny and includes only part of content/
// in its dependencies. Make sure to not link things that are not needed.
#if !defined(IN_NACL_HELPER)
@@ -220,6 +217,7 @@ bool StartBPFSandbox(const base::CommandLine& command_line,
return false;
}
#endif // !defined(IN_NACL_HELPER)
+#endif // !defined(OS_NACL_NONSFI)
} // namespace
@@ -237,6 +235,7 @@ bool SandboxSeccompBPF::IsSeccompBPFDesired() {
}
}
+#if !defined(OS_NACL_NONSFI)
bool SandboxSeccompBPF::ShouldEnableSeccompBPF(
const std::string& process_type) {
#if defined(USE_SECCOMP_BPF)
@@ -249,6 +248,7 @@ bool SandboxSeccompBPF::ShouldEnableSeccompBPF(
#endif // USE_SECCOMP_BPF
return false;
}
+#endif // !defined(OS_NACL_NONSFI)
bool SandboxSeccompBPF::SupportsSandbox() {
#if defined(USE_SECCOMP_BPF)
@@ -258,6 +258,7 @@ bool SandboxSeccompBPF::SupportsSandbox() {
return false;
}
+#if !defined(OS_NACL_NONSFI)
bool SandboxSeccompBPF::SupportsSandboxWithTsync() {
#if defined(USE_SECCOMP_BPF)
return SandboxBPF::SupportsSeccompSandbox(
@@ -285,6 +286,7 @@ bool SandboxSeccompBPF::StartSandbox(const std::string& process_type,
#endif
return false;
}
+#endif // !defined(OS_NACL_NONSFI)
bool SandboxSeccompBPF::StartSandboxWithExternalPolicy(
scoped_ptr<sandbox::bpf_dsl::Policy> policy,
@@ -299,6 +301,7 @@ bool SandboxSeccompBPF::StartSandboxWithExternalPolicy(
return false;
}
+#if !defined(OS_NACL_NONSFI)
scoped_ptr<sandbox::bpf_dsl::Policy> SandboxSeccompBPF::GetBaselinePolicy() {
#if defined(USE_SECCOMP_BPF)
return scoped_ptr<sandbox::bpf_dsl::Policy>(new BaselinePolicy);
@@ -306,5 +309,6 @@ scoped_ptr<sandbox::bpf_dsl::Policy> SandboxSeccompBPF::GetBaselinePolicy() {
return scoped_ptr<sandbox::bpf_dsl::Policy>();
#endif // defined(USE_SECCOMP_BPF)
}
+#endif // !defined(OS_NACL_NONSFI)
} // namespace content
diff --git a/content/content_nacl_nonsfi.gyp b/content/content_nacl_nonsfi.gyp
index f60f120..cfff0a5 100644
--- a/content/content_nacl_nonsfi.gyp
+++ b/content/content_nacl_nonsfi.gyp
@@ -25,11 +25,15 @@
'build_nonsfi_helper': 1,
'sources': [
+ 'common/sandbox_linux/sandbox_init_linux.cc',
+ 'common/sandbox_linux/sandbox_seccomp_bpf_linux.cc',
'common/send_zygote_child_ping_linux.cc',
'public/common/content_switches.cc',
- # TODO(hidehiko): Add sandbox code.
],
},
+ 'defines': [
+ 'USE_SECCOMP_BPF=1',
+ ],
'dependencies': [
'../base/base_nacl.gyp:base_nacl_nonsfi',
],
diff --git a/content/public/common/sandbox_init.h b/content/public/common/sandbox_init.h
index bd12ff8..6f4b19c 100644
--- a/content/public/common/sandbox_init.h
+++ b/content/public/common/sandbox_init.h
@@ -82,7 +82,7 @@ CONTENT_EXPORT base::Process StartSandboxedProcess(
CONTENT_EXPORT bool InitializeSandbox(int sandbox_type,
const base::FilePath& allowed_path);
-#elif defined(OS_LINUX)
+#elif defined(OS_LINUX) || defined(OS_NACL_NONSFI)
class SandboxInitializerDelegate;
@@ -98,7 +98,7 @@ CONTENT_EXPORT bool InitializeSandbox(
// implement a policy that is derived from the baseline.
CONTENT_EXPORT scoped_ptr<sandbox::bpf_dsl::Policy>
GetBPFSandboxBaselinePolicy();
-#endif // defined(OS_LINUX)
+#endif // defined(OS_LINUX) || defined(OS_NACL_NONSFI)
} // namespace content
diff --git a/sandbox/linux/bpf_dsl/codegen.cc b/sandbox/linux/bpf_dsl/codegen.cc
index 99b78ed..bc2c7a2 100644
--- a/sandbox/linux/bpf_dsl/codegen.cc
+++ b/sandbox/linux/bpf_dsl/codegen.cc
@@ -131,7 +131,8 @@ CodeGen::Node CodeGen::Append(uint16_t code, uint32_t k, size_t jt, size_t jf) {
CHECK_EQ(program_.size(), equivalent_.size());
Node res = program_.size();
- program_.push_back(sock_filter{code, jt, jf, k});
+ program_.push_back(sock_filter{
+ code, static_cast<uint8_t>(jt), static_cast<uint8_t>(jf), k});
equivalent_.push_back(res);
return res;
}
diff --git a/sandbox/linux/bpf_dsl/policy_compiler.cc b/sandbox/linux/bpf_dsl/policy_compiler.cc
index d4d52801..f38232f 100644
--- a/sandbox/linux/bpf_dsl/policy_compiler.cc
+++ b/sandbox/linux/bpf_dsl/policy_compiler.cc
@@ -22,6 +22,7 @@
#include "sandbox/linux/seccomp-bpf/errorcode.h"
#include "sandbox/linux/system_headers/linux_filter.h"
#include "sandbox/linux/system_headers/linux_seccomp.h"
+#include "sandbox/linux/system_headers/linux_syscalls.h"
namespace sandbox {
namespace bpf_dsl {
diff --git a/sandbox/linux/bpf_dsl/seccomp_macros.h b/sandbox/linux/bpf_dsl/seccomp_macros.h
index 7f4866d..ca28c1d 100644
--- a/sandbox/linux/bpf_dsl/seccomp_macros.h
+++ b/sandbox/linux/bpf_dsl/seccomp_macros.h
@@ -11,7 +11,9 @@
// All x86_64 builds use a new enough bionic to have sys/user.h.
#if !defined(__BIONIC__) || defined(__x86_64__)
#include <sys/types.h> // Fix for gcc 4.7, make sure __uint16_t is defined.
+#if !defined(__native_client_nonsfi__)
#include <sys/user.h>
+#endif
#if defined(__mips__)
// sys/user.h in eglibc misses size_t definition
#include <stddef.h>
@@ -50,10 +52,10 @@
8*(nr) + 0)
-#if defined(__BIONIC__)
-// Old Bionic versions don't have sys/user.h, so we just define regs_struct
-// directly. This can be removed once we no longer need to support these old
-// Bionic versions.
+#if defined(__BIONIC__) || defined(__native_client_nonsfi__)
+// Old Bionic versions and PNaCl toolchain don't have sys/user.h, so we just
+// define regs_struct directly. This can be removed once we no longer need to
+// support these old Bionic versions and PNaCl toolchain.
struct regs_struct {
long int ebx;
long int ecx;
@@ -149,10 +151,10 @@ typedef user_regs_struct regs_struct;
#define SECCOMP_ARG_LSB_IDX(nr) (offsetof(struct arch_seccomp_data, args) + \
8*(nr) + 0)
-#if defined(__BIONIC__)
-// Old Bionic versions don't have sys/user.h, so we just define regs_struct
-// directly. This can be removed once we no longer need to support these old
-// Bionic versions.
+#if defined(__BIONIC__) || defined(__native_client_nonsfi__)
+// Old Bionic versions and PNaCl toolchain don't have sys/user.h, so we just
+// define regs_struct directly. This can be removed once we no longer need to
+// support these old Bionic versions and PNaCl toolchain.
struct regs_struct {
unsigned long uregs[18];
};
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
index 282e727..60c16d3 100644
--- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
@@ -11,7 +11,6 @@
#include <sched.h>
#include <signal.h>
#include <stdint.h>
-#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/prctl.h>
#include <sys/resource.h>
@@ -32,6 +31,11 @@
#include "sandbox/linux/system_headers/linux_futex.h"
#include "sandbox/linux/system_headers/linux_syscalls.h"
+// PNaCl toolchain does not provide sys/ioctl.h header.
+#if !defined(OS_NACL_NONSFI)
+#include <sys/ioctl.h>
+#endif
+
#if defined(OS_ANDROID)
#if !defined(F_DUPFD_CLOEXEC)
@@ -104,6 +108,7 @@ using sandbox::bpf_dsl::ResultExpr;
namespace sandbox {
+#if !defined(OS_NACL_NONSFI)
// 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.
@@ -261,21 +266,6 @@ ResultExpr RestrictGetSetpriority(pid_t target_pid) {
.Else(CrashSIGSYS());
}
-ResultExpr RestrictClockID() {
- static_assert(4 == sizeof(clockid_t), "clockid_t is not 32bit");
- const Arg<clockid_t> clockid(0);
- return If(
-#if defined(OS_CHROMEOS)
- // Allow the special clock for Chrome OS used by Chrome tracing.
- clockid == base::TimeTicks::kClockSystemTrace ||
-#endif
- clockid == CLOCK_MONOTONIC ||
- clockid == CLOCK_PROCESS_CPUTIME_ID ||
- clockid == CLOCK_REALTIME ||
- clockid == CLOCK_THREAD_CPUTIME_ID,
- Allow()).Else(CrashSIGSYS());
-}
-
ResultExpr RestrictSchedTarget(pid_t target_pid, int sysno) {
switch (sysno) {
case __NR_sched_getaffinity:
@@ -306,5 +296,21 @@ ResultExpr RestrictGetrusage() {
const Arg<int> who(0);
return If(who == RUSAGE_SELF, Allow()).Else(CrashSIGSYS());
}
+#endif // !defined(OS_NACL_NONSFI)
+
+ResultExpr RestrictClockID() {
+ static_assert(4 == sizeof(clockid_t), "clockid_t is not 32bit");
+ const Arg<clockid_t> clockid(0);
+ return If(
+#if defined(OS_CHROMEOS)
+ // Allow the special clock for Chrome OS used by Chrome tracing.
+ clockid == base::TimeTicks::kClockSystemTrace ||
+#endif
+ clockid == CLOCK_MONOTONIC ||
+ clockid == CLOCK_PROCESS_CPUTIME_ID ||
+ clockid == CLOCK_REALTIME ||
+ clockid == CLOCK_THREAD_CPUTIME_ID,
+ Allow()).Else(CrashSIGSYS());
+}
} // namespace sandbox.
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h
index d557c5f..0ec396d 100644
--- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h
+++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h
@@ -67,15 +67,6 @@ SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictFutex();
// |target_pid| while calling setpriority(2) / getpriority(2).
SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictGetSetpriority(pid_t target_pid);
-// Restrict |clk_id| for clock_getres(), clock_gettime() and clock_settime().
-// We allow accessing only CLOCK_MONOTONIC, CLOCK_PROCESS_CPUTIME_ID,
-// CLOCK_REALTIME, and CLOCK_THREAD_CPUTIME_ID. In particular, this disallows
-// access to arbitrary per-{process,thread} CPU-time clock IDs (such as those
-// returned by {clock,pthread}_getcpuclockid), which can leak information
-// about the state of the host OS.
-// On Chrome OS, base::TimeTicks::kClockSystemTrace is also allowed.
-SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictClockID();
-
// Restricts |pid| for sched_* syscalls which take a pid as the first argument.
// We only allow calling these syscalls if the pid argument is equal to the pid
// of the sandboxed process or 0 (indicating the current thread). The following
@@ -95,6 +86,15 @@ SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictPrlimit64(pid_t target_pid);
// process).
SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictGetrusage();
+// Restrict |clk_id| for clock_getres(), clock_gettime() and clock_settime().
+// We allow accessing only CLOCK_MONOTONIC, CLOCK_PROCESS_CPUTIME_ID,
+// CLOCK_REALTIME, and CLOCK_THREAD_CPUTIME_ID. In particular, this disallows
+// access to arbitrary per-{process,thread} CPU-time clock IDs (such as those
+// returned by {clock,pthread}_getcpuclockid), which can leak information
+// about the state of the host OS.
+// On Chrome OS, base::TimeTicks::kClockSystemTrace is also allowed.
+SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictClockID();
+
} // namespace sandbox.
#endif // SANDBOX_LINUX_SECCOMP_BPF_HELPERS_SYSCALL_PARAMETERS_RESTRICTIONS_H_
diff --git a/sandbox/linux/seccomp-bpf/syscall.cc b/sandbox/linux/seccomp-bpf/syscall.cc
index 3b3c8db..1c77533 100644
--- a/sandbox/linux/seccomp-bpf/syscall.cc
+++ b/sandbox/linux/seccomp-bpf/syscall.cc
@@ -133,7 +133,13 @@ asm(// We need to be able to tell the kernel exactly where we made a
#else
".arm\n"
#endif
- "SyscallAsm:.fnstart\n"
+ "SyscallAsm:\n"
+#if !defined(__native_client_nonsfi__)
+ // .fnstart and .fnend pseudo operations creates unwind table.
+ // It also creates a reference to the symbol __aeabi_unwind_cpp_pr0, which
+ // is not provided by PNaCl toolchain. Disable it.
+ ".fnstart\n"
+#endif
"@ args = 0, pretend = 0, frame = 8\n"
"@ frame_needed = 1, uses_anonymous_args = 0\n"
#if defined(__thumb__)
@@ -177,7 +183,11 @@ asm(// We need to be able to tell the kernel exactly where we made a
#else
"2:ldmfd sp!, {fp, pc}\n"
#endif
+#if !defined(__native_client_nonsfi__)
+ // Do not use .fnstart and .fnend for PNaCl toolchain. See above comment,
+ // for more details.
".fnend\n"
+#endif
"9:.size SyscallAsm, 9b-SyscallAsm\n"
#elif defined(__mips__)
".text\n"
diff --git a/sandbox/linux/seccomp-bpf/trap.cc b/sandbox/linux/seccomp-bpf/trap.cc
index 79b7569..8f559e5 100644
--- a/sandbox/linux/seccomp-bpf/trap.cc
+++ b/sandbox/linux/seccomp-bpf/trap.cc
@@ -12,6 +12,7 @@
#include <algorithm>
#include <limits>
+#include "base/compiler_specific.h"
#include "base/logging.h"
#include "build/build_config.h"
#include "sandbox/linux/bpf_dsl/seccomp_macros.h"
@@ -121,15 +122,26 @@ bpf_dsl::TrapRegistry* Trap::Registry() {
}
void Trap::SigSysAction(int nr, LinuxSigInfo* info, void* void_context) {
+ if (info) {
+ MSAN_UNPOISON(info, sizeof(*info));
+ }
+
+ // Obtain the signal context. This, most notably, gives us access to
+ // all CPU registers at the time of the signal.
+ ucontext_t* ctx = reinterpret_cast<ucontext_t*>(void_context);
+ if (ctx) {
+ MSAN_UNPOISON(ctx, sizeof(*ctx));
+ }
+
if (!global_trap_) {
RAW_SANDBOX_DIE(
"This can't happen. Found no global singleton instance "
"for Trap() handling.");
}
- global_trap_->SigSys(nr, info, void_context);
+ global_trap_->SigSys(nr, info, ctx);
}
-void Trap::SigSys(int nr, LinuxSigInfo* info, void* void_context) {
+void Trap::SigSys(int nr, LinuxSigInfo* info, ucontext_t* ctx) {
// Signal handlers should always preserve "errno". Otherwise, we could
// trigger really subtle bugs.
const int old_errno = errno;
@@ -137,7 +149,7 @@ void Trap::SigSys(int nr, LinuxSigInfo* info, void* void_context) {
// Various sanity checks to make sure we actually received a signal
// triggered by a BPF filter. If something else triggered SIGSYS
// (e.g. kill()), there is really nothing we can do with this signal.
- if (nr != LINUX_SIGSYS || info->si_code != SYS_SECCOMP || !void_context ||
+ if (nr != LINUX_SIGSYS || info->si_code != SYS_SECCOMP || !ctx ||
info->si_errno <= 0 ||
static_cast<size_t>(info->si_errno) > trap_array_size_) {
// ATI drivers seem to send SIGSYS, so this cannot be FATAL.
@@ -148,9 +160,6 @@ void Trap::SigSys(int nr, LinuxSigInfo* info, void* void_context) {
return;
}
- // Obtain the signal context. This, most notably, gives us access to
- // all CPU registers at the time of the signal.
- ucontext_t* ctx = reinterpret_cast<ucontext_t*>(void_context);
// Obtain the siginfo information that is specific to SIGSYS. Unfortunately,
// most versions of glibc don't include this information in siginfo_t. So,
diff --git a/sandbox/linux/seccomp-bpf/trap.h b/sandbox/linux/seccomp-bpf/trap.h
index bbddeb7..50ac3fd 100644
--- a/sandbox/linux/seccomp-bpf/trap.h
+++ b/sandbox/linux/seccomp-bpf/trap.h
@@ -61,7 +61,7 @@ class SANDBOX_EXPORT Trap : public bpf_dsl::TrapRegistry {
// Make sure that SigSys is not inlined in order to get slightly better crash
// dumps.
- void SigSys(int nr, LinuxSigInfo* info, void* void_context)
+ void SigSys(int nr, LinuxSigInfo* info, ucontext_t* ctx)
__attribute__((noinline));
// We have a global singleton that handles all of our SIGSYS traps. This
// variable must never be deallocated after it has been set up initially, as
diff --git a/sandbox/linux/services/syscall_wrappers.cc b/sandbox/linux/services/syscall_wrappers.cc
index a84d329..264eb68 100644
--- a/sandbox/linux/services/syscall_wrappers.cc
+++ b/sandbox/linux/services/syscall_wrappers.cc
@@ -148,8 +148,9 @@ int sys_sigprocmask(int how, const sigset_t* set, decltype(nullptr) oldset) {
sizeof(linux_value));
}
-#if defined(MEMORY_SANITIZER) || defined(THREAD_SANITIZER) || \
- (defined(ARCH_CPU_X86_64) && !defined(__clang__))
+#if (defined(MEMORY_SANITIZER) || defined(THREAD_SANITIZER) || \
+ (defined(ARCH_CPU_X86_64) && !defined(__clang__))) && \
+ !defined(OS_NACL_NONSFI)
// If MEMORY_SANITIZER or THREAD_SANITIZER is enabled, it is necessary to call
// sigaction() here, rather than the direct syscall (sys_sigaction() defined
// by ourselves).
@@ -173,6 +174,12 @@ int sys_sigprocmask(int how, const sigset_t* set, decltype(nullptr) oldset) {
// of function is actually very small (only two instructions), but we need to
// define much debug information in addition, otherwise backtrace() used by
// base::StackTrace would not work so that some tests would fail.
+//
+// When this is built with PNaCl toolchain, we should always use sys_sigaction
+// below, because sigaction() provided by the toolchain is incompatible with
+// Linux's ABI. So, otherwise, it would just fail. Note that it is not
+// necessary to think about sigaction() invocation in other places even with
+// MEMORY_SANITIZER or THREAD_SANITIZER, because it would just fail there.
int sys_sigaction(int signum,
const struct sigaction* act,
struct sigaction* oldact) {
diff --git a/sandbox/linux/system_headers/linux_futex.h b/sandbox/linux/system_headers/linux_futex.h
index 91733a8..4e28403 100644
--- a/sandbox/linux/system_headers/linux_futex.h
+++ b/sandbox/linux/system_headers/linux_futex.h
@@ -5,7 +5,9 @@
#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_FUTEX_H_
#define SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_FUTEX_H_
+#if !defined(__native_client_nonsfi__)
#include <linux/futex.h>
+#endif // !defined(__native_client_nonsfi__)
#if !defined(FUTEX_WAIT)
#define FUTEX_WAIT 0
diff --git a/sandbox/sandbox_nacl_nonsfi.gyp b/sandbox/sandbox_nacl_nonsfi.gyp
index 781df42..906fc7b 100644
--- a/sandbox/sandbox_nacl_nonsfi.gyp
+++ b/sandbox/sandbox_nacl_nonsfi.gyp
@@ -27,14 +27,28 @@
'sources': [
# This is the subset of linux build target, needed for
# nacl_helper_nonsfi's sandbox implementation.
+ 'linux/bpf_dsl/bpf_dsl.cc',
+ 'linux/bpf_dsl/codegen.cc',
+ 'linux/bpf_dsl/dump_bpf.cc',
+ 'linux/bpf_dsl/policy.cc',
+ 'linux/bpf_dsl/policy_compiler.cc',
+ 'linux/bpf_dsl/syscall_set.cc',
+ 'linux/bpf_dsl/verifier.cc',
+ 'linux/seccomp-bpf-helpers/sigsys_handlers.cc',
+ 'linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc',
+ 'linux/seccomp-bpf/die.cc',
+ 'linux/seccomp-bpf/errorcode.cc',
+ 'linux/seccomp-bpf/sandbox_bpf.cc',
+ 'linux/seccomp-bpf/syscall.cc',
+ 'linux/seccomp-bpf/trap.cc',
'linux/services/credentials.cc',
- 'linux/services/namespace_utils.cc',
'linux/services/namespace_sandbox.cc',
+ 'linux/services/namespace_utils.cc',
'linux/services/proc_util.cc',
+ 'linux/services/resource_limits.cc',
'linux/services/syscall_wrappers.cc',
'linux/services/thread_helpers.cc',
'linux/suid/client/setuid_sandbox_client.cc',
- # TODO(hidehiko): Support seccomp-bpf sandbox.
],
},
'dependencies': [