Chromium Code Reviews| 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> | 8 #include <signal.h> |
| 9 #include <string.h> | 9 #include <string.h> |
| 10 #include <sys/prctl.h> | 10 #include <sys/prctl.h> |
| 11 #include <sys/syscall.h> | 11 #include <sys/syscall.h> |
| 12 | 12 |
| 13 #include <limits> | 13 #include <limits> |
| 14 | 14 |
| 15 #include "base/logging.h" | 15 #include "base/logging.h" |
| 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/services/kernel_to_errno.h" | |
| 19 | 20 |
| 20 // Android's signal.h doesn't define ucontext etc. | 21 // Android's signal.h doesn't define ucontext etc. |
| 21 #if defined(OS_ANDROID) | 22 #if defined(OS_ANDROID) |
| 22 #include "sandbox/linux/services/android_ucontext.h" | 23 #include "sandbox/linux/services/android_ucontext.h" |
| 23 #endif | 24 #endif |
| 24 | 25 |
| 25 namespace { | 26 namespace { |
| 26 | 27 |
| 27 const int kCapacityIncrement = 20; | 28 const int kCapacityIncrement = 20; |
| 28 | 29 |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 143 // Obtain the signal context. This, most notably, gives us access to | 144 // Obtain the signal context. This, most notably, gives us access to |
| 144 // all CPU registers at the time of the signal. | 145 // all CPU registers at the time of the signal. |
| 145 ucontext_t* ctx = reinterpret_cast<ucontext_t*>(void_context); | 146 ucontext_t* ctx = reinterpret_cast<ucontext_t*>(void_context); |
| 146 | 147 |
| 147 // Obtain the siginfo information that is specific to SIGSYS. Unfortunately, | 148 // Obtain the siginfo information that is specific to SIGSYS. Unfortunately, |
| 148 // most versions of glibc don't include this information in siginfo_t. So, | 149 // most versions of glibc don't include this information in siginfo_t. So, |
| 149 // we need to explicitly copy it into a arch_sigsys structure. | 150 // we need to explicitly copy it into a arch_sigsys structure. |
| 150 struct arch_sigsys sigsys; | 151 struct arch_sigsys sigsys; |
| 151 memcpy(&sigsys, &info->_sifields, sizeof(sigsys)); | 152 memcpy(&sigsys, &info->_sifields, sizeof(sigsys)); |
| 152 | 153 |
| 154 bool sigsys_nr_is_bad = true; | |
| 155 #if defined(__mips__) | |
| 156 // When indirect syscall (syscall(__NR_foo, ...)) is made on Mips, number | |
|
jln (very slow on Chromium)
2014/05/16 19:30:17
"number" -> "the number"
nedeljko
2014/05/22 17:38:55
Done.
| |
| 157 // in register SECCOMP_SYSCALL(ctx) is always __NR_syscall and real | |
|
jln (very slow on Chromium)
2014/05/16 19:30:17
"real number" -> "the real number"
nedeljko
2014/05/22 17:38:55
Done.
| |
| 158 // number of a syscall (__NR_foo) is in SECCOMP_PARM1(ctx) | |
| 159 sigsys_nr_is_bad = sigsys.nr != static_cast<int>(SECCOMP_SYSCALL(ctx)) && | |
| 160 sigsys.nr != static_cast<int>(SECCOMP_PARM1(ctx)); | |
| 161 #else | |
| 162 sigsys_nr_is_bad = sigsys.nr != static_cast<int>(SECCOMP_SYSCALL(ctx)); | |
| 163 #endif | |
| 164 | |
| 153 // Some more sanity checks. | 165 // Some more sanity checks. |
| 154 if (sigsys.ip != reinterpret_cast<void*>(SECCOMP_IP(ctx)) || | 166 if (sigsys.ip != reinterpret_cast<void*>(SECCOMP_IP(ctx)) || |
| 155 sigsys.nr != static_cast<int>(SECCOMP_SYSCALL(ctx)) || | 167 sigsys_nr_is_bad || |
| 156 sigsys.arch != SECCOMP_ARCH) { | 168 sigsys.arch != SECCOMP_ARCH) { |
| 157 // TODO(markus): | 169 // TODO(markus): |
| 158 // SANDBOX_DIE() can call LOG(FATAL). This is not normally async-signal | 170 // SANDBOX_DIE() can call LOG(FATAL). This is not normally async-signal |
| 159 // safe and can lead to bugs. We should eventually implement a different | 171 // safe and can lead to bugs. We should eventually implement a different |
| 160 // logging and reporting mechanism that is safe to be called from | 172 // logging and reporting mechanism that is safe to be called from |
| 161 // the sigSys() handler. | 173 // the sigSys() handler. |
| 162 RAW_SANDBOX_DIE("Sanity checks are failing after receiving SIGSYS."); | 174 RAW_SANDBOX_DIE("Sanity checks are failing after receiving SIGSYS."); |
| 163 } | 175 } |
| 164 | 176 |
| 165 intptr_t rc; | 177 intptr_t rc; |
| 166 if (has_unsafe_traps_ && GetIsInSigHandler(ctx)) { | 178 if (has_unsafe_traps_ && GetIsInSigHandler(ctx)) { |
| 167 errno = old_errno; | 179 errno = old_errno; |
| 168 if (sigsys.nr == __NR_clone) { | 180 if (sigsys.nr == __NR_clone) { |
| 169 RAW_SANDBOX_DIE("Cannot call clone() from an UnsafeTrap() handler."); | 181 RAW_SANDBOX_DIE("Cannot call clone() from an UnsafeTrap() handler."); |
| 170 } | 182 } |
| 171 rc = SandboxSyscall(sigsys.nr, | 183 rc = SandboxSyscall(SECCOMP_SYSCALL(ctx), |
| 172 SECCOMP_PARM1(ctx), | 184 SECCOMP_PARM1(ctx), |
| 173 SECCOMP_PARM2(ctx), | 185 SECCOMP_PARM2(ctx), |
| 174 SECCOMP_PARM3(ctx), | 186 SECCOMP_PARM3(ctx), |
| 175 SECCOMP_PARM4(ctx), | 187 SECCOMP_PARM4(ctx), |
| 176 SECCOMP_PARM5(ctx), | 188 SECCOMP_PARM5(ctx), |
| 177 SECCOMP_PARM6(ctx)); | 189 SECCOMP_PARM6(ctx)); |
| 178 } else { | 190 } else { |
| 179 const ErrorCode& err = trap_array_[info->si_errno - 1]; | 191 const ErrorCode& err = trap_array_[info->si_errno - 1]; |
| 180 if (!err.safe_) { | 192 if (!err.safe_) { |
| 181 SetIsInSigHandler(); | 193 SetIsInSigHandler(); |
| 182 } | 194 } |
| 183 | 195 |
| 184 // Copy the seccomp-specific data into a arch_seccomp_data structure. This | 196 // 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 | 197 // is what we are showing to TrapFnc callbacks that the system call |
| 186 // evaluator registered with the sandbox. | 198 // evaluator registered with the sandbox. |
| 187 struct arch_seccomp_data data = { | 199 struct arch_seccomp_data data = { |
| 188 sigsys.nr, SECCOMP_ARCH, reinterpret_cast<uint64_t>(sigsys.ip), | 200 static_cast<int>SECCOMP_SYSCALL(ctx), SECCOMP_ARCH, |
| 201 reinterpret_cast<uint64_t>(sigsys.ip), | |
| 189 {static_cast<uint64_t>(SECCOMP_PARM1(ctx)), | 202 {static_cast<uint64_t>(SECCOMP_PARM1(ctx)), |
| 190 static_cast<uint64_t>(SECCOMP_PARM2(ctx)), | 203 static_cast<uint64_t>(SECCOMP_PARM2(ctx)), |
| 191 static_cast<uint64_t>(SECCOMP_PARM3(ctx)), | 204 static_cast<uint64_t>(SECCOMP_PARM3(ctx)), |
| 192 static_cast<uint64_t>(SECCOMP_PARM4(ctx)), | 205 static_cast<uint64_t>(SECCOMP_PARM4(ctx)), |
| 193 static_cast<uint64_t>(SECCOMP_PARM5(ctx)), | 206 static_cast<uint64_t>(SECCOMP_PARM5(ctx)), |
| 194 static_cast<uint64_t>(SECCOMP_PARM6(ctx))}}; | 207 static_cast<uint64_t>(SECCOMP_PARM6(ctx))}}; |
| 195 | 208 |
| 196 // Now call the TrapFnc callback associated with this particular instance | 209 // Now call the TrapFnc callback associated with this particular instance |
| 197 // of SECCOMP_RET_TRAP. | 210 // of SECCOMP_RET_TRAP. |
| 198 rc = err.fnc_(data, err.aux_); | 211 rc = err.fnc_(data, err.aux_); |
| 199 } | 212 } |
| 200 | 213 |
| 201 // Update the CPU register that stores the return code of the system call | 214 // Update the CPU register that stores the return code of the system call |
| 202 // that we just handled, and restore "errno" to the value that it had | 215 // that we just handled, and restore "errno" to the value that it had |
| 203 // before entering the signal handler. | 216 // before entering the signal handler. |
| 204 SECCOMP_RESULT(ctx) = static_cast<greg_t>(rc); | 217 SECCOMP_RESULT(ctx) = |
| 218 static_cast<greg_t>(RetValToKernelRet(static_cast<int>(rc), ctx)); | |
|
jln (very slow on Chromium)
2014/05/16 19:30:17
This is too commplicated. Let's have a function th
nedeljko
2014/05/22 17:38:55
Done.
| |
| 205 errno = old_errno; | 219 errno = old_errno; |
| 206 | 220 |
| 207 return; | 221 return; |
| 208 } | 222 } |
| 209 | 223 |
| 210 bool Trap::TrapKey::operator<(const TrapKey& o) const { | 224 bool Trap::TrapKey::operator<(const TrapKey& o) const { |
| 211 if (fnc != o.fnc) { | 225 if (fnc != o.fnc) { |
| 212 return fnc < o.fnc; | 226 return fnc < o.fnc; |
| 213 } else if (aux != o.aux) { | 227 } else if (aux != o.aux) { |
| 214 return aux < o.aux; | 228 return aux < o.aux; |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 348 if (global_trap_ && id > 0 && id <= global_trap_->trap_array_size_) { | 362 if (global_trap_ && id > 0 && id <= global_trap_->trap_array_size_) { |
| 349 return global_trap_->trap_array_[id - 1]; | 363 return global_trap_->trap_array_[id - 1]; |
| 350 } else { | 364 } else { |
| 351 return ErrorCode(); | 365 return ErrorCode(); |
| 352 } | 366 } |
| 353 } | 367 } |
| 354 | 368 |
| 355 Trap* Trap::global_trap_; | 369 Trap* Trap::global_trap_; |
| 356 | 370 |
| 357 } // namespace sandbox | 371 } // namespace sandbox |
| OLD | NEW |