Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(157)

Side by Side Diff: sandbox/linux/seccomp-bpf/trap.cc

Issue 66723007: Make sandbox/linux/seccomp-bpf/ follow the style guide. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: (empty) rebase Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « sandbox/linux/seccomp-bpf/trap.h ('k') | sandbox/linux/seccomp-bpf/verifier.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 <errno.h> 5 #include <errno.h>
6 #include <signal.h> 6 #include <signal.h>
7 #include <string.h> 7 #include <string.h>
8 #include <sys/prctl.h> 8 #include <sys/prctl.h>
9 #include <sys/syscall.h> 9 #include <sys/syscall.h>
10 10
11 #ifndef SECCOMP_BPF_STANDALONE 11 #ifndef SECCOMP_BPF_STANDALONE
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/posix/eintr_wrapper.h" 13 #include "base/posix/eintr_wrapper.h"
14 #endif 14 #endif
15 15
16 #include "sandbox/linux/seccomp-bpf/codegen.h" 16 #include "sandbox/linux/seccomp-bpf/codegen.h"
17 #include "sandbox/linux/seccomp-bpf/die.h" 17 #include "sandbox/linux/seccomp-bpf/die.h"
18 #include "sandbox/linux/seccomp-bpf/syscall.h" 18 #include "sandbox/linux/seccomp-bpf/syscall.h"
19 #include "sandbox/linux/seccomp-bpf/trap.h" 19 #include "sandbox/linux/seccomp-bpf/trap.h"
20 20
21 // Android's signal.h doesn't define ucontext etc. 21 // Android's signal.h doesn't define ucontext etc.
22 #if defined(OS_ANDROID) 22 #if defined(OS_ANDROID)
23 #include "sandbox/linux/services/android_ucontext.h" 23 #include "sandbox/linux/services/android_ucontext.h"
24 #endif 24 #endif
25 25
26 #include <limits> 26 #include <limits>
27 27
28
29 namespace { 28 namespace {
30 29
31 const int kCapacityIncrement = 20; 30 const int kCapacityIncrement = 20;
32 31
33 // Unsafe traps can only be turned on, if the user explicitly allowed them 32 // Unsafe traps can only be turned on, if the user explicitly allowed them
34 // by setting the CHROME_SANDBOX_DEBUGGING environment variable. 33 // by setting the CHROME_SANDBOX_DEBUGGING environment variable.
35 const char kSandboxDebuggingEnv[] = "CHROME_SANDBOX_DEBUGGING"; 34 const char kSandboxDebuggingEnv[] = "CHROME_SANDBOX_DEBUGGING";
36 35
37 // We need to tell whether we are performing a "normal" callback, or 36 // We need to tell whether we are performing a "normal" callback, or
38 // whether we were called recursively from within a UnsafeTrap() callback. 37 // whether we were called recursively from within a UnsafeTrap() callback.
39 // This is a little tricky to do, because we need to somehow get access to 38 // This is a little tricky to do, because we need to somehow get access to
40 // per-thread data from within a signal context. Normal TLS storage is not 39 // per-thread data from within a signal context. Normal TLS storage is not
41 // safely accessible at this time. We could roll our own, but that involves 40 // safely accessible at this time. We could roll our own, but that involves
42 // a lot of complexity. Instead, we co-opt one bit in the signal mask. 41 // a lot of complexity. Instead, we co-opt one bit in the signal mask.
43 // If BUS is blocked, we assume that we have been called recursively. 42 // If BUS is blocked, we assume that we have been called recursively.
44 // There is a possibility for collision with other code that needs to do 43 // There is a possibility for collision with other code that needs to do
45 // this, but in practice the risks are low. 44 // this, but in practice the risks are low.
46 // If SIGBUS turns out to be a problem, we could instead co-opt one of the 45 // If SIGBUS turns out to be a problem, we could instead co-opt one of the
47 // realtime signals. There are plenty of them. Unfortunately, there is no 46 // realtime signals. There are plenty of them. Unfortunately, there is no
48 // way to mark a signal as allocated. So, the potential for collision is 47 // way to mark a signal as allocated. So, the potential for collision is
49 // possibly even worse. 48 // possibly even worse.
50 bool GetIsInSigHandler(const ucontext_t *ctx) { 49 bool GetIsInSigHandler(const ucontext_t* ctx) {
51 // Note: on Android, sigismember does not take a pointer to const. 50 // Note: on Android, sigismember does not take a pointer to const.
52 return sigismember(const_cast<sigset_t*>(&ctx->uc_sigmask), SIGBUS); 51 return sigismember(const_cast<sigset_t*>(&ctx->uc_sigmask), SIGBUS);
53 } 52 }
54 53
55 void SetIsInSigHandler() { 54 void SetIsInSigHandler() {
56 sigset_t mask; 55 sigset_t mask;
57 if (sigemptyset(&mask) || 56 if (sigemptyset(&mask) || sigaddset(&mask, SIGBUS) ||
58 sigaddset(&mask, SIGBUS) ||
59 sigprocmask(SIG_BLOCK, &mask, NULL)) { 57 sigprocmask(SIG_BLOCK, &mask, NULL)) {
60 SANDBOX_DIE("Failed to block SIGBUS"); 58 SANDBOX_DIE("Failed to block SIGBUS");
61 } 59 }
62 } 60 }
63 61
64 bool IsDefaultSignalAction(const struct sigaction& sa) { 62 bool IsDefaultSignalAction(const struct sigaction& sa) {
65 if (sa.sa_flags & SA_SIGINFO || 63 if (sa.sa_flags & SA_SIGINFO || sa.sa_handler != SIG_DFL) {
66 sa.sa_handler != SIG_DFL) {
67 return false; 64 return false;
68 } 65 }
69 return true; 66 return true;
70 } 67 }
71 68
72 } // namespace 69 } // namespace
73 70
74 namespace playground2 { 71 namespace playground2 {
75 72
76 Trap::Trap() 73 Trap::Trap()
77 : trap_array_(NULL), 74 : trap_array_(NULL),
78 trap_array_size_(0), 75 trap_array_size_(0),
79 trap_array_capacity_(0), 76 trap_array_capacity_(0),
80 has_unsafe_traps_(false) { 77 has_unsafe_traps_(false) {
81 // Set new SIGSYS handler 78 // Set new SIGSYS handler
82 struct sigaction sa = { }; 79 struct sigaction sa = {};
83 sa.sa_sigaction = SigSysAction; 80 sa.sa_sigaction = SigSysAction;
84 sa.sa_flags = SA_SIGINFO | SA_NODEFER; 81 sa.sa_flags = SA_SIGINFO | SA_NODEFER;
85 struct sigaction old_sa; 82 struct sigaction old_sa;
86 if (sigaction(SIGSYS, &sa, &old_sa) < 0) { 83 if (sigaction(SIGSYS, &sa, &old_sa) < 0) {
87 SANDBOX_DIE("Failed to configure SIGSYS handler"); 84 SANDBOX_DIE("Failed to configure SIGSYS handler");
88 } 85 }
89 86
90 if (!IsDefaultSignalAction(old_sa)) { 87 if (!IsDefaultSignalAction(old_sa)) {
91 // TODO(jln): make this FATAL, at least in DEBUG mode. 88 // TODO(jln): make this FATAL, at least in DEBUG mode.
92 LOG(ERROR) << "Existing signal handler when trying to install SIGSYS"; 89 LOG(ERROR) << "Existing signal handler when trying to install SIGSYS";
93 } 90 }
94 91
95 // Unmask SIGSYS 92 // Unmask SIGSYS
96 sigset_t mask; 93 sigset_t mask;
97 if (sigemptyset(&mask) || 94 if (sigemptyset(&mask) || sigaddset(&mask, SIGSYS) ||
98 sigaddset(&mask, SIGSYS) ||
99 sigprocmask(SIG_UNBLOCK, &mask, NULL)) { 95 sigprocmask(SIG_UNBLOCK, &mask, NULL)) {
100 SANDBOX_DIE("Failed to configure SIGSYS handler"); 96 SANDBOX_DIE("Failed to configure SIGSYS handler");
101 } 97 }
102 } 98 }
103 99
104 Trap *Trap::GetInstance() { 100 Trap* Trap::GetInstance() {
105 // Note: This class is not thread safe. It is the caller's responsibility 101 // Note: This class is not thread safe. It is the caller's responsibility
106 // to avoid race conditions. Normally, this is a non-issue as the sandbox 102 // to avoid race conditions. Normally, this is a non-issue as the sandbox
107 // can only be initialized if there are no other threads present. 103 // can only be initialized if there are no other threads present.
108 // Also, this is not a normal singleton. Once created, the global trap 104 // Also, this is not a normal singleton. Once created, the global trap
109 // object must never be destroyed again. 105 // object must never be destroyed again.
110 if (!global_trap_) { 106 if (!global_trap_) {
111 global_trap_ = new Trap(); 107 global_trap_ = new Trap();
112 if (!global_trap_) { 108 if (!global_trap_) {
113 SANDBOX_DIE("Failed to allocate global trap handler"); 109 SANDBOX_DIE("Failed to allocate global trap handler");
114 } 110 }
115 } 111 }
116 return global_trap_; 112 return global_trap_;
117 } 113 }
118 114
119 void Trap::SigSysAction(int nr, siginfo_t *info, void *void_context) { 115 void Trap::SigSysAction(int nr, siginfo_t* info, void* void_context) {
120 if (!global_trap_) { 116 if (!global_trap_) {
121 RAW_SANDBOX_DIE("This can't happen. Found no global singleton instance " 117 RAW_SANDBOX_DIE(
122 "for Trap() handling."); 118 "This can't happen. Found no global singleton instance "
119 "for Trap() handling.");
123 } 120 }
124 global_trap_->SigSys(nr, info, void_context); 121 global_trap_->SigSys(nr, info, void_context);
125 } 122 }
126 123
127 void Trap::SigSys(int nr, siginfo_t *info, void *void_context) { 124 void Trap::SigSys(int nr, siginfo_t* info, void* void_context) {
128 // Signal handlers should always preserve "errno". Otherwise, we could 125 // Signal handlers should always preserve "errno". Otherwise, we could
129 // trigger really subtle bugs. 126 // trigger really subtle bugs.
130 const int old_errno = errno; 127 const int old_errno = errno;
131 128
132 // Various sanity checks to make sure we actually received a signal 129 // Various sanity checks to make sure we actually received a signal
133 // triggered by a BPF filter. If something else triggered SIGSYS 130 // triggered by a BPF filter. If something else triggered SIGSYS
134 // (e.g. kill()), there is really nothing we can do with this signal. 131 // (e.g. kill()), there is really nothing we can do with this signal.
135 if (nr != SIGSYS || info->si_code != SYS_SECCOMP || !void_context || 132 if (nr != SIGSYS || info->si_code != SYS_SECCOMP || !void_context ||
136 info->si_errno <= 0 || 133 info->si_errno <= 0 ||
137 static_cast<size_t>(info->si_errno) > trap_array_size_) { 134 static_cast<size_t>(info->si_errno) > trap_array_size_) {
138 // ATI drivers seem to send SIGSYS, so this cannot be FATAL. 135 // ATI drivers seem to send SIGSYS, so this cannot be FATAL.
139 // See crbug.com/178166. 136 // See crbug.com/178166.
140 // TODO(jln): add a DCHECK or move back to FATAL. 137 // TODO(jln): add a DCHECK or move back to FATAL.
141 RAW_LOG(ERROR, "Unexpected SIGSYS received."); 138 RAW_LOG(ERROR, "Unexpected SIGSYS received.");
142 errno = old_errno; 139 errno = old_errno;
143 return; 140 return;
144 } 141 }
145 142
146 // Obtain the signal context. This, most notably, gives us access to 143 // Obtain the signal context. This, most notably, gives us access to
147 // all CPU registers at the time of the signal. 144 // all CPU registers at the time of the signal.
148 ucontext_t *ctx = reinterpret_cast<ucontext_t *>(void_context); 145 ucontext_t* ctx = reinterpret_cast<ucontext_t*>(void_context);
149 146
150 // Obtain the siginfo information that is specific to SIGSYS. Unfortunately, 147 // Obtain the siginfo information that is specific to SIGSYS. Unfortunately,
151 // most versions of glibc don't include this information in siginfo_t. So, 148 // most versions of glibc don't include this information in siginfo_t. So,
152 // we need to explicitly copy it into a arch_sigsys structure. 149 // we need to explicitly copy it into a arch_sigsys structure.
153 struct arch_sigsys sigsys; 150 struct arch_sigsys sigsys;
154 memcpy(&sigsys, &info->_sifields, sizeof(sigsys)); 151 memcpy(&sigsys, &info->_sifields, sizeof(sigsys));
155 152
156 // Some more sanity checks. 153 // Some more sanity checks.
157 if (sigsys.ip != reinterpret_cast<void *>(SECCOMP_IP(ctx)) || 154 if (sigsys.ip != reinterpret_cast<void*>(SECCOMP_IP(ctx)) ||
158 sigsys.nr != static_cast<int>(SECCOMP_SYSCALL(ctx)) || 155 sigsys.nr != static_cast<int>(SECCOMP_SYSCALL(ctx)) ||
159 sigsys.arch != SECCOMP_ARCH) { 156 sigsys.arch != SECCOMP_ARCH) {
160 // TODO(markus): 157 // TODO(markus):
161 // SANDBOX_DIE() can call LOG(FATAL). This is not normally async-signal 158 // SANDBOX_DIE() can call LOG(FATAL). This is not normally async-signal
162 // safe and can lead to bugs. We should eventually implement a different 159 // safe and can lead to bugs. We should eventually implement a different
163 // logging and reporting mechanism that is safe to be called from 160 // logging and reporting mechanism that is safe to be called from
164 // the sigSys() handler. 161 // the sigSys() handler.
165 RAW_SANDBOX_DIE("Sanity checks are failing after receiving SIGSYS."); 162 RAW_SANDBOX_DIE("Sanity checks are failing after receiving SIGSYS.");
166 } 163 }
167 164
168 intptr_t rc; 165 intptr_t rc;
169 if (has_unsafe_traps_ && GetIsInSigHandler(ctx)) { 166 if (has_unsafe_traps_ && GetIsInSigHandler(ctx)) {
170 errno = old_errno; 167 errno = old_errno;
171 if (sigsys.nr == __NR_clone) { 168 if (sigsys.nr == __NR_clone) {
172 RAW_SANDBOX_DIE("Cannot call clone() from an UnsafeTrap() handler."); 169 RAW_SANDBOX_DIE("Cannot call clone() from an UnsafeTrap() handler.");
173 } 170 }
174 rc = SandboxSyscall(sigsys.nr, 171 rc = SandboxSyscall(sigsys.nr,
175 SECCOMP_PARM1(ctx), SECCOMP_PARM2(ctx), 172 SECCOMP_PARM1(ctx),
176 SECCOMP_PARM3(ctx), SECCOMP_PARM4(ctx), 173 SECCOMP_PARM2(ctx),
177 SECCOMP_PARM5(ctx), SECCOMP_PARM6(ctx)); 174 SECCOMP_PARM3(ctx),
175 SECCOMP_PARM4(ctx),
176 SECCOMP_PARM5(ctx),
177 SECCOMP_PARM6(ctx));
178 } else { 178 } else {
179 const ErrorCode& err = trap_array_[info->si_errno - 1]; 179 const ErrorCode& err = trap_array_[info->si_errno - 1];
180 if (!err.safe_) { 180 if (!err.safe_) {
181 SetIsInSigHandler(); 181 SetIsInSigHandler();
182 } 182 }
183 183
184 // Copy the seccomp-specific data into a arch_seccomp_data structure. This 184 // Copy the seccomp-specific data into a arch_seccomp_data structure. This
185 // is what we are showing to TrapFnc callbacks that the system call 185 // is what we are showing to TrapFnc callbacks that the system call
186 // evaluator registered with the sandbox. 186 // evaluator registered with the sandbox.
187 struct arch_seccomp_data data = { 187 struct arch_seccomp_data data = {
188 sigsys.nr, 188 sigsys.nr, SECCOMP_ARCH, reinterpret_cast<uint64_t>(sigsys.ip),
189 SECCOMP_ARCH, 189 {static_cast<uint64_t>(SECCOMP_PARM1(ctx)),
190 reinterpret_cast<uint64_t>(sigsys.ip), 190 static_cast<uint64_t>(SECCOMP_PARM2(ctx)),
191 { 191 static_cast<uint64_t>(SECCOMP_PARM3(ctx)),
192 static_cast<uint64_t>(SECCOMP_PARM1(ctx)), 192 static_cast<uint64_t>(SECCOMP_PARM4(ctx)),
193 static_cast<uint64_t>(SECCOMP_PARM2(ctx)), 193 static_cast<uint64_t>(SECCOMP_PARM5(ctx)),
194 static_cast<uint64_t>(SECCOMP_PARM3(ctx)), 194 static_cast<uint64_t>(SECCOMP_PARM6(ctx))}};
195 static_cast<uint64_t>(SECCOMP_PARM4(ctx)),
196 static_cast<uint64_t>(SECCOMP_PARM5(ctx)),
197 static_cast<uint64_t>(SECCOMP_PARM6(ctx))
198 }
199 };
200 195
201 // Now call the TrapFnc callback associated with this particular instance 196 // Now call the TrapFnc callback associated with this particular instance
202 // of SECCOMP_RET_TRAP. 197 // of SECCOMP_RET_TRAP.
203 rc = err.fnc_(data, err.aux_); 198 rc = err.fnc_(data, err.aux_);
204 } 199 }
205 200
206 // Update the CPU register that stores the return code of the system call 201 // Update the CPU register that stores the return code of the system call
207 // that we just handled, and restore "errno" to the value that it had 202 // that we just handled, and restore "errno" to the value that it had
208 // before entering the signal handler. 203 // before entering the signal handler.
209 SECCOMP_RESULT(ctx) = static_cast<greg_t>(rc); 204 SECCOMP_RESULT(ctx) = static_cast<greg_t>(rc);
210 errno = old_errno; 205 errno = old_errno;
211 206
212 return; 207 return;
213 } 208 }
214 209
215 bool Trap::TrapKey::operator<(const TrapKey& o) const { 210 bool Trap::TrapKey::operator<(const TrapKey& o) const {
216 if (fnc != o.fnc) { 211 if (fnc != o.fnc) {
217 return fnc < o.fnc; 212 return fnc < o.fnc;
218 } else if (aux != o.aux) { 213 } else if (aux != o.aux) {
219 return aux < o.aux; 214 return aux < o.aux;
220 } else { 215 } else {
221 return safe < o.safe; 216 return safe < o.safe;
222 } 217 }
223 } 218 }
224 219
225 ErrorCode Trap::MakeTrap(TrapFnc fnc, const void *aux, bool safe) { 220 ErrorCode Trap::MakeTrap(TrapFnc fnc, const void* aux, bool safe) {
226 return GetInstance()->MakeTrapImpl(fnc, aux, safe); 221 return GetInstance()->MakeTrapImpl(fnc, aux, safe);
227 } 222 }
228 223
229 ErrorCode Trap::MakeTrapImpl(TrapFnc fnc, const void *aux, bool safe) { 224 ErrorCode Trap::MakeTrapImpl(TrapFnc fnc, const void* aux, bool safe) {
230 if (!safe && !SandboxDebuggingAllowedByUser()) { 225 if (!safe && !SandboxDebuggingAllowedByUser()) {
231 // Unless the user set the CHROME_SANDBOX_DEBUGGING environment variable, 226 // Unless the user set the CHROME_SANDBOX_DEBUGGING environment variable,
232 // we never return an ErrorCode that is marked as "unsafe". This also 227 // we never return an ErrorCode that is marked as "unsafe". This also
233 // means, the BPF compiler will never emit code that allow unsafe system 228 // means, the BPF compiler will never emit code that allow unsafe system
234 // calls to by-pass the filter (because they use the magic return address 229 // calls to by-pass the filter (because they use the magic return address
235 // from SandboxSyscall(-1)). 230 // from SandboxSyscall(-1)).
236 231
237 // This SANDBOX_DIE() can optionally be removed. It won't break security, 232 // This SANDBOX_DIE() can optionally be removed. It won't break security,
238 // but it might make error messages from the BPF compiler a little harder 233 // but it might make error messages from the BPF compiler a little harder
239 // to understand. Removing the SANDBOX_DIE() allows callers to easyly check 234 // to understand. Removing the SANDBOX_DIE() allows callers to easyly check
240 // whether unsafe traps are supported (by checking whether the returned 235 // whether unsafe traps are supported (by checking whether the returned
241 // ErrorCode is ET_INVALID). 236 // ErrorCode is ET_INVALID).
242 SANDBOX_DIE("Cannot use unsafe traps unless CHROME_SANDBOX_DEBUGGING " 237 SANDBOX_DIE(
243 "is enabled"); 238 "Cannot use unsafe traps unless CHROME_SANDBOX_DEBUGGING "
239 "is enabled");
244 240
245 return ErrorCode(); 241 return ErrorCode();
246 } 242 }
247 243
248 // Each unique pair of TrapFnc and auxiliary data make up a distinct instance 244 // Each unique pair of TrapFnc and auxiliary data make up a distinct instance
249 // of a SECCOMP_RET_TRAP. 245 // of a SECCOMP_RET_TRAP.
250 TrapKey key(fnc, aux, safe); 246 TrapKey key(fnc, aux, safe);
251 TrapIds::const_iterator iter = trap_ids_.find(key); 247 TrapIds::const_iterator iter = trap_ids_.find(key);
252 248
253 // We return unique identifiers together with SECCOMP_RET_TRAP. This allows 249 // We return unique identifiers together with SECCOMP_RET_TRAP. This allows
(...skipping 29 matching lines...) Expand all
283 // Instead, we allocate a new array, copy the values, and then switch the 279 // Instead, we allocate a new array, copy the values, and then switch the
284 // pointer. We only really care about the pointer being updated atomically 280 // pointer. We only really care about the pointer being updated atomically
285 // and the data that is pointed to being valid, as these are the only 281 // and the data that is pointed to being valid, as these are the only
286 // values accessed from the signal handler. It is OK if trap_array_size_ 282 // values accessed from the signal handler. It is OK if trap_array_size_
287 // is inconsistent with the pointer, as it is monotonously increasing. 283 // is inconsistent with the pointer, as it is monotonously increasing.
288 // Also, we only care about compiler barriers, as the signal handler is 284 // Also, we only care about compiler barriers, as the signal handler is
289 // triggered synchronously from a system call. We don't have to protect 285 // triggered synchronously from a system call. We don't have to protect
290 // against issues with the memory model or with completely asynchronous 286 // against issues with the memory model or with completely asynchronous
291 // events. 287 // events.
292 if (trap_array_size_ >= trap_array_capacity_) { 288 if (trap_array_size_ >= trap_array_capacity_) {
293 trap_array_capacity_ += kCapacityIncrement; 289 trap_array_capacity_ += kCapacityIncrement;
294 ErrorCode *old_trap_array = trap_array_; 290 ErrorCode* old_trap_array = trap_array_;
295 ErrorCode *new_trap_array = new ErrorCode[trap_array_capacity_]; 291 ErrorCode* new_trap_array = new ErrorCode[trap_array_capacity_];
296 292
297 // Language specs are unclear on whether the compiler is allowed to move 293 // Language specs are unclear on whether the compiler is allowed to move
298 // the "delete[]" above our preceding assignments and/or memory moves, 294 // the "delete[]" above our preceding assignments and/or memory moves,
299 // iff the compiler believes that "delete[]" doesn't have any other 295 // iff the compiler believes that "delete[]" doesn't have any other
300 // global side-effects. 296 // global side-effects.
301 // We insert optimization barriers to prevent this from happening. 297 // We insert optimization barriers to prevent this from happening.
302 // The first barrier is probably not needed, but better be explicit in 298 // The first barrier is probably not needed, but better be explicit in
303 // what we want to tell the compiler. 299 // what we want to tell the compiler.
304 // The clang developer mailing list couldn't answer whether this is a 300 // The clang developer mailing list couldn't answer whether this is a
305 // legitimate worry; but they at least thought that the barrier is 301 // legitimate worry; but they at least thought that the barrier is
306 // sufficient to prevent the (so far hypothetical) problem of re-ordering 302 // sufficient to prevent the (so far hypothetical) problem of re-ordering
307 // of instructions by the compiler. 303 // of instructions by the compiler.
308 memcpy(new_trap_array, trap_array_, trap_array_size_*sizeof(ErrorCode)); 304 memcpy(new_trap_array, trap_array_, trap_array_size_ * sizeof(ErrorCode));
309 asm volatile("" : "=r"(new_trap_array) : "0"(new_trap_array) : "memory"); 305 asm volatile("" : "=r"(new_trap_array) : "0"(new_trap_array) : "memory");
310 trap_array_ = new_trap_array; 306 trap_array_ = new_trap_array;
311 asm volatile("" : "=r"(trap_array_) : "0"(trap_array_) : "memory"); 307 asm volatile("" : "=r"(trap_array_) : "0"(trap_array_) : "memory");
312 308
313 delete[] old_trap_array; 309 delete[] old_trap_array;
314 } 310 }
315 trap_ids_[key] = id; 311 trap_ids_[key] = id;
316 trap_array_[trap_array_size_] = ErrorCode(fnc, aux, safe, id); 312 trap_array_[trap_array_size_] = ErrorCode(fnc, aux, safe, id);
317 return trap_array_[trap_array_size_++]; 313 return trap_array_[trap_array_size_++];
318 } 314 }
319 315
320 return ErrorCode(fnc, aux, safe, id); 316 return ErrorCode(fnc, aux, safe, id);
321 } 317 }
322 318
323 bool Trap::SandboxDebuggingAllowedByUser() const { 319 bool Trap::SandboxDebuggingAllowedByUser() const {
324 const char *debug_flag = getenv(kSandboxDebuggingEnv); 320 const char* debug_flag = getenv(kSandboxDebuggingEnv);
325 return debug_flag && *debug_flag; 321 return debug_flag && *debug_flag;
326 } 322 }
327 323
328
329 bool Trap::EnableUnsafeTrapsInSigSysHandler() { 324 bool Trap::EnableUnsafeTrapsInSigSysHandler() {
330 Trap *trap = GetInstance(); 325 Trap* trap = GetInstance();
331 if (!trap->has_unsafe_traps_) { 326 if (!trap->has_unsafe_traps_) {
332 // Unsafe traps are a one-way fuse. Once enabled, they can never be turned 327 // Unsafe traps are a one-way fuse. Once enabled, they can never be turned
333 // off again. 328 // off again.
334 // We only allow enabling unsafe traps, if the user explicitly set an 329 // We only allow enabling unsafe traps, if the user explicitly set an
335 // appropriate environment variable. This prevents bugs that accidentally 330 // appropriate environment variable. This prevents bugs that accidentally
336 // disable all sandboxing for all users. 331 // disable all sandboxing for all users.
337 if (trap->SandboxDebuggingAllowedByUser()) { 332 if (trap->SandboxDebuggingAllowedByUser()) {
338 // We only ever print this message once, when we enable unsafe traps the 333 // We only ever print this message once, when we enable unsafe traps the
339 // first time. 334 // first time.
340 SANDBOX_INFO("WARNING! Disabling sandbox for debugging purposes"); 335 SANDBOX_INFO("WARNING! Disabling sandbox for debugging purposes");
341 trap->has_unsafe_traps_ = true; 336 trap->has_unsafe_traps_ = true;
342 } else { 337 } else {
343 SANDBOX_INFO("Cannot disable sandbox and use unsafe traps unless " 338 SANDBOX_INFO(
344 "CHROME_SANDBOX_DEBUGGING is turned on first"); 339 "Cannot disable sandbox and use unsafe traps unless "
340 "CHROME_SANDBOX_DEBUGGING is turned on first");
345 } 341 }
346 } 342 }
347 // Returns the, possibly updated, value of has_unsafe_traps_. 343 // Returns the, possibly updated, value of has_unsafe_traps_.
348 return trap->has_unsafe_traps_; 344 return trap->has_unsafe_traps_;
349 } 345 }
350 346
351 ErrorCode Trap::ErrorCodeFromTrapId(uint16_t id) { 347 ErrorCode Trap::ErrorCodeFromTrapId(uint16_t id) {
352 if (global_trap_ && id > 0 && id <= global_trap_->trap_array_size_) { 348 if (global_trap_ && id > 0 && id <= global_trap_->trap_array_size_) {
353 return global_trap_->trap_array_[id - 1]; 349 return global_trap_->trap_array_[id - 1];
354 } else { 350 } else {
355 return ErrorCode(); 351 return ErrorCode();
356 } 352 }
357 } 353 }
358 354
359 Trap *Trap::global_trap_; 355 Trap* Trap::global_trap_;
360 356
361 } // namespace playground2 357 } // namespace playground2
OLDNEW
« no previous file with comments | « sandbox/linux/seccomp-bpf/trap.h ('k') | sandbox/linux/seccomp-bpf/verifier.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698