| 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 <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 Loading... |
| 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 |
| OLD | NEW |