diff options
Diffstat (limited to 'sandbox/linux')
-rw-r--r-- | sandbox/linux/bpf_dsl/codegen.cc | 3 | ||||
-rw-r--r-- | sandbox/linux/bpf_dsl/policy_compiler.cc | 1 | ||||
-rw-r--r-- | sandbox/linux/bpf_dsl/seccomp_macros.h | 18 | ||||
-rw-r--r-- | sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc | 38 | ||||
-rw-r--r-- | sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h | 18 | ||||
-rw-r--r-- | sandbox/linux/seccomp-bpf/syscall.cc | 12 | ||||
-rw-r--r-- | sandbox/linux/seccomp-bpf/trap.cc | 21 | ||||
-rw-r--r-- | sandbox/linux/seccomp-bpf/trap.h | 2 | ||||
-rw-r--r-- | sandbox/linux/services/syscall_wrappers.cc | 11 | ||||
-rw-r--r-- | sandbox/linux/system_headers/linux_futex.h | 2 |
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 |