Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(474)

Side by Side Diff: sandbox/linux/seccomp-bpf/verifier.cc

Issue 10546041: Added a new Verifier class to the BPF compiler. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Changes requested by Chris Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « sandbox/linux/seccomp-bpf/verifier.h ('k') | sandbox/sandbox.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
6 #include "sandbox/linux/seccomp-bpf/verifier.h"
7
8
9 namespace playground2 {
10
11 bool Verifier::verifyBPF(const std::vector<struct sock_filter>& program,
12 const Sandbox::Evaluators& evaluators,
13 const char **err) {
14 *err = NULL;
15 if (evaluators.size() != 1) {
16 *err = "Not implemented";
17 return false;
18 }
19 Sandbox::EvaluateSyscall evaluateSyscall = evaluators.begin()->first;
20 for (int nr = MIN_SYSCALL-1; nr <= MAX_SYSCALL+1; ++nr) {
21 // 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
23 // of the "evaluators".
24 // 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
26 // 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.
28 #if defined(__i386__) || defined(__x86_64__)
29 #if defined(__x86_64__) && defined(__ILP32__)
30 int sysnum = nr | 0x40000000;
31 #else
32 int sysnum = nr & ~0x40000000;
33 #endif
34 #else
35 int sysnum = nr;
36 #endif
37
38 struct arch_seccomp_data data = { sysnum, SECCOMP_ARCH };
39 uint32_t expectedRet;
40 Sandbox::ErrorCode code = evaluateSyscall(sysnum);
41 switch (code) {
42 case Sandbox::SB_TRAP:
43 expectedRet = SECCOMP_RET_TRAP;
44 break;
45 case Sandbox::SB_ALLOWED:
46 expectedRet = SECCOMP_RET_ALLOW;
47 break;
48 case Sandbox::SB_INSPECT_ARG_1...Sandbox::SB_INSPECT_ARG_6:
49 *err = "Not implemented";
50 return false;
51 default:
52 if (code >= 1 && code < 4096) {
53 expectedRet = SECCOMP_RET_ERRNO + static_cast<int>(code);
54 } else {
55 *err = "Invalid errno value";
56 return false;
57 }
58 break;
59 }
60 uint32_t computedRet = evaluateBPF(program, data, err);
61 if (*err) {
62 return false;
63 } else if (computedRet != expectedRet) {
64 *err = "Exit code from BPF program doesn't match";
65 return false;
66 }
67 }
68 return true;
69 }
70
71 uint32_t Verifier::evaluateBPF(const std::vector<struct sock_filter>& program,
72 const struct arch_seccomp_data& data,
73 const char **err) {
74 *err = NULL;
75 for (State state(program, data); !*err; ++state.ip) {
76 if (state.ip >= program.size()) {
77 *err = "Invalid instruction pointer in BPF program";
78 break;
79 }
80 const struct sock_filter& insn = program[state.ip];
81 switch (BPF_CLASS(insn.code)) {
82 case BPF_LD:
83 ld(&state, insn, err);
84 break;
85 case BPF_JMP:
86 jmp(&state, insn, err);
87 break;
88 case BPF_RET:
89 return ret(&state, insn, err);
90 default:
91 *err = "Unexpected instruction in BPF program";
92 break;
93 }
94 }
95 return 0;
96 }
97
98 void Verifier::ld(State *state, const struct sock_filter& insn,
99 const char **err) {
100 if (BPF_SIZE(insn.code) != BPF_W ||
101 BPF_MODE(insn.code) != BPF_ABS) {
102 *err = "Invalid BPF_LD instruction";
103 return;
104 }
105 if (insn.k < sizeof(struct arch_seccomp_data) && (insn.k & 3) == 0) {
106 // We only allow loading of properly aligned 32bit quantities.
107 memcpy(&state->accumulator,
108 reinterpret_cast<const char *>(&state->data) + insn.k,
109 4);
110 } else {
111 *err = "Invalid operand in BPF_LD instruction";
112 return;
113 }
114 state->accIsValid = true;
115 return;
116 }
117
118 void Verifier::jmp(State *state, const struct sock_filter& insn,
119 const char **err) {
120 if (BPF_OP(insn.code) == BPF_JA) {
121 if (state->ip + insn.k + 1 >= state->program.size()) {
Chris Evans 2012/06/12 18:23:01 Integer overflow. This would permit a huge k that
122 compilation_failure:
123 *err = "Invalid BPF_JMP instruction";
124 return;
125 }
126 state->ip += insn.k;
127 } else {
128 if (BPF_SRC(insn.code) != BPF_K ||
129 !state->accIsValid ||
130 state->ip + insn.jt + 1 >= state->program.size() ||
131 state->ip + insn.jf + 1 >= state->program.size()) {
Chris Evans 2012/06/12 18:23:01 These are integer overflow free because jt and jf
132 goto compilation_failure;
133 }
134 switch (BPF_OP(insn.code)) {
135 case BPF_JEQ:
136 if (state->accumulator == insn.k) {
137 state->ip += insn.jt;
138 } else {
139 state->ip += insn.jf;
140 }
141 break;
142 case BPF_JGT:
143 if (state->accumulator > insn.k) {
144 state->ip += insn.jt;
145 } else {
146 state->ip += insn.jf;
147 }
148 break;
149 case BPF_JGE:
150 if (state->accumulator >= insn.k) {
151 state->ip += insn.jt;
152 } else {
153 state->ip += insn.jf;
154 }
155 break;
156 case BPF_JSET:
157 if (state->accumulator & insn.k) {
158 state->ip += insn.jt;
159 } else {
160 state->ip += insn.jf;
161 }
162 break;
163 default:
164 goto compilation_failure;
165 }
166 }
167 }
168
169 uint32_t Verifier::ret(State *state, const struct sock_filter& insn,
170 const char **err) {
171 if (BPF_SRC(insn.code) != BPF_K) {
172 *err = "Invalid BPF_RET instruction";
173 return 0;
174 }
175 return insn.k;
176 }
177
178 } // namespace
OLDNEW
« no previous file with comments | « sandbox/linux/seccomp-bpf/verifier.h ('k') | sandbox/sandbox.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698