summaryrefslogtreecommitdiffstats
path: root/sandbox/linux
diff options
context:
space:
mode:
authormdempsky <mdempsky@chromium.org>2015-08-24 15:40:26 -0700
committerCommit bot <commit-bot@chromium.org>2015-08-24 22:41:10 +0000
commite1bc35ab4d1f3da73d0532dbbcc3999fcb599fe3 (patch)
treeed72df82ff8a2fc4ddd45c98735c1d93bcdd2b0e /sandbox/linux
parent2d1b445673161962e56cf51533a181656f40ae5c (diff)
downloadchromium_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.cc220
-rw-r--r--sandbox/linux/bpf_dsl/dump_bpf.h6
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