| 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/sandbox_bpf.h" | 5 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" |
| 6 #include "sandbox/linux/seccomp-bpf/syscall_iterator.h" |
| 6 #include "sandbox/linux/seccomp-bpf/verifier.h" | 7 #include "sandbox/linux/seccomp-bpf/verifier.h" |
| 7 | 8 |
| 8 | 9 |
| 9 namespace playground2 { | 10 namespace playground2 { |
| 10 | 11 |
| 11 bool Verifier::verifyBPF(const std::vector<struct sock_filter>& program, | 12 bool Verifier::verifyBPF(const std::vector<struct sock_filter>& program, |
| 12 const Sandbox::Evaluators& evaluators, | 13 const Sandbox::Evaluators& evaluators, |
| 13 const char **err) { | 14 const char **err) { |
| 14 *err = NULL; | 15 *err = NULL; |
| 15 if (evaluators.size() != 1) { | 16 if (evaluators.size() != 1) { |
| 16 *err = "Not implemented"; | 17 *err = "Not implemented"; |
| 17 return false; | 18 return false; |
| 18 } | 19 } |
| 19 Sandbox::EvaluateSyscall evaluateSyscall = evaluators.begin()->first; | 20 Sandbox::EvaluateSyscall evaluateSyscall = evaluators.begin()->first; |
| 20 for (int nr = MIN_SYSCALL-1; nr <= static_cast<int>(MAX_SYSCALL)+1; ++nr) { | 21 for (SyscallIterator iter(false); !iter.Done(); ) { |
| 22 uint32_t sysnum = iter.Next(); |
| 21 // We ideally want to iterate over the full system call range and values | 23 // We ideally want to iterate over the full system call range and values |
| 22 // just above and just below this range. This gives us the full result set | 24 // just above and just below this range. This gives us the full result set |
| 23 // of the "evaluators". | 25 // of the "evaluators". |
| 24 // On Intel systems, this can fail in a surprising way, as a cleared bit 30 | 26 // On Intel systems, this can fail in a surprising way, as a cleared bit 30 |
| 25 // indicates either i386 or x86-64; and a set bit 30 indicates x32. And | 27 // indicates either i386 or x86-64; and a set bit 30 indicates x32. And |
| 26 // unless we pay attention to setting this bit correctly, an early check in | 28 // unless we pay attention to setting this bit correctly, an early check in |
| 27 // our BPF program will make us fail with a misleading error code. | 29 // our BPF program will make us fail with a misleading error code. |
| 30 struct arch_seccomp_data data = { sysnum, SECCOMP_ARCH }; |
| 28 #if defined(__i386__) || defined(__x86_64__) | 31 #if defined(__i386__) || defined(__x86_64__) |
| 29 #if defined(__x86_64__) && defined(__ILP32__) | 32 #if defined(__x86_64__) && defined(__ILP32__) |
| 30 int sysnum = nr | 0x40000000; | 33 if (!(sysnum & 0x40000000u)) { |
| 34 continue; |
| 35 } |
| 31 #else | 36 #else |
| 32 int sysnum = nr & ~0x40000000; | 37 if (sysnum & 0x40000000u) { |
| 38 continue; |
| 39 } |
| 33 #endif | 40 #endif |
| 34 #else | |
| 35 int sysnum = nr; | |
| 36 #endif | 41 #endif |
| 37 | |
| 38 struct arch_seccomp_data data = { sysnum, SECCOMP_ARCH }; | |
| 39 ErrorCode code = evaluateSyscall(sysnum); | 42 ErrorCode code = evaluateSyscall(sysnum); |
| 40 uint32_t computedRet = evaluateBPF(program, data, err); | 43 uint32_t computedRet = evaluateBPF(program, data, err); |
| 41 if (*err) { | 44 if (*err) { |
| 42 return false; | 45 return false; |
| 43 } else if (computedRet != code.err()) { | 46 } else if (computedRet != code.err()) { |
| 44 *err = "Exit code from BPF program doesn't match"; | 47 *err = "Exit code from BPF program doesn't match"; |
| 45 return false; | 48 return false; |
| 46 } | 49 } |
| 47 } | 50 } |
| 48 return true; | 51 return true; |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 uint32_t Verifier::ret(State *, const struct sock_filter& insn, | 157 uint32_t Verifier::ret(State *, const struct sock_filter& insn, |
| 155 const char **err) { | 158 const char **err) { |
| 156 if (BPF_SRC(insn.code) != BPF_K) { | 159 if (BPF_SRC(insn.code) != BPF_K) { |
| 157 *err = "Invalid BPF_RET instruction"; | 160 *err = "Invalid BPF_RET instruction"; |
| 158 return 0; | 161 return 0; |
| 159 } | 162 } |
| 160 return insn.k; | 163 return insn.k; |
| 161 } | 164 } |
| 162 | 165 |
| 163 } // namespace | 166 } // namespace |
| OLD | NEW |