diff options
author | hidehiko <hidehiko@chromium.org> | 2015-04-24 14:55:21 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-04-24 21:55:53 +0000 |
commit | a926d0b8cd3d2a3175ef518d8987c7511b083303 (patch) | |
tree | 0315efc501cc5c1aaef4596ae66393ebb8766686 /sandbox/linux | |
parent | 08d2ab130415694f0db6ef89605b984758ab4822 (diff) | |
download | chromium_src-a926d0b8cd3d2a3175ef518d8987c7511b083303.zip chromium_src-a926d0b8cd3d2a3175ef518d8987c7511b083303.tar.gz chromium_src-a926d0b8cd3d2a3175ef518d8987c7511b083303.tar.bz2 |
Reland: Introduce sys_sigprocmask and sys_sigaction. (patchset #4 id:80001 of https://codereview.chromium.org/1092153005/)
The last version was broken for x86_64 DEBUG build.
On x86_64, it is necessary to set sa_restorer appropriately,
if not specified. What we need in the function is just invoking
the rt_sigreturn system call. However, it is special system call
which touches user land stack, so that a function prologue will
break the program.
In RELEASE build, that prologue is gone (including syscall() invocation)
by optimization. However, in DEBUG build, there is the prologue.
Unfortunately, all CQ and trybot do not run DEBUG tests so that it
was not catched.
Also, it turned out that MSAN does not work with direct sigaction syscall, unfortunately. (In more precise, it does not work if we *mix* direct sigaction syscall and sigaction() in libc).
This version fixes them.
TEST=Ran sandbox_linux_tests with DEBUG build locally. Ran msan tests, too. Ran trybots including 64 debug bot and msan ones.
BUG=358465
CQ_EXTRA_TRYBOTS=tryserver.chromium.linux:linux_chromium_trusty32_rel,linux_arm,linux_chromium_trusty_dbg,linux_chromium_dbg_ng,linux_chromium_msan_rel_ng
Review URL: https://codereview.chromium.org/1099263003
Cr-Commit-Position: refs/heads/master@{#326893}
Diffstat (limited to 'sandbox/linux')
21 files changed, 380 insertions, 112 deletions
diff --git a/sandbox/linux/BUILD.gn b/sandbox/linux/BUILD.gn index 21f856b..8496685 100644 --- a/sandbox/linux/BUILD.gn +++ b/sandbox/linux/BUILD.gn @@ -117,6 +117,7 @@ source_set("sandbox_linux_unittests_sources") { "seccomp-bpf/errorcode_unittest.cc", "seccomp-bpf/sandbox_bpf_unittest.cc", "seccomp-bpf/syscall_unittest.cc", + "seccomp-bpf/trap_unittest.cc", ] } if (compile_credentials) { @@ -288,15 +289,16 @@ component("sandbox_services") { source_set("sandbox_services_headers") { sources = [ - "system_headers/android_arm64_ucontext.h", - "system_headers/android_arm_ucontext.h", - "system_headers/android_i386_ucontext.h", - "system_headers/android_ucontext.h", "system_headers/arm64_linux_syscalls.h", + "system_headers/arm64_linux_ucontext.h", "system_headers/arm_linux_syscalls.h", + "system_headers/arm_linux_ucontext.h", + "system_headers/i386_linux_ucontext.h", "system_headers/linux_futex.h", "system_headers/linux_seccomp.h", + "system_headers/linux_signal.h", "system_headers/linux_syscalls.h", + "system_headers/linux_ucontext.h", "system_headers/x86_32_linux_syscalls.h", "system_headers/x86_64_linux_syscalls.h", ] diff --git a/sandbox/linux/sandbox_linux.gypi b/sandbox/linux/sandbox_linux.gypi index 1cf3b2d..7724223 100644 --- a/sandbox/linux/sandbox_linux.gypi +++ b/sandbox/linux/sandbox_linux.gypi @@ -278,18 +278,18 @@ { 'target_name': 'sandbox_services_headers', 'type': 'none', 'sources': [ - 'system_headers/android_arm64_ucontext.h', - 'system_headers/android_arm_ucontext.h', - 'system_headers/android_i386_ucontext.h', - 'system_headers/android_mips_ucontext.h', - 'system_headers/android_ucontext.h', 'system_headers/arm64_linux_syscalls.h', + 'system_headers/arm64_linux_ucontext.h', 'system_headers/arm_linux_syscalls.h', + 'system_headers/arm_linux_ucontext.h', 'system_headers/capability.h', + 'system_headers/i386_linux_ucontext.h', 'system_headers/linux_futex.h', 'system_headers/linux_seccomp.h', 'system_headers/linux_syscalls.h', + 'system_headers/linux_ucontext.h', 'system_headers/mips_linux_syscalls.h', + 'system_headers/mips_linux_ucontext.h', 'system_headers/x86_32_linux_syscalls.h', 'system_headers/x86_64_linux_syscalls.h', ], diff --git a/sandbox/linux/sandbox_linux_test_sources.gypi b/sandbox/linux/sandbox_linux_test_sources.gypi index c558a0d..ce7817d 100644 --- a/sandbox/linux/sandbox_linux_test_sources.gypi +++ b/sandbox/linux/sandbox_linux_test_sources.gypi @@ -53,6 +53,7 @@ 'seccomp-bpf/errorcode_unittest.cc', 'seccomp-bpf/sandbox_bpf_unittest.cc', 'seccomp-bpf/syscall_unittest.cc', + 'seccomp-bpf/trap_unittest.cc', ], }], [ 'compile_credentials==1', { diff --git a/sandbox/linux/seccomp-bpf/die.cc b/sandbox/linux/seccomp-bpf/die.cc index 777c9d1..3baf1f1 100644 --- a/sandbox/linux/seccomp-bpf/die.cc +++ b/sandbox/linux/seccomp-bpf/die.cc @@ -16,6 +16,8 @@ #include "base/logging.h" #include "base/posix/eintr_wrapper.h" #include "sandbox/linux/seccomp-bpf/syscall.h" +#include "sandbox/linux/services/syscall_wrappers.h" +#include "sandbox/linux/system_headers/linux_signal.h" namespace sandbox { @@ -32,7 +34,10 @@ void Die::ExitGroup() { // to a defined state; but we have not way to verify whether we actually // succeeded in doing so. Nonetheless, triggering a fatal signal could help // us terminate. - signal(SIGSEGV, SIG_DFL); + struct sigaction sa = {}; + sa.sa_handler = LINUX_SIG_DFL; + sa.sa_flags = LINUX_SA_RESTART; + sys_sigaction(LINUX_SIGSEGV, &sa, nullptr); Syscall::Call(__NR_prctl, PR_SET_DUMPABLE, (void*)0, (void*)0, (void*)0); if (*(volatile char*)0) { } diff --git a/sandbox/linux/seccomp-bpf/syscall.h b/sandbox/linux/seccomp-bpf/syscall.h index dfb44eb..ccfc88d 100644 --- a/sandbox/linux/seccomp-bpf/syscall.h +++ b/sandbox/linux/seccomp-bpf/syscall.h @@ -9,13 +9,9 @@ #include <stdint.h> #include "base/macros.h" +#include "sandbox/linux/system_headers/linux_signal.h" #include "sandbox/sandbox_export.h" -// Android's signal.h doesn't define ucontext etc. -#if defined(OS_ANDROID) -#include "sandbox/linux/system_headers/android_ucontext.h" -#endif - namespace sandbox { // This purely static class can be used to perform system calls with some diff --git a/sandbox/linux/seccomp-bpf/trap.cc b/sandbox/linux/seccomp-bpf/trap.cc index 145e624..79b7569 100644 --- a/sandbox/linux/seccomp-bpf/trap.cc +++ b/sandbox/linux/seccomp-bpf/trap.cc @@ -17,12 +17,9 @@ #include "sandbox/linux/bpf_dsl/seccomp_macros.h" #include "sandbox/linux/seccomp-bpf/die.h" #include "sandbox/linux/seccomp-bpf/syscall.h" +#include "sandbox/linux/services/syscall_wrappers.h" #include "sandbox/linux/system_headers/linux_seccomp.h" - -// Android's signal.h doesn't define ucontext etc. -#if defined(OS_ANDROID) -#include "sandbox/linux/system_headers/android_ucontext.h" -#endif +#include "sandbox/linux/system_headers/linux_signal.h" namespace { @@ -53,13 +50,13 @@ const char kSandboxDebuggingEnv[] = "CHROME_SANDBOX_DEBUGGING"; // possibly even worse. bool GetIsInSigHandler(const ucontext_t* ctx) { // Note: on Android, sigismember does not take a pointer to const. - return sigismember(const_cast<sigset_t*>(&ctx->uc_sigmask), SIGBUS); + return sigismember(const_cast<sigset_t*>(&ctx->uc_sigmask), LINUX_SIGBUS); } void SetIsInSigHandler() { sigset_t mask; - if (sigemptyset(&mask) || sigaddset(&mask, SIGBUS) || - sigprocmask(SIG_BLOCK, &mask, NULL)) { + if (sigemptyset(&mask) || sigaddset(&mask, LINUX_SIGBUS) || + sandbox::sys_sigprocmask(LINUX_SIG_BLOCK, &mask, NULL)) { SANDBOX_DIE("Failed to block SIGBUS"); } } @@ -82,10 +79,13 @@ Trap::Trap() has_unsafe_traps_(false) { // Set new SIGSYS handler struct sigaction sa = {}; - sa.sa_sigaction = SigSysAction; - sa.sa_flags = SA_SIGINFO | SA_NODEFER; - struct sigaction old_sa; - if (sigaction(SIGSYS, &sa, &old_sa) < 0) { + // In some toolchain, sa_sigaction is not declared in struct sigaction. + // So, here cast the pointer to the sa_handler's type. This works because + // |sa_handler| and |sa_sigaction| shares the same memory. + sa.sa_handler = reinterpret_cast<void (*)(int)>(SigSysAction); + sa.sa_flags = LINUX_SA_SIGINFO | LINUX_SA_NODEFER; + struct sigaction old_sa = {}; + if (sys_sigaction(LINUX_SIGSYS, &sa, &old_sa) < 0) { SANDBOX_DIE("Failed to configure SIGSYS handler"); } @@ -99,8 +99,8 @@ Trap::Trap() // Unmask SIGSYS sigset_t mask; - if (sigemptyset(&mask) || sigaddset(&mask, SIGSYS) || - sigprocmask(SIG_UNBLOCK, &mask, NULL)) { + if (sigemptyset(&mask) || sigaddset(&mask, LINUX_SIGSYS) || + sys_sigprocmask(LINUX_SIG_UNBLOCK, &mask, NULL)) { SANDBOX_DIE("Failed to configure SIGSYS handler"); } } @@ -120,7 +120,7 @@ bpf_dsl::TrapRegistry* Trap::Registry() { return global_trap_; } -void Trap::SigSysAction(int nr, siginfo_t* info, void* void_context) { +void Trap::SigSysAction(int nr, LinuxSigInfo* info, void* void_context) { if (!global_trap_) { RAW_SANDBOX_DIE( "This can't happen. Found no global singleton instance " @@ -129,7 +129,7 @@ void Trap::SigSysAction(int nr, siginfo_t* info, void* void_context) { global_trap_->SigSys(nr, info, void_context); } -void Trap::SigSys(int nr, siginfo_t* info, void* void_context) { +void Trap::SigSys(int nr, LinuxSigInfo* info, void* void_context) { // Signal handlers should always preserve "errno". Otherwise, we could // trigger really subtle bugs. const int old_errno = errno; @@ -137,7 +137,7 @@ void Trap::SigSys(int nr, siginfo_t* 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 != SIGSYS || info->si_code != SYS_SECCOMP || !void_context || + if (nr != LINUX_SIGSYS || info->si_code != SYS_SECCOMP || !void_context || 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. diff --git a/sandbox/linux/seccomp-bpf/trap.h b/sandbox/linux/seccomp-bpf/trap.h index 4073bfe..bbddeb7 100644 --- a/sandbox/linux/seccomp-bpf/trap.h +++ b/sandbox/linux/seccomp-bpf/trap.h @@ -5,13 +5,13 @@ #ifndef SANDBOX_LINUX_SECCOMP_BPF_TRAP_H__ #define SANDBOX_LINUX_SECCOMP_BPF_TRAP_H__ -#include <signal.h> #include <stdint.h> #include <map> #include "base/macros.h" #include "sandbox/linux/bpf_dsl/trap_registry.h" +#include "sandbox/linux/system_headers/linux_signal.h" #include "sandbox/sandbox_export.h" namespace sandbox { @@ -57,11 +57,11 @@ class SANDBOX_EXPORT Trap : public bpf_dsl::TrapRegistry { // break subsequent system calls that trigger a SIGSYS. ~Trap() = delete; - static void SigSysAction(int nr, siginfo_t* info, void* void_context); + static void SigSysAction(int nr, LinuxSigInfo* info, void* void_context); // Make sure that SigSys is not inlined in order to get slightly better crash // dumps. - void SigSys(int nr, siginfo_t* info, void* void_context) + void SigSys(int nr, LinuxSigInfo* info, void* void_context) __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/seccomp-bpf/trap_unittest.cc b/sandbox/linux/seccomp-bpf/trap_unittest.cc new file mode 100644 index 0000000..99f94bf --- /dev/null +++ b/sandbox/linux/seccomp-bpf/trap_unittest.cc @@ -0,0 +1,28 @@ +// Copyright 2015 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/trap.h" + +#include <signal.h> + +#include "sandbox/linux/tests/unit_tests.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace sandbox { +namespace { + +SANDBOX_TEST_ALLOW_NOISE(Trap, SigSysAction) { + // This creates a global Trap instance, and registers the signal handler + // (Trap::SigSysAction). + Trap::Registry(); + + // Send SIGSYS to self. If signal handler (SigSysAction) is not registered, + // the process will be terminated with status code -SIGSYS. + // Note that, SigSysAction handler would output an error message + // "Unexpected SIGSYS received." so it is necessary to allow the noise. + raise(SIGSYS); +} + +} // namespace +} // namespace sandbox diff --git a/sandbox/linux/services/credentials.cc b/sandbox/linux/services/credentials.cc index b562d8b..35bb4dc 100644 --- a/sandbox/linux/services/credentials.cc +++ b/sandbox/linux/services/credentials.cc @@ -27,16 +27,12 @@ #include "sandbox/linux/services/syscall_wrappers.h" #include "sandbox/linux/services/thread_helpers.h" #include "sandbox/linux/system_headers/capability.h" +#include "sandbox/linux/system_headers/linux_signal.h" namespace sandbox { namespace { -// Signal ABI for some toolchain is incompatible with Linux's. In particular, -// PNaCl toolchain defines SIGCHLD = 20. So, here, directly define Linux's -// value. -const int kLinuxSIGCHLD = 17; - bool IsRunningOnValgrind() { return RUNNING_ON_VALGRIND; } // Checks that the set of RES-uids and the set of RES-gids have @@ -96,8 +92,8 @@ bool ChrootToSafeEmptyDir() { #endif pid = clone(ChrootToSelfFdinfo, stack, - CLONE_VM | CLONE_VFORK | CLONE_FS | kLinuxSIGCHLD, - nullptr, nullptr, nullptr, nullptr); + CLONE_VM | CLONE_VFORK | CLONE_FS | LINUX_SIGCHLD, nullptr, + nullptr, nullptr, nullptr); PCHECK(pid != -1); int status = -1; diff --git a/sandbox/linux/services/syscall_wrappers.cc b/sandbox/linux/services/syscall_wrappers.cc index e793fad..fdfcb94 100644 --- a/sandbox/linux/services/syscall_wrappers.cc +++ b/sandbox/linux/services/syscall_wrappers.cc @@ -12,12 +12,14 @@ #include <sys/time.h> #include <sys/types.h> #include <unistd.h> +#include <cstring> #include "base/compiler_specific.h" #include "base/logging.h" #include "base/third_party/valgrind/valgrind.h" #include "build/build_config.h" #include "sandbox/linux/system_headers/capability.h" +#include "sandbox/linux/system_headers/linux_signal.h" #include "sandbox/linux/system_headers/linux_syscalls.h" namespace sandbox { @@ -137,4 +139,94 @@ int sys_unshare(int flags) { return syscall(__NR_unshare, flags); } +int sys_sigprocmask(int how, const sigset_t* set, decltype(nullptr) oldset) { + // In some toolchain (in particular Android and PNaCl toolchain), + // sigset_t is 32 bits, but Linux ABI requires 64 bits. + uint64_t linux_value = 0; + std::memcpy(&linux_value, set, std::min(sizeof(sigset_t), sizeof(uint64_t))); + return syscall(__NR_rt_sigprocmask, how, &linux_value, nullptr, + sizeof(linux_value)); +} + +#if defined(MEMORY_SANITIZER) || \ + (defined(ARCH_CPU_X86_64) && defined(__GNUC__) && !defined(__clang__)) +// If MEMORY_SANITIZER is enabled, it is necessary to call sigaction() here, +// rather than the direct syscall (sys_sigaction() defined by ourselves). +// It is because, if MEMORY_SANITIZER is enabled, sigaction is wrapped, and +// |act->sa_handler| is injected in order to unpoisonize the memory passed via +// callback's arguments. Please see msan_interceptors.cc for more details. +// So, if the direct syscall is used, as MEMORY_SANITIZER does not know about +// it, sigaction() invocation in other places would be broken (in more precise, +// returned |oldact| would have a broken |sa_handler| callback). +// Practically, it would break NaCl's signal handler installation. +// cf) native_client/src/trusted/service_runtime/linux/nacl_signal.c. +// +// Also on x86_64 architecture, we need naked function for rt_sigreturn. +// However, there is no simple way to define it with GCC. Note that the body +// 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. +int sys_sigaction(int signum, + const struct sigaction* act, + struct sigaction* oldact) { + return sigaction(signum, act, oldact); +} +#else +// struct sigaction is different ABI from the Linux's. +struct KernelSigAction { + void (*kernel_handler)(int); + uint32_t sa_flags; + void (*sa_restorer)(void); + uint64_t sa_mask; +}; + +// On X86_64 arch, it is necessary to set sa_restorer always. +#if defined(ARCH_CPU_X86_64) +#if !defined(SA_RESTORER) +#define SA_RESTORER 0x04000000 +#endif + +// rt_sigreturn is a special system call that interacts with the user land +// stack. Thus, here prologue must not be created, which implies syscall() +// does not work properly, too. Note that rt_sigreturn will never return. +static __attribute__((naked)) void sys_rt_sigreturn() { + // Just invoke rt_sigreturn system call. + asm volatile ("syscall\n" + :: "a"(__NR_rt_sigreturn)); +} +#endif + +int sys_sigaction(int signum, + const struct sigaction* act, + struct sigaction* oldact) { + KernelSigAction kernel_act = {}; + if (act) { + kernel_act.kernel_handler = act->sa_handler; + std::memcpy(&kernel_act.sa_mask, &act->sa_mask, + std::min(sizeof(kernel_act.sa_mask), sizeof(act->sa_mask))); + kernel_act.sa_flags = act->sa_flags; + +#if defined(ARCH_CPU_X86_64) + if (!(kernel_act.sa_flags & SA_RESTORER)) { + kernel_act.sa_flags |= SA_RESTORER; + kernel_act.sa_restorer = sys_rt_sigreturn; + } +#endif + } + + KernelSigAction kernel_oldact = {}; + int result = syscall(__NR_rt_sigaction, signum, act ? &kernel_act : nullptr, + oldact ? &kernel_oldact : nullptr, sizeof(uint64_t)); + if (result == 0 && oldact) { + oldact->sa_handler = kernel_oldact.kernel_handler; + sigemptyset(&oldact->sa_mask); + std::memcpy(&oldact->sa_mask, &kernel_oldact.sa_mask, + std::min(sizeof(kernel_act.sa_mask), sizeof(act->sa_mask))); + oldact->sa_flags = kernel_oldact.sa_flags; + } + return result; +} + +#endif // defined(MEMORY_SANITIZER) + } // namespace sandbox diff --git a/sandbox/linux/services/syscall_wrappers.h b/sandbox/linux/services/syscall_wrappers.h index 4558adf..581425a 100644 --- a/sandbox/linux/services/syscall_wrappers.h +++ b/sandbox/linux/services/syscall_wrappers.h @@ -5,6 +5,7 @@ #ifndef SANDBOX_LINUX_SERVICES_SYSCALL_WRAPPERS_H_ #define SANDBOX_LINUX_SERVICES_SYSCALL_WRAPPERS_H_ +#include <signal.h> #include <stdint.h> #include <sys/types.h> @@ -66,6 +67,17 @@ SANDBOX_EXPORT int sys_chroot(const char* path); // Some libcs do not expose a unshare wrapper. SANDBOX_EXPORT int sys_unshare(int flags); +// Some libcs do not expose a sigprocmask. Note that oldset must be a nullptr, +// because of some ABI gap between toolchain's and Linux's. +SANDBOX_EXPORT int sys_sigprocmask(int how, + const sigset_t* set, + decltype(nullptr) oldset); + +// Some libcs do not expose a sigaction(). +SANDBOX_EXPORT int sys_sigaction(int signum, + const struct sigaction* act, + struct sigaction* oldact); + } // namespace sandbox #endif // SANDBOX_LINUX_SERVICES_SYSCALL_WRAPPERS_H_ diff --git a/sandbox/linux/services/syscall_wrappers_unittest.cc b/sandbox/linux/services/syscall_wrappers_unittest.cc index 6a70beb..1878ff3 100644 --- a/sandbox/linux/services/syscall_wrappers_unittest.cc +++ b/sandbox/linux/services/syscall_wrappers_unittest.cc @@ -8,11 +8,13 @@ #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> +#include <cstring> #include "base/logging.h" #include "base/posix/eintr_wrapper.h" #include "base/third_party/valgrind/valgrind.h" #include "build/build_config.h" +#include "sandbox/linux/system_headers/linux_signal.h" #include "sandbox/linux/tests/test_utils.h" #include "sandbox/linux/tests/unit_tests.h" #include "testing/gtest/include/gtest/gtest.h" @@ -80,6 +82,18 @@ TEST(SyscallWrappers, GetRESGid) { EXPECT_EQ(sgid, sys_sgid); } +TEST(SyscallWrappers, LinuxSigSet) { + sigset_t sigset; + ASSERT_EQ(0, sigemptyset(&sigset)); + ASSERT_EQ(0, sigaddset(&sigset, LINUX_SIGSEGV)); + ASSERT_EQ(0, sigaddset(&sigset, LINUX_SIGBUS)); + uint64_t linux_sigset = 0; + std::memcpy(&linux_sigset, &sigset, + std::min(sizeof(sigset), sizeof(linux_sigset))); + EXPECT_EQ((1ULL << (LINUX_SIGSEGV - 1)) | (1ULL << (LINUX_SIGBUS - 1)), + linux_sigset); +} + } // namespace } // namespace sandbox diff --git a/sandbox/linux/system_headers/android_arm_ucontext.h b/sandbox/linux/system_headers/android_arm_ucontext.h deleted file mode 100644 index a380499..0000000 --- a/sandbox/linux/system_headers/android_arm_ucontext.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2012 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_SYSTEM_HEADERS_ANDROID_ARM_UCONTEXT_H_ -#define SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_ARM_UCONTEXT_H_ - -#if !defined(__BIONIC_HAVE_UCONTEXT_T) -#include <asm/sigcontext.h> - -// We also need greg_t for the sandbox, include it in this header as well. -typedef unsigned long greg_t; - -//typedef unsigned long sigset_t; -typedef struct ucontext { - unsigned long uc_flags; - struct ucontext *uc_link; - stack_t uc_stack; - struct sigcontext uc_mcontext; - sigset_t uc_sigmask; - /* Allow for uc_sigmask growth. Glibc uses a 1024-bit sigset_t. */ - int __not_used[32 - (sizeof (sigset_t) / sizeof (int))]; - /* Last for extensibility. Eight byte aligned because some - coprocessors require eight byte alignment. */ - unsigned long uc_regspace[128] __attribute__((__aligned__(8))); -} ucontext_t; - -#else -#include <sys/ucontext.h> -#endif // __BIONIC_HAVE_UCONTEXT_T - -#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_ARM_UCONTEXT_H_ diff --git a/sandbox/linux/system_headers/android_ucontext.h b/sandbox/linux/system_headers/android_ucontext.h deleted file mode 100644 index 8e873be..0000000 --- a/sandbox/linux/system_headers/android_ucontext.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2013 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_SYSTEM_HEADERS_ANDROID_UCONTEXT_H_ -#define SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_UCONTEXT_H_ - -#if defined(__ANDROID__) - -#if defined(__arm__) -#include "sandbox/linux/system_headers/android_arm_ucontext.h" -#elif defined(__i386__) -#include "sandbox/linux/system_headers/android_i386_ucontext.h" -#elif defined(__x86_64__) -#include "sandbox/linux/system_headers/android_x86_64_ucontext.h" -#elif defined(__mips__) -#include "sandbox/linux/system_headers/android_mips_ucontext.h" -#elif defined(__aarch64__) -#include "sandbox/linux/system_headers/android_arm64_ucontext.h" -#else -#error "No support for your architecture in Android header" -#endif - -#else // __ANDROID__ -#error "Android header file included on non Android." -#endif // __ANDROID__ - -#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_UCONTEXT_H_ diff --git a/sandbox/linux/system_headers/android_arm64_ucontext.h b/sandbox/linux/system_headers/arm64_linux_ucontext.h index df2b66a..46e0407 100644 --- a/sandbox/linux/system_headers/android_arm64_ucontext.h +++ b/sandbox/linux/system_headers/arm64_linux_ucontext.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_ARM64_UCONTEXT_H_ -#define SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_ARM64_UCONTEXT_H_ +#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ARM64_LINUX_UCONTEXT_H_ +#define SANDBOX_LINUX_SYSTEM_HEADERS_ARM64_LINUX_UCONTEXT_H_ #if !defined(__BIONIC_HAVE_UCONTEXT_T) #include <asm/sigcontext.h> @@ -26,4 +26,4 @@ struct ucontext_t { #include <sys/ucontext.h> #endif // __BIONIC_HAVE_UCONTEXT_T -#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_ARM64_UCONTEXT_H_ +#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ARM64_LINUX_UCONTEXT_H_ diff --git a/sandbox/linux/system_headers/arm_linux_ucontext.h b/sandbox/linux/system_headers/arm_linux_ucontext.h new file mode 100644 index 0000000..0eb723a --- /dev/null +++ b/sandbox/linux/system_headers/arm_linux_ucontext.h @@ -0,0 +1,67 @@ +// Copyright (c) 2012 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_SYSTEM_HEADERS_ARM_LINUX_UCONTEXT_H_ +#define SANDBOX_LINUX_SYSTEM_HEADERS_ARM_LINUX_UCONTEXT_H_ + +#if !defined(__BIONIC_HAVE_UCONTEXT_T) +#if !defined(__native_client_nonsfi__) +#include <asm/sigcontext.h> +#else +// In PNaCl toolchain, sigcontext and stack_t is not defined. So here declare +// them. +struct sigcontext { + unsigned long trap_no; + unsigned long error_code; + unsigned long oldmask; + unsigned long arm_r0; + unsigned long arm_r1; + unsigned long arm_r2; + unsigned long arm_r3; + unsigned long arm_r4; + unsigned long arm_r5; + unsigned long arm_r6; + unsigned long arm_r7; + unsigned long arm_r8; + unsigned long arm_r9; + unsigned long arm_r10; + unsigned long arm_fp; + unsigned long arm_ip; + unsigned long arm_sp; + unsigned long arm_lr; + unsigned long arm_pc; + unsigned long arm_cpsr; + unsigned long fault_address; +}; + +typedef struct sigaltstack { + void* ss_sp; + int ss_flags; + size_t ss_size; +} stack_t; + +#endif + +// We also need greg_t for the sandbox, include it in this header as well. +typedef unsigned long greg_t; + +// typedef unsigned long sigset_t; +typedef struct ucontext { + unsigned long uc_flags; + struct ucontext* uc_link; + stack_t uc_stack; + struct sigcontext uc_mcontext; + sigset_t uc_sigmask; + /* Allow for uc_sigmask growth. Glibc uses a 1024-bit sigset_t. */ + int __not_used[32 - (sizeof(sigset_t) / sizeof(int))]; + /* Last for extensibility. Eight byte aligned because some + coprocessors require eight byte alignment. */ + unsigned long uc_regspace[128] __attribute__((__aligned__(8))); +} ucontext_t; + +#else +#include <sys/ucontext.h> +#endif // __BIONIC_HAVE_UCONTEXT_T + +#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ARM_LINUX_UCONTEXT_H_ diff --git a/sandbox/linux/system_headers/android_i386_ucontext.h b/sandbox/linux/system_headers/i386_linux_ucontext.h index 868016b..61d9f7a 100644 --- a/sandbox/linux/system_headers/android_i386_ucontext.h +++ b/sandbox/linux/system_headers/i386_linux_ucontext.h @@ -11,7 +11,16 @@ // except we do use sigset_t for uc_sigmask instead of a custom type. #if !defined(__BIONIC_HAVE_UCONTEXT_T) +#if !defined(__native_client_nonsfi__) #include <asm/sigcontext.h> +#else +// In PNaCl toolchain, sigcontext is not defined. So here declare it. +typedef struct sigaltstack { + void* ss_sp; + int ss_flags; + size_t ss_size; +} stack_t; +#endif /* 80-bit floating-point register */ struct _libc_fpreg { @@ -68,7 +77,12 @@ typedef struct ucontext { struct ucontext* uc_link; stack_t uc_stack; mcontext_t uc_mcontext; - sigset_t uc_sigmask; + // Android and PNaCl toolchain's sigset_t has only 32 bits, though Linux + // ABI requires 64 bits. + union { + sigset_t uc_sigmask; + uint32_t kernel_sigmask[2]; + }; struct _libc_fpstate __fpregs_mem; } ucontext_t; diff --git a/sandbox/linux/system_headers/linux_signal.h b/sandbox/linux/system_headers/linux_signal.h new file mode 100644 index 0000000..5db7fc5 --- /dev/null +++ b/sandbox/linux/system_headers/linux_signal.h @@ -0,0 +1,73 @@ +// Copyright 2015 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_SYSTEM_HEADERS_LINUX_SIGNAL_H_ +#define SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_SIGNAL_H_ + +// NOTE: On some toolchains, signal related ABI is incompatible with Linux's +// (not undefined, but defined different values and in different memory +// layouts). So, fill the gap here. + +#if defined(__native_client_nonsfi__) +#if !defined(__i386__) && !defined(__arm__) +#error "Unsupported platform" +#endif + +#include <signal.h> + +#define LINUX_SIGBUS 7 // 10 in PNaCl toolchain. +#define LINUX_SIGSEGV 11 // 11 in PNaCl toolchain. Defined for consistency. +#define LINUX_SIGCHLD 17 // 20 in PNaCl toolchain. +#define LINUX_SIGSYS 31 // 12 in PNaCl toolchain. + +#define LINUX_SIG_BLOCK 0 // 1 in PNaCl toolchain. +#define LINUX_SIG_UNBLOCK 1 // 2 in PNaCl toolchain. + +#define LINUX_SA_SIGINFO 4 // 2 in PNaCl toolchain. +#define LINUX_SA_NODEFER 0x40000000 // Undefined in PNaCl toolchain. +#define LINUX_SA_RESTART 0x10000000 // Undefined in PNaCl toolchain. + +#define LINUX_SIG_DFL 0 // In PNaCl toolchain, unneeded cast is applied. + +struct LinuxSigInfo { + int si_signo; + int si_errno; + int si_code; + + // Extra data is followed by the |si_code|. The length depends on the + // signal number. + char _sifields[1]; +}; + +#include "sandbox/linux/system_headers/linux_ucontext.h" + +#else // !defined(__native_client_nonsfi__) + +// Just alias the toolchain's value. +#include <signal.h> + +#define LINUX_SIGBUS SIGBUS +#define LINUX_SIGSEGV SIGSEGV +#define LINUX_SIGCHLD SIGCHLD +#define LINUX_SIGSYS SIGSYS + +#define LINUX_SIG_BLOCK SIG_BLOCK +#define LINUX_SIG_UNBLOCK SIG_UNBLOCK + +#define LINUX_SA_SIGINFO SA_SIGINFO +#define LINUX_SA_NODEFER SA_NODEFER +#define LINUX_SA_RESTART SA_RESTART + +#define LINUX_SIG_DFL SIG_DFL + +typedef siginfo_t LinuxSigInfo; + +#if defined(__ANDROID__) +// Android's signal.h doesn't define ucontext etc. +#include "sandbox/linux/system_headers/linux_ucontext.h" +#endif // defined(__ANDROID__) + +#endif // !defined(__native_client_nonsfi__) + +#endif // SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_SIGNAL_H_ diff --git a/sandbox/linux/system_headers/linux_ucontext.h b/sandbox/linux/system_headers/linux_ucontext.h new file mode 100644 index 0000000..ea4d8a6 --- /dev/null +++ b/sandbox/linux/system_headers/linux_ucontext.h @@ -0,0 +1,28 @@ +// Copyright (c) 2013 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_SYSTEM_HEADERS_LINUX_UCONTEXT_H_ +#define SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_UCONTEXT_H_ + +#if defined(__ANDROID__) || defined(__native_client_nonsfi__) + +#if defined(__arm__) +#include "sandbox/linux/system_headers/arm_linux_ucontext.h" +#elif defined(__i386__) +#include "sandbox/linux/system_headers/i386_linux_ucontext.h" +#elif defined(__x86_64__) +#include "sandbox/linux/system_headers/x86_64_linux_ucontext.h" +#elif defined(__mips__) +#include "sandbox/linux/system_headers/mips_linux_ucontext.h" +#elif defined(__aarch64__) +#include "sandbox/linux/system_headers/arm64_linux_ucontext.h" +#else +#error "No support for your architecture in Android or PNaCl header" +#endif + +#else // defined(__ANDROID__) || defined(__native_client_nonsfi__) +#error "The header file included on non Android and non PNaCl." +#endif // defined(__ANDROID__) || defined(__native_client_nonsfi__) + +#endif // SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_UCONTEXT_H_ diff --git a/sandbox/linux/system_headers/android_mips_ucontext.h b/sandbox/linux/system_headers/mips_linux_ucontext.h index ec3aa63..27b3763 100644 --- a/sandbox/linux/system_headers/android_mips_ucontext.h +++ b/sandbox/linux/system_headers/mips_linux_ucontext.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_MIPS_UCONTEXT_H_ -#define SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_MIPS_UCONTEXT_H_ +#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_MIPS_LINUX_UCONTEXT_H_ +#define SANDBOX_LINUX_SYSTEM_HEADERS_MIPS_LINUX_UCONTEXT_H_ // This is mostly copied from breakpad (common/android/include/sys/ucontext.h), // except we do use sigset_t for uc_sigmask instead of a custom type. @@ -48,4 +48,4 @@ typedef struct ucontext { #include <sys/ucontext.h> #endif // __BIONIC_HAVE_UCONTEXT_T -#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_MIPS_UCONTEXT_H_ +#endif // SANDBOX_LINUX_SYSTEM_HEADERS_MIPS_LINUX_UCONTEXT_H_ diff --git a/sandbox/linux/system_headers/android_x86_64_ucontext.h b/sandbox/linux/system_headers/x86_64_linux_ucontext.h index 778e6d0..57b8919 100644 --- a/sandbox/linux/system_headers/android_x86_64_ucontext.h +++ b/sandbox/linux/system_headers/x86_64_linux_ucontext.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_X86_64_UCONTEXT_H_ -#define SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_X86_64_UCONTEXT_H_ +#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_X86_64_LINUX_UCONTEXT_H_ +#define SANDBOX_LINUX_SYSTEM_HEADERS_X86_64_LINUX_UCONTEXT_H_ // We do something compatible with glibc. Hopefully, at some point Android will // provide that for us, and __BIONIC_HAVE_UCONTEXT_T should be defined. @@ -85,4 +85,4 @@ typedef struct ucontext { #include <sys/ucontext.h> #endif // __BIONIC_HAVE_UCONTEXT_T -#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_X86_64_UCONTEXT_H_ +#endif // SANDBOX_LINUX_SYSTEM_HEADERS_X86_64_LINUX_UCONTEXT_H_ |