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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: sandbox/linux/seccomp-bpf/verifier.cc
diff --git a/sandbox/linux/seccomp-bpf/verifier.cc b/sandbox/linux/seccomp-bpf/verifier.cc
new file mode 100644
index 0000000000000000000000000000000000000000..6e706960441c392fb730afc92c50d72c5b88fc6d
--- /dev/null
+++ b/sandbox/linux/seccomp-bpf/verifier.cc
@@ -0,0 +1,145 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
+#include "sandbox/linux/seccomp-bpf/verifier.h"
+
+
+namespace playground2 {
+
+void Verifier::verifyBPF(const std::vector<struct sock_filter>& program,
+ const Sandbox::Evaluators& evaluators) {
+ // 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
+ // 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
+ // We do not implement the full BPF syntax, but only the parts that
+ // can actually be generated by our BPF compiler. If we encounter an
+ // unsupported instruction, we fail.
+ // This method is called after compiling the entire BPF filter
+ // program. It either completes without making any state changes, or
+ // 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
+ if (evaluators.size() != 1) {
+ Sandbox::die("Not implemented");
+ }
+ Sandbox::EvaluateSyscall evaluateSyscall = evaluators.begin()->first;
+ for (int sysnum = MIN_SYSCALL-1; sysnum <= MAX_SYSCALL+1; ++sysnum) {
+ // Iterate through the entire BPF program until we either return
+ // or hit an invalid instruction pointer.
+ for (State state(program, sysnum, evaluateSyscall(sysnum));
+ ;
jln (very slow on Chromium) 2012/06/07 22:55:17 This is roughly an emulator. Can be very useful. D
+ ++state.ip) {
+ if (state.ip >= program.size()) {
+ Sandbox::die("Invalid instruction pointer in BPF program");
+ }
+ const struct sock_filter& insn = program[state.ip];
+ switch (BPF_CLASS(insn.code)) {
+ case BPF_LD:
+ ld(&state, insn);
+ break;
+ case BPF_JMP:
+ jmp(&state, insn);
+ break;
+ case BPF_RET:
+ ret(&state, insn);
+ goto returned;
+ default:
+ Sandbox::die("Unexpected instruction in BPF program");
+ }
+ }
+ returned:;
+ }
+}
+
+void Verifier::ld(State *state, const struct sock_filter& insn) {
+ if (BPF_SIZE(insn.code) != BPF_W ||
+ BPF_MODE(insn.code) != BPF_ABS) {
+ compilation_failure:
+ Sandbox::die("Invalid BPF_LD instruction");
+ }
+ switch (insn.k) {
+ case offsetof(struct arch_seccomp_data, arch):
+ state->accumulator = SECCOMP_ARCH;
+ break;
+ case offsetof(struct arch_seccomp_data, nr):
+ state->accumulator = state->sysnum;
+ break;
+ default:
+ goto compilation_failure;
+ }
+ state->accIsValid = true;
+}
+
+void Verifier::jmp(State *state, const struct sock_filter& insn) {
+ if (BPF_OP(insn.code) == BPF_JA) {
+ state->ip += insn.k;
+ } else {
+ if (BPF_SRC(insn.code) != BPF_K ||
+ !state->accIsValid ||
+ state->ip + insn.jt + 1 >= state->program.size() ||
+ state->ip + insn.jf + 1 >= state->program.size()) {
+ compilation_failure:
+ Sandbox::die("Invalid BPF_JMP instruction");
+ }
+ switch (BPF_OP(insn.code)) {
+ case BPF_JEQ:
+ if (state->accumulator == insn.k) {
+ state->ip += insn.jt;
+ } else {
+ state->ip += insn.jf;
+ }
+ break;
+ case BPF_JGT:
+ if (state->accumulator > insn.k) {
+ state->ip += insn.jt;
+ } else {
+ state->ip += insn.jf;
+ }
+ break;
+ case BPF_JGE:
+ if (state->accumulator >= insn.k) {
+ state->ip += insn.jt;
+ } else {
+ state->ip += insn.jf;
+ }
+ break;
+ case BPF_JSET:
+ if (state->accumulator & insn.k) {
+ state->ip += insn.jt;
+ } else {
+ state->ip += insn.jf;
+ }
+ break;
+ default:
+ goto compilation_failure;
+ }
+ }
+}
+
+void Verifier::ret(State *state, const struct sock_filter& insn) {
+ if (BPF_SRC(insn.code) != BPF_K) {
+ compilation_failure:
+ Sandbox::die("Invalid BPF_RET instruction");
+ }
+ switch (state->err) {
+ case Sandbox::SB_TRAP:
+ if (insn.k != SECCOMP_RET_TRAP) {
+ goto compilation_failure;
+ }
+ break;
+ case Sandbox::SB_ALLOWED:
+ if (insn.k != SECCOMP_RET_ALLOW) {
+ goto compilation_failure;
+ }
+ break;
+ case Sandbox::SB_INSPECT_ARG_1...Sandbox::SB_INSPECT_ARG_6:
+ Sandbox::die("Not implemented");
+ break;
+ default:
+ if (insn.k != SECCOMP_RET_ERRNO + state->err) {
+ goto compilation_failure;
+ }
+ break;
+ }
+}
+
+} // namespace

Powered by Google App Engine
This is Rietveld 408576698