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 |