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

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: Update GYP file 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
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 void Verifier::verifyBPF(const std::vector<struct sock_filter>& program,
12 const Sandbox::Evaluators& evaluators) {
13 // Evaluate the BPF filter program for all possible inputs and
jln (very slow on Chromium) 2012/06/07 22:55:17 Could you document the API in the interface instea
14 // verify that it computes the correct result.
jln (very slow on Chromium) 2012/06/07 22:55:17 We will probably never iterate over all possible i
15 // We do not implement the full BPF syntax, but only the parts that
16 // can actually be generated by our BPF compiler. If we encounter an
17 // unsupported instruction, we fail.
18 // This method is called after compiling the entire BPF filter
19 // program. It either completes without making any state changes, or
20 // it terminates the program by calling Sandbox::die().
jln (very slow on Chromium) 2012/06/07 22:55:17 See my remark about dying in the interface
21 if (evaluators.size() != 1) {
22 Sandbox::die("Not implemented");
23 }
24 Sandbox::EvaluateSyscall evaluateSyscall = evaluators.begin()->first;
25 for (int sysnum = MIN_SYSCALL-1; sysnum <= MAX_SYSCALL+1; ++sysnum) {
26 // Iterate through the entire BPF program until we either return
27 // or hit an invalid instruction pointer.
28 for (State state(program, sysnum, evaluateSyscall(sysnum));
29 ;
jln (very slow on Chromium) 2012/06/07 22:55:17 This is roughly an emulator. Can be very useful. D
30 ++state.ip) {
31 if (state.ip >= program.size()) {
32 Sandbox::die("Invalid instruction pointer in BPF program");
33 }
34 const struct sock_filter& insn = program[state.ip];
35 switch (BPF_CLASS(insn.code)) {
36 case BPF_LD:
37 ld(&state, insn);
38 break;
39 case BPF_JMP:
40 jmp(&state, insn);
41 break;
42 case BPF_RET:
43 ret(&state, insn);
44 goto returned;
45 default:
46 Sandbox::die("Unexpected instruction in BPF program");
47 }
48 }
49 returned:;
50 }
51 }
52
53 void Verifier::ld(State *state, const struct sock_filter& insn) {
54 if (BPF_SIZE(insn.code) != BPF_W ||
55 BPF_MODE(insn.code) != BPF_ABS) {
56 compilation_failure:
57 Sandbox::die("Invalid BPF_LD instruction");
58 }
59 switch (insn.k) {
60 case offsetof(struct arch_seccomp_data, arch):
61 state->accumulator = SECCOMP_ARCH;
62 break;
63 case offsetof(struct arch_seccomp_data, nr):
64 state->accumulator = state->sysnum;
65 break;
66 default:
67 goto compilation_failure;
68 }
69 state->accIsValid = true;
70 }
71
72 void Verifier::jmp(State *state, const struct sock_filter& insn) {
73 if (BPF_OP(insn.code) == BPF_JA) {
74 state->ip += insn.k;
75 } else {
76 if (BPF_SRC(insn.code) != BPF_K ||
77 !state->accIsValid ||
78 state->ip + insn.jt + 1 >= state->program.size() ||
79 state->ip + insn.jf + 1 >= state->program.size()) {
80 compilation_failure:
81 Sandbox::die("Invalid BPF_JMP instruction");
82 }
83 switch (BPF_OP(insn.code)) {
84 case BPF_JEQ:
85 if (state->accumulator == insn.k) {
86 state->ip += insn.jt;
87 } else {
88 state->ip += insn.jf;
89 }
90 break;
91 case BPF_JGT:
92 if (state->accumulator > insn.k) {
93 state->ip += insn.jt;
94 } else {
95 state->ip += insn.jf;
96 }
97 break;
98 case BPF_JGE:
99 if (state->accumulator >= insn.k) {
100 state->ip += insn.jt;
101 } else {
102 state->ip += insn.jf;
103 }
104 break;
105 case BPF_JSET:
106 if (state->accumulator & insn.k) {
107 state->ip += insn.jt;
108 } else {
109 state->ip += insn.jf;
110 }
111 break;
112 default:
113 goto compilation_failure;
114 }
115 }
116 }
117
118 void Verifier::ret(State *state, const struct sock_filter& insn) {
119 if (BPF_SRC(insn.code) != BPF_K) {
120 compilation_failure:
121 Sandbox::die("Invalid BPF_RET instruction");
122 }
123 switch (state->err) {
124 case Sandbox::SB_TRAP:
125 if (insn.k != SECCOMP_RET_TRAP) {
126 goto compilation_failure;
127 }
128 break;
129 case Sandbox::SB_ALLOWED:
130 if (insn.k != SECCOMP_RET_ALLOW) {
131 goto compilation_failure;
132 }
133 break;
134 case Sandbox::SB_INSPECT_ARG_1...Sandbox::SB_INSPECT_ARG_6:
135 Sandbox::die("Not implemented");
136 break;
137 default:
138 if (insn.k != SECCOMP_RET_ERRNO + state->err) {
139 goto compilation_failure;
140 }
141 break;
142 }
143 }
144
145 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698