diff options
author | mdempsky <mdempsky@chromium.org> | 2015-08-24 15:40:26 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-08-24 22:41:10 +0000 |
commit | e1bc35ab4d1f3da73d0532dbbcc3999fcb599fe3 (patch) | |
tree | ed72df82ff8a2fc4ddd45c98735c1d93bcdd2b0e /sandbox/linux | |
parent | 2d1b445673161962e56cf51533a181656f40ae5c (diff) | |
download | chromium_src-e1bc35ab4d1f3da73d0532dbbcc3999fcb599fe3.zip chromium_src-e1bc35ab4d1f3da73d0532dbbcc3999fcb599fe3.tar.gz chromium_src-e1bc35ab4d1f3da73d0532dbbcc3999fcb599fe3.tar.bz2 |
sandbox/linux/bpf_dsl: add DumpBPF::StringPrintProgram
Android doesn't have open_memstream, so the code had to be cleaned up
to use something else. base::StringAppendF seems like the least bad
option, and this code will eventually be test-only code anyway.
While here, clean up the code to be clang-format'able. Also, satisfy
my pedantic side by switching from int casts to using <inttypes.h>.
BUG=414363
Review URL: https://codereview.chromium.org/1310683002
Cr-Commit-Position: refs/heads/master@{#345195}
Diffstat (limited to 'sandbox/linux')
-rw-r--r-- | sandbox/linux/bpf_dsl/dump_bpf.cc | 220 | ||||
-rw-r--r-- | sandbox/linux/bpf_dsl/dump_bpf.h | 6 |
2 files changed, 140 insertions, 86 deletions
diff --git a/sandbox/linux/bpf_dsl/dump_bpf.cc b/sandbox/linux/bpf_dsl/dump_bpf.cc index d0c8f75..29d28a6 100644 --- a/sandbox/linux/bpf_dsl/dump_bpf.cc +++ b/sandbox/linux/bpf_dsl/dump_bpf.cc @@ -4,9 +4,14 @@ #include "sandbox/linux/bpf_dsl/dump_bpf.h" +#include <inttypes.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" @@ -14,95 +19,138 @@ namespace sandbox { namespace bpf_dsl { -void DumpBPF::PrintProgram(const CodeGen::Program& program) { - for (CodeGen::Program::const_iterator iter = program.begin(); - iter != program.end(); - ++iter) { - int ip = (int)(iter - program.begin()); - fprintf(stderr, "%3d) ", ip); - switch (BPF_CLASS(iter->code)) { - case BPF_LD: - if (iter->code == BPF_LD + BPF_W + BPF_ABS) { - fprintf(stderr, "LOAD %d // ", (int)iter->k); - if (iter->k == offsetof(struct arch_seccomp_data, nr)) { - fprintf(stderr, "System call number\n"); - } else if (iter->k == offsetof(struct arch_seccomp_data, arch)) { - fprintf(stderr, "Architecture\n"); - } else if (iter->k == - offsetof(struct arch_seccomp_data, instruction_pointer)) { - fprintf(stderr, "Instruction pointer (LSB)\n"); - } else if (iter->k == - offsetof(struct arch_seccomp_data, instruction_pointer) + - 4) { - fprintf(stderr, "Instruction pointer (MSB)\n"); - } else if (iter->k >= offsetof(struct arch_seccomp_data, args) && - iter->k < offsetof(struct arch_seccomp_data, args) + 48 && - (iter->k - offsetof(struct arch_seccomp_data, args)) % 4 == - 0) { - fprintf( - stderr, - "Argument %d (%cSB)\n", - (int)(iter->k - offsetof(struct arch_seccomp_data, args)) / 8, - (iter->k - offsetof(struct arch_seccomp_data, args)) % 8 ? 'M' - : 'L'); - } else { - fprintf(stderr, "???\n"); - } - } else { - fprintf(stderr, "LOAD ???\n"); - } - break; - case BPF_JMP: - if (BPF_OP(iter->code) == BPF_JA) { - fprintf(stderr, "JMP %d\n", ip + iter->k + 1); - } else { - fprintf(stderr, "if A %s 0x%x; then JMP %d else JMP %d\n", - BPF_OP(iter->code) == BPF_JSET ? "&" : - BPF_OP(iter->code) == BPF_JEQ ? "==" : - BPF_OP(iter->code) == BPF_JGE ? ">=" : - BPF_OP(iter->code) == BPF_JGT ? ">" : "???", - (int)iter->k, - ip + iter->jt + 1, ip + iter->jf + 1); - } - break; - case BPF_RET: - fprintf(stderr, "RET 0x%x // ", iter->k); - if ((iter->k & SECCOMP_RET_ACTION) == SECCOMP_RET_TRAP) { - fprintf(stderr, "Trap #%d\n", iter->k & SECCOMP_RET_DATA); - } else if ((iter->k & SECCOMP_RET_ACTION) == SECCOMP_RET_ERRNO) { - fprintf(stderr, "errno = %d\n", iter->k & SECCOMP_RET_DATA); - } else if ((iter->k & SECCOMP_RET_ACTION) == SECCOMP_RET_TRACE) { - fprintf(stderr, "Trace #%d\n", iter->k & SECCOMP_RET_DATA); - } else if (iter->k == SECCOMP_RET_ALLOW) { - fprintf(stderr, "Allowed\n"); - } else { - fprintf(stderr, "???\n"); - } - break; - case BPF_ALU: - if (BPF_OP(iter->code) == BPF_NEG) { - fprintf(stderr, "A := -A\n"); +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 { - fprintf(stderr, "A := A %s 0x%x\n", - BPF_OP(iter->code) == BPF_ADD ? "+" : - BPF_OP(iter->code) == BPF_SUB ? "-" : - BPF_OP(iter->code) == BPF_MUL ? "*" : - BPF_OP(iter->code) == BPF_DIV ? "/" : - BPF_OP(iter->code) == BPF_MOD ? "%" : - BPF_OP(iter->code) == BPF_OR ? "|" : - BPF_OP(iter->code) == BPF_XOR ? "^" : - BPF_OP(iter->code) == BPF_AND ? "&" : - BPF_OP(iter->code) == BPF_LSH ? "<<" : - BPF_OP(iter->code) == BPF_RSH ? ">>" : "???", - (int)iter->k); + base::StringAppendF(dst, "%s\n", DataOffsetName(insn.k)); } - break; - default: - fprintf(stderr, "???\n"); - break; - } + } 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; + return res; } } // namespace bpf_dsl diff --git a/sandbox/linux/bpf_dsl/dump_bpf.h b/sandbox/linux/bpf_dsl/dump_bpf.h index cd12be7..a7db589 100644 --- a/sandbox/linux/bpf_dsl/dump_bpf.h +++ b/sandbox/linux/bpf_dsl/dump_bpf.h @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <string> + #include "sandbox/linux/bpf_dsl/codegen.h" #include "sandbox/sandbox_export.h" @@ -12,6 +14,10 @@ class SANDBOX_EXPORT DumpBPF { public: // PrintProgram writes |program| in a human-readable format to stderr. static void PrintProgram(const CodeGen::Program& program); + + // StringPrintProgram writes |program| in a human-readable format to + // a std::string. + static std::string StringPrintProgram(const CodeGen::Program& program); }; } // namespace bpf_dsl |