OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "sandbox/linux/seccomp-bpf/trap.h" | 5 #include "sandbox/linux/seccomp-bpf/trap.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <signal.h> | |
9 #include <string.h> | 8 #include <string.h> |
10 #include <sys/syscall.h> | 9 #include <sys/syscall.h> |
11 | 10 |
12 #include <algorithm> | 11 #include <algorithm> |
13 #include <limits> | 12 #include <limits> |
14 | 13 |
15 #include "base/logging.h" | 14 #include "base/logging.h" |
16 #include "build/build_config.h" | 15 #include "build/build_config.h" |
17 #include "sandbox/linux/bpf_dsl/seccomp_macros.h" | 16 #include "sandbox/linux/bpf_dsl/seccomp_macros.h" |
18 #include "sandbox/linux/seccomp-bpf/die.h" | 17 #include "sandbox/linux/seccomp-bpf/die.h" |
19 #include "sandbox/linux/seccomp-bpf/syscall.h" | 18 #include "sandbox/linux/seccomp-bpf/syscall.h" |
| 19 #include "sandbox/linux/services/syscall_wrappers.h" |
20 #include "sandbox/linux/system_headers/linux_seccomp.h" | 20 #include "sandbox/linux/system_headers/linux_seccomp.h" |
| 21 #include "sandbox/linux/system_headers/linux_signal.h" |
21 | 22 |
22 // Android's signal.h doesn't define ucontext etc. | 23 // Android's signal.h doesn't define ucontext etc. |
23 #if defined(OS_ANDROID) | 24 #if defined(OS_ANDROID) || defined(OS_NACL_NONSFI) |
24 #include "sandbox/linux/system_headers/android_ucontext.h" | 25 #include "sandbox/linux/system_headers/android_ucontext.h" |
25 #endif | 26 #endif |
26 | 27 |
27 namespace { | 28 namespace { |
28 | 29 |
29 struct arch_sigsys { | 30 // TODO: Where is the best place to put these? |
30 void* ip; | 31 int linux_sigemptyset(linux_sigset_t* sigset) { |
31 int nr; | 32 memset(sigset, 0, sizeof(*sigset)); |
32 unsigned int arch; | 33 return 0; |
33 }; | 34 } |
| 35 |
| 36 // TODO: do we need to support 64-bits? |
| 37 int linux_sigaddset(linux_sigset_t* sigset, int signum) { |
| 38 sigset->sig[0] |= (1 << (signum - 1)); |
| 39 return 0; |
| 40 } |
| 41 |
| 42 // TODO: do we need to support 64-bits? |
| 43 int linux_sigismember(const linux_sigset_t *sigset, int signum) { |
| 44 return (sigset->sig[0] >> (signum - 1)) & 1; |
| 45 } |
34 | 46 |
35 const int kCapacityIncrement = 20; | 47 const int kCapacityIncrement = 20; |
36 | 48 |
37 // Unsafe traps can only be turned on, if the user explicitly allowed them | 49 // Unsafe traps can only be turned on, if the user explicitly allowed them |
38 // by setting the CHROME_SANDBOX_DEBUGGING environment variable. | 50 // by setting the CHROME_SANDBOX_DEBUGGING environment variable. |
39 const char kSandboxDebuggingEnv[] = "CHROME_SANDBOX_DEBUGGING"; | 51 const char kSandboxDebuggingEnv[] = "CHROME_SANDBOX_DEBUGGING"; |
40 | 52 |
41 // We need to tell whether we are performing a "normal" callback, or | 53 // We need to tell whether we are performing a "normal" callback, or |
42 // whether we were called recursively from within a UnsafeTrap() callback. | 54 // whether we were called recursively from within a UnsafeTrap() callback. |
43 // This is a little tricky to do, because we need to somehow get access to | 55 // This is a little tricky to do, because we need to somehow get access to |
44 // per-thread data from within a signal context. Normal TLS storage is not | 56 // per-thread data from within a signal context. Normal TLS storage is not |
45 // safely accessible at this time. We could roll our own, but that involves | 57 // safely accessible at this time. We could roll our own, but that involves |
46 // a lot of complexity. Instead, we co-opt one bit in the signal mask. | 58 // a lot of complexity. Instead, we co-opt one bit in the signal mask. |
47 // If BUS is blocked, we assume that we have been called recursively. | 59 // If BUS is blocked, we assume that we have been called recursively. |
48 // There is a possibility for collision with other code that needs to do | 60 // There is a possibility for collision with other code that needs to do |
49 // this, but in practice the risks are low. | 61 // this, but in practice the risks are low. |
50 // If SIGBUS turns out to be a problem, we could instead co-opt one of the | 62 // If SIGBUS turns out to be a problem, we could instead co-opt one of the |
51 // realtime signals. There are plenty of them. Unfortunately, there is no | 63 // realtime signals. There are plenty of them. Unfortunately, there is no |
52 // way to mark a signal as allocated. So, the potential for collision is | 64 // way to mark a signal as allocated. So, the potential for collision is |
53 // possibly even worse. | 65 // possibly even worse. |
54 bool GetIsInSigHandler(const ucontext_t* ctx) { | 66 bool GetIsInSigHandler(const ucontext_t* ctx) { |
55 // Note: on Android, sigismember does not take a pointer to const. | 67 return linux_sigismember( |
56 return sigismember(const_cast<sigset_t*>(&ctx->uc_sigmask), SIGBUS); | 68 reinterpret_cast<const linux_sigset_t*>(&ctx->uc_sigmask), |
| 69 LINUX_SIGBUS); |
57 } | 70 } |
58 | 71 |
59 void SetIsInSigHandler() { | 72 void SetIsInSigHandler() { |
60 sigset_t mask; | 73 linux_sigset_t mask; |
61 if (sigemptyset(&mask) || sigaddset(&mask, SIGBUS) || | 74 if (linux_sigemptyset(&mask) || linux_sigaddset(&mask, LINUX_SIGBUS) || |
62 sigprocmask(SIG_BLOCK, &mask, NULL)) { | 75 sandbox::sys_sigprocmask(LINUX_SIG_BLOCK, &mask, NULL)) { |
63 SANDBOX_DIE("Failed to block SIGBUS"); | 76 SANDBOX_DIE("Failed to block SIGBUS"); |
64 } | 77 } |
65 } | 78 } |
66 | 79 |
67 bool IsDefaultSignalAction(const struct sigaction& sa) { | 80 bool IsDefaultSignalAction(const struct linux_sigaction& sa) { |
68 if (sa.sa_flags & SA_SIGINFO || sa.sa_handler != SIG_DFL) { | 81 if (sa.sa_flags & LINUX_SA_SIGINFO || sa.sa_handler_ != LINUX_SIG_DFL) { |
69 return false; | 82 return false; |
70 } | 83 } |
71 return true; | 84 return true; |
72 } | 85 } |
73 | 86 |
74 } // namespace | 87 } // namespace |
75 | 88 |
76 namespace sandbox { | 89 namespace sandbox { |
77 | 90 |
78 Trap::Trap() | 91 Trap::Trap() |
79 : trap_array_(NULL), | 92 : trap_array_(NULL), |
80 trap_array_size_(0), | 93 trap_array_size_(0), |
81 trap_array_capacity_(0), | 94 trap_array_capacity_(0), |
82 has_unsafe_traps_(false) { | 95 has_unsafe_traps_(false) { |
83 // Set new SIGSYS handler | 96 // Set new SIGSYS handler |
84 struct sigaction sa = {}; | 97 struct linux_sigaction sa = {}; |
85 sa.sa_sigaction = SigSysAction; | 98 sa.sa_sigaction_ = SigSysAction; |
86 sa.sa_flags = SA_SIGINFO | SA_NODEFER; | 99 sa.sa_flags = LINUX_SA_SIGINFO | LINUX_SA_NODEFER; |
87 struct sigaction old_sa; | 100 struct linux_sigaction old_sa; |
88 if (sigaction(SIGSYS, &sa, &old_sa) < 0) { | 101 if (sys_sigaction(LINUX_SIGSYS, &sa, &old_sa) < 0) { |
89 SANDBOX_DIE("Failed to configure SIGSYS handler"); | 102 SANDBOX_DIE("Failed to configure SIGSYS handler"); |
90 } | 103 } |
91 | 104 |
92 if (!IsDefaultSignalAction(old_sa)) { | 105 if (!IsDefaultSignalAction(old_sa)) { |
93 static const char kExistingSIGSYSMsg[] = | 106 static const char kExistingSIGSYSMsg[] = |
94 "Existing signal handler when trying to install SIGSYS. SIGSYS needs " | 107 "Existing signal handler when trying to install SIGSYS. SIGSYS needs " |
95 "to be reserved for seccomp-bpf."; | 108 "to be reserved for seccomp-bpf."; |
96 DLOG(FATAL) << kExistingSIGSYSMsg; | 109 DLOG(FATAL) << kExistingSIGSYSMsg; |
97 LOG(ERROR) << kExistingSIGSYSMsg; | 110 LOG(ERROR) << kExistingSIGSYSMsg; |
98 } | 111 } |
99 | 112 |
100 // Unmask SIGSYS | 113 // Unmask SIGSYS |
101 sigset_t mask; | 114 linux_sigset_t mask; |
102 if (sigemptyset(&mask) || sigaddset(&mask, SIGSYS) || | 115 if (linux_sigemptyset(&mask) || linux_sigaddset(&mask, SIGSYS) || |
103 sigprocmask(SIG_UNBLOCK, &mask, NULL)) { | 116 sys_sigprocmask(LINUX_SIG_UNBLOCK, &mask, NULL)) { |
104 SANDBOX_DIE("Failed to configure SIGSYS handler"); | 117 SANDBOX_DIE("Failed to configure SIGSYS handler"); |
105 } | 118 } |
106 } | 119 } |
107 | 120 |
108 bpf_dsl::TrapRegistry* Trap::Registry() { | 121 bpf_dsl::TrapRegistry* Trap::Registry() { |
109 // Note: This class is not thread safe. It is the caller's responsibility | 122 // Note: This class is not thread safe. It is the caller's responsibility |
110 // to avoid race conditions. Normally, this is a non-issue as the sandbox | 123 // to avoid race conditions. Normally, this is a non-issue as the sandbox |
111 // can only be initialized if there are no other threads present. | 124 // can only be initialized if there are no other threads present. |
112 // Also, this is not a normal singleton. Once created, the global trap | 125 // Also, this is not a normal singleton. Once created, the global trap |
113 // object must never be destroyed again. | 126 // object must never be destroyed again. |
114 if (!global_trap_) { | 127 if (!global_trap_) { |
115 global_trap_ = new Trap(); | 128 global_trap_ = new Trap(); |
116 if (!global_trap_) { | 129 if (!global_trap_) { |
117 SANDBOX_DIE("Failed to allocate global trap handler"); | 130 SANDBOX_DIE("Failed to allocate global trap handler"); |
118 } | 131 } |
119 } | 132 } |
120 return global_trap_; | 133 return global_trap_; |
121 } | 134 } |
122 | 135 |
123 void Trap::SigSysAction(int nr, siginfo_t* info, void* void_context) { | 136 void Trap::SigSysAction(int nr, linux_siginfo_t* info, void* void_context) { |
124 if (!global_trap_) { | 137 if (!global_trap_) { |
125 RAW_SANDBOX_DIE( | 138 RAW_SANDBOX_DIE( |
126 "This can't happen. Found no global singleton instance " | 139 "This can't happen. Found no global singleton instance " |
127 "for Trap() handling."); | 140 "for Trap() handling."); |
128 } | 141 } |
129 global_trap_->SigSys(nr, info, void_context); | 142 global_trap_->SigSys(nr, info, void_context); |
130 } | 143 } |
131 | 144 |
132 void Trap::SigSys(int nr, siginfo_t* info, void* void_context) { | 145 void Trap::SigSys(int nr, linux_siginfo_t* info, void* void_context) { |
133 // Signal handlers should always preserve "errno". Otherwise, we could | 146 // Signal handlers should always preserve "errno". Otherwise, we could |
134 // trigger really subtle bugs. | 147 // trigger really subtle bugs. |
135 const int old_errno = errno; | 148 const int old_errno = errno; |
136 | 149 |
137 // Various sanity checks to make sure we actually received a signal | 150 // Various sanity checks to make sure we actually received a signal |
138 // triggered by a BPF filter. If something else triggered SIGSYS | 151 // triggered by a BPF filter. If something else triggered SIGSYS |
139 // (e.g. kill()), there is really nothing we can do with this signal. | 152 // (e.g. kill()), there is really nothing we can do with this signal. |
140 if (nr != SIGSYS || info->si_code != SYS_SECCOMP || !void_context || | 153 if (nr != LINUX_SIGSYS || info->si_code != SYS_SECCOMP || !void_context || |
141 info->si_errno <= 0 || | 154 info->si_errno <= 0 || |
142 static_cast<size_t>(info->si_errno) > trap_array_size_) { | 155 static_cast<size_t>(info->si_errno) > trap_array_size_) { |
143 // ATI drivers seem to send SIGSYS, so this cannot be FATAL. | 156 // ATI drivers seem to send SIGSYS, so this cannot be FATAL. |
144 // See crbug.com/178166. | 157 // See crbug.com/178166. |
145 // TODO(jln): add a DCHECK or move back to FATAL. | 158 // TODO(jln): add a DCHECK or move back to FATAL. |
146 RAW_LOG(ERROR, "Unexpected SIGSYS received."); | 159 RAW_LOG(ERROR, "Unexpected SIGSYS received."); |
147 errno = old_errno; | 160 errno = old_errno; |
148 return; | 161 return; |
149 } | 162 } |
150 | 163 |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
372 "CHROME_SANDBOX_DEBUGGING is turned on first"); | 385 "CHROME_SANDBOX_DEBUGGING is turned on first"); |
373 } | 386 } |
374 } | 387 } |
375 // Returns the, possibly updated, value of has_unsafe_traps_. | 388 // Returns the, possibly updated, value of has_unsafe_traps_. |
376 return has_unsafe_traps_; | 389 return has_unsafe_traps_; |
377 } | 390 } |
378 | 391 |
379 Trap* Trap::global_trap_; | 392 Trap* Trap::global_trap_; |
380 | 393 |
381 } // namespace sandbox | 394 } // namespace sandbox |
OLD | NEW |