diff options
author | hidehiko <hidehiko@chromium.org> | 2015-04-17 07:59:28 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-04-17 14:59:48 +0000 |
commit | 3a315e3246a5191cee27216c09e669ea2d6c33d3 (patch) | |
tree | b4dfc25b3a8f2c89d154947c2a52b7fac46d5155 /sandbox | |
parent | f3bd9b49dc8eecd3352436ea4b83579da12d5364 (diff) | |
download | chromium_src-3a315e3246a5191cee27216c09e669ea2d6c33d3.zip chromium_src-3a315e3246a5191cee27216c09e669ea2d6c33d3.tar.gz chromium_src-3a315e3246a5191cee27216c09e669ea2d6c33d3.tar.bz2 |
Introduce sys_sigprocmask and sys_sigaction.
This is preparation of nacl_helper_nonsfi's secompbpf sandbox
implementation.
PNaCl toolchain's signal ABI is incompatible with Linux's.
For example, the length of sigset_t is shoter than Linux's.
(Android has also same problem).
siginfo_t has different memory layout.
Some signal numbers, including SIGBUS, SIGCHLD and SIGSYS,
or some signal flags are different.
This CL fills the gap, by introducing linux_signal.h and
two syscalls, sys_sigprocmask and sys_sigaction.
Also, as signal.h provides ucontext_t, but PNaCl toolchain
does not provides ucontext_t, this CL re-use the
android_ucontext.h (by renaming it to linux_ucontext.h).
TEST=Ran bots.
BUG=358465
CQ_EXTRA_TRYBOTS=tryserver.chromium.linux:linux_chromium_trusty32_rel,linux_arm
Review URL: https://codereview.chromium.org/1077143002
Cr-Commit-Position: refs/heads/master@{#325634}
Diffstat (limited to 'sandbox')
19 files changed, 319 insertions, 112 deletions
diff --git a/sandbox/linux/BUILD.gn b/sandbox/linux/BUILD.gn index 21f856b..c42520e 100644 --- a/sandbox/linux/BUILD.gn +++ b/sandbox/linux/BUILD.gn @@ -288,15 +288,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/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/services/credentials.cc b/sandbox/linux/services/credentials.cc index 475ce3f..883e396 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..0366051 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,63 @@ 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)); +} + +// 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 + +static void sys_rt_sigreturn() { + syscall(__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; +} + } // 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_ |