summaryrefslogtreecommitdiffstats
path: root/sandbox/linux
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 /sandbox/linux
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}
Diffstat (limited to 'sandbox/linux')
-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
10 files changed, 82 insertions, 44 deletions
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