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> |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
143 // Obtain the signal context. This, most notably, gives us access to | 143 // Obtain the signal context. This, most notably, gives us access to |
144 // all CPU registers at the time of the signal. | 144 // all CPU registers at the time of the signal. |
145 ucontext_t* ctx = reinterpret_cast<ucontext_t*>(void_context); | 145 ucontext_t* ctx = reinterpret_cast<ucontext_t*>(void_context); |
146 | 146 |
147 // Obtain the siginfo information that is specific to SIGSYS. Unfortunately, | 147 // Obtain the siginfo information that is specific to SIGSYS. Unfortunately, |
148 // 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, |
149 // we need to explicitly copy it into a arch_sigsys structure. | 149 // we need to explicitly copy it into a arch_sigsys structure. |
150 struct arch_sigsys sigsys; | 150 struct arch_sigsys sigsys; |
151 memcpy(&sigsys, &info->_sifields, sizeof(sigsys)); | 151 memcpy(&sigsys, &info->_sifields, sizeof(sigsys)); |
152 | 152 |
| 153 #if defined(__mips__) |
| 154 // When indirect syscall (syscall(__NR_foo, ...)) is made on Mips, the |
| 155 // number in register SECCOMP_SYSCALL(ctx) is always __NR_syscall and the |
| 156 // real number of a syscall (__NR_foo) is in SECCOMP_PARM1(ctx) |
| 157 bool sigsys_nr_is_bad = sigsys.nr != static_cast<int>(SECCOMP_SYSCALL(ctx)) && |
| 158 sigsys.nr != static_cast<int>(SECCOMP_PARM1(ctx)); |
| 159 #else |
| 160 bool sigsys_nr_is_bad = sigsys.nr != static_cast<int>(SECCOMP_SYSCALL(ctx)); |
| 161 #endif |
| 162 |
153 // Some more sanity checks. | 163 // Some more sanity checks. |
154 if (sigsys.ip != reinterpret_cast<void*>(SECCOMP_IP(ctx)) || | 164 if (sigsys.ip != reinterpret_cast<void*>(SECCOMP_IP(ctx)) || |
155 sigsys.nr != static_cast<int>(SECCOMP_SYSCALL(ctx)) || | 165 sigsys_nr_is_bad || sigsys.arch != SECCOMP_ARCH) { |
156 sigsys.arch != SECCOMP_ARCH) { | |
157 // TODO(markus): | 166 // TODO(markus): |
158 // SANDBOX_DIE() can call LOG(FATAL). This is not normally async-signal | 167 // 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 | 168 // safe and can lead to bugs. We should eventually implement a different |
160 // logging and reporting mechanism that is safe to be called from | 169 // logging and reporting mechanism that is safe to be called from |
161 // the sigSys() handler. | 170 // the sigSys() handler. |
162 RAW_SANDBOX_DIE("Sanity checks are failing after receiving SIGSYS."); | 171 RAW_SANDBOX_DIE("Sanity checks are failing after receiving SIGSYS."); |
163 } | 172 } |
164 | 173 |
165 intptr_t rc; | 174 intptr_t rc; |
166 if (has_unsafe_traps_ && GetIsInSigHandler(ctx)) { | 175 if (has_unsafe_traps_ && GetIsInSigHandler(ctx)) { |
167 errno = old_errno; | 176 errno = old_errno; |
168 if (sigsys.nr == __NR_clone) { | 177 if (sigsys.nr == __NR_clone) { |
169 RAW_SANDBOX_DIE("Cannot call clone() from an UnsafeTrap() handler."); | 178 RAW_SANDBOX_DIE("Cannot call clone() from an UnsafeTrap() handler."); |
170 } | 179 } |
171 rc = Syscall::Call(sigsys.nr, | 180 #if defined(__mips__) |
| 181 // Mips supports up to eight arguments for syscall. |
| 182 // However, seccomp bpf can filter only up to six arguments, so using eight |
| 183 // arguments has sense only when using UnsafeTrap() handler. |
| 184 rc = Syscall::Call(SECCOMP_SYSCALL(ctx), |
| 185 SECCOMP_PARM1(ctx), |
| 186 SECCOMP_PARM2(ctx), |
| 187 SECCOMP_PARM3(ctx), |
| 188 SECCOMP_PARM4(ctx), |
| 189 SECCOMP_PARM5(ctx), |
| 190 SECCOMP_PARM6(ctx), |
| 191 SECCOMP_PARM7(ctx), |
| 192 SECCOMP_PARM8(ctx)); |
| 193 #else |
| 194 rc = Syscall::Call(SECCOMP_SYSCALL(ctx), |
172 SECCOMP_PARM1(ctx), | 195 SECCOMP_PARM1(ctx), |
173 SECCOMP_PARM2(ctx), | 196 SECCOMP_PARM2(ctx), |
174 SECCOMP_PARM3(ctx), | 197 SECCOMP_PARM3(ctx), |
175 SECCOMP_PARM4(ctx), | 198 SECCOMP_PARM4(ctx), |
176 SECCOMP_PARM5(ctx), | 199 SECCOMP_PARM5(ctx), |
177 SECCOMP_PARM6(ctx)); | 200 SECCOMP_PARM6(ctx)); |
| 201 #endif // defined(__mips__) |
178 } else { | 202 } else { |
179 const ErrorCode& err = trap_array_[info->si_errno - 1]; | 203 const ErrorCode& err = trap_array_[info->si_errno - 1]; |
180 if (!err.safe_) { | 204 if (!err.safe_) { |
181 SetIsInSigHandler(); | 205 SetIsInSigHandler(); |
182 } | 206 } |
183 | 207 |
184 // Copy the seccomp-specific data into a arch_seccomp_data structure. This | 208 // 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 | 209 // is what we are showing to TrapFnc callbacks that the system call |
186 // evaluator registered with the sandbox. | 210 // evaluator registered with the sandbox. |
187 struct arch_seccomp_data data = { | 211 struct arch_seccomp_data data = { |
188 sigsys.nr, SECCOMP_ARCH, reinterpret_cast<uint64_t>(sigsys.ip), | 212 static_cast<int>(SECCOMP_SYSCALL(ctx)), |
| 213 SECCOMP_ARCH, |
| 214 reinterpret_cast<uint64_t>(sigsys.ip), |
189 {static_cast<uint64_t>(SECCOMP_PARM1(ctx)), | 215 {static_cast<uint64_t>(SECCOMP_PARM1(ctx)), |
190 static_cast<uint64_t>(SECCOMP_PARM2(ctx)), | 216 static_cast<uint64_t>(SECCOMP_PARM2(ctx)), |
191 static_cast<uint64_t>(SECCOMP_PARM3(ctx)), | 217 static_cast<uint64_t>(SECCOMP_PARM3(ctx)), |
192 static_cast<uint64_t>(SECCOMP_PARM4(ctx)), | 218 static_cast<uint64_t>(SECCOMP_PARM4(ctx)), |
193 static_cast<uint64_t>(SECCOMP_PARM5(ctx)), | 219 static_cast<uint64_t>(SECCOMP_PARM5(ctx)), |
194 static_cast<uint64_t>(SECCOMP_PARM6(ctx))}}; | 220 static_cast<uint64_t>(SECCOMP_PARM6(ctx))}}; |
195 | 221 |
196 // Now call the TrapFnc callback associated with this particular instance | 222 // Now call the TrapFnc callback associated with this particular instance |
197 // of SECCOMP_RET_TRAP. | 223 // of SECCOMP_RET_TRAP. |
198 rc = err.fnc_(data, err.aux_); | 224 rc = err.fnc_(data, err.aux_); |
199 } | 225 } |
200 | 226 |
201 // Update the CPU register that stores the return code of the system call | 227 // 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 | 228 // that we just handled, and restore "errno" to the value that it had |
203 // before entering the signal handler. | 229 // before entering the signal handler. |
204 SECCOMP_RESULT(ctx) = static_cast<greg_t>(rc); | 230 Syscall::PutValueInUcontext(rc, ctx); |
205 errno = old_errno; | 231 errno = old_errno; |
206 | 232 |
207 return; | 233 return; |
208 } | 234 } |
209 | 235 |
210 bool Trap::TrapKey::operator<(const TrapKey& o) const { | 236 bool Trap::TrapKey::operator<(const TrapKey& o) const { |
211 if (fnc != o.fnc) { | 237 if (fnc != o.fnc) { |
212 return fnc < o.fnc; | 238 return fnc < o.fnc; |
213 } else if (aux != o.aux) { | 239 } else if (aux != o.aux) { |
214 return aux < o.aux; | 240 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_) { | 374 if (global_trap_ && id > 0 && id <= global_trap_->trap_array_size_) { |
349 return global_trap_->trap_array_[id - 1]; | 375 return global_trap_->trap_array_[id - 1]; |
350 } else { | 376 } else { |
351 return ErrorCode(); | 377 return ErrorCode(); |
352 } | 378 } |
353 } | 379 } |
354 | 380 |
355 Trap* Trap::global_trap_; | 381 Trap* Trap::global_trap_; |
356 | 382 |
357 } // namespace sandbox | 383 } // namespace sandbox |
OLD | NEW |