diff options
Diffstat (limited to 'security/sandbox/chromium/sandbox/linux/bpf_dsl/dump_bpf.cc')
-rw-r--r-- | security/sandbox/chromium/sandbox/linux/bpf_dsl/dump_bpf.cc | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/security/sandbox/chromium/sandbox/linux/bpf_dsl/dump_bpf.cc b/security/sandbox/chromium/sandbox/linux/bpf_dsl/dump_bpf.cc new file mode 100644 index 0000000000..2edf592f68 --- /dev/null +++ b/security/sandbox/chromium/sandbox/linux/bpf_dsl/dump_bpf.cc @@ -0,0 +1,159 @@ +// Copyright 2014 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/bpf_dsl/dump_bpf.h" + +#include <inttypes.h> +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> + +#include <string> + +#include "base/strings/stringprintf.h" +#include "sandbox/linux/bpf_dsl/codegen.h" +#include "sandbox/linux/bpf_dsl/seccomp_macros.h" +#include "sandbox/linux/bpf_dsl/trap_registry.h" +#include "sandbox/linux/system_headers/linux_filter.h" +#include "sandbox/linux/system_headers/linux_seccomp.h" + +namespace sandbox { +namespace bpf_dsl { + +namespace { + +const char* AluOpToken(uint32_t code) { + switch (BPF_OP(code)) { + case BPF_ADD: + return "+"; + case BPF_SUB: + return "-"; + case BPF_MUL: + return "*"; + case BPF_DIV: + return "/"; + case BPF_MOD: + return "%"; + case BPF_OR: + return "|"; + case BPF_XOR: + return "^"; + case BPF_AND: + return "&"; + case BPF_LSH: + return "<<"; + case BPF_RSH: + return ">>"; + default: + return "???"; + } +} + +const char* JmpOpToken(uint32_t code) { + switch (BPF_OP(code)) { + case BPF_JSET: + return "&"; + case BPF_JEQ: + return "=="; + case BPF_JGE: + return ">="; + default: + return "???"; + } +} + +const char* DataOffsetName(size_t off) { + switch (off) { + case SECCOMP_NR_IDX: + return "System call number"; + case SECCOMP_ARCH_IDX: + return "Architecture"; + case SECCOMP_IP_LSB_IDX: + return "Instruction pointer (LSB)"; + case SECCOMP_IP_MSB_IDX: + return "Instruction pointer (MSB)"; + default: + return "???"; + } +} + +void AppendInstruction(std::string* dst, size_t pc, const sock_filter& insn) { + base::StringAppendF(dst, "%3zu) ", pc); + switch (BPF_CLASS(insn.code)) { + case BPF_LD: + if (insn.code == BPF_LD + BPF_W + BPF_ABS) { + base::StringAppendF(dst, "LOAD %" PRIu32 " // ", insn.k); + size_t maybe_argno = + (insn.k - offsetof(struct arch_seccomp_data, args)) / + sizeof(uint64_t); + if (maybe_argno < 6 && insn.k == SECCOMP_ARG_LSB_IDX(maybe_argno)) { + base::StringAppendF(dst, "Argument %zu (LSB)\n", maybe_argno); + } else if (maybe_argno < 6 && + insn.k == SECCOMP_ARG_MSB_IDX(maybe_argno)) { + base::StringAppendF(dst, "Argument %zu (MSB)\n", maybe_argno); + } else { + base::StringAppendF(dst, "%s\n", DataOffsetName(insn.k)); + } + } else { + base::StringAppendF(dst, "Load ???\n"); + } + break; + case BPF_JMP: + if (BPF_OP(insn.code) == BPF_JA) { + base::StringAppendF(dst, "JMP %zu\n", pc + insn.k + 1); + } else { + base::StringAppendF( + dst, "if A %s 0x%" PRIx32 "; then JMP %zu else JMP %zu\n", + JmpOpToken(insn.code), insn.k, pc + insn.jt + 1, pc + insn.jf + 1); + } + break; + case BPF_RET: + base::StringAppendF(dst, "RET 0x%" PRIx32 " // ", insn.k); + if ((insn.k & SECCOMP_RET_ACTION) == SECCOMP_RET_TRAP) { + base::StringAppendF(dst, "Trap #%" PRIu32 "\n", + insn.k & SECCOMP_RET_DATA); + } else if ((insn.k & SECCOMP_RET_ACTION) == SECCOMP_RET_ERRNO) { + base::StringAppendF(dst, "errno = %" PRIu32 "\n", + insn.k & SECCOMP_RET_DATA); + } else if ((insn.k & SECCOMP_RET_ACTION) == SECCOMP_RET_TRACE) { + base::StringAppendF(dst, "Trace #%" PRIu32 "\n", + insn.k & SECCOMP_RET_DATA); + } else if (insn.k == SECCOMP_RET_ALLOW) { + base::StringAppendF(dst, "Allowed\n"); + } else if (insn.k == SECCOMP_RET_KILL) { + base::StringAppendF(dst, "Kill\n"); + } else { + base::StringAppendF(dst, "???\n"); + } + break; + case BPF_ALU: + if (BPF_OP(insn.code) == BPF_NEG) { + base::StringAppendF(dst, "A := -A\n"); + } else { + base::StringAppendF(dst, "A := A %s 0x%" PRIx32 "\n", + AluOpToken(insn.code), insn.k); + } + break; + default: + base::StringAppendF(dst, "???\n"); + break; + } +} + +} // namespace + +void DumpBPF::PrintProgram(const CodeGen::Program& program) { + fputs(StringPrintProgram(program).c_str(), stderr); +} + +std::string DumpBPF::StringPrintProgram(const CodeGen::Program& program) { + std::string res; + for (size_t i = 0; i < program.size(); i++) { + AppendInstruction(&res, i + 1, program[i]); + } + return res; +} + +} // namespace bpf_dsl +} // namespace sandbox |