Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / sandbox / linux / bpf_dsl / dump_bpf.cc
blob29d28a67474885186d294ad0199573fc9aa32ee9
1 // Copyright 2014 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.
5 #include "sandbox/linux/bpf_dsl/dump_bpf.h"
7 #include <inttypes.h>
8 #include <stdio.h>
10 #include <string>
12 #include "base/strings/stringprintf.h"
13 #include "sandbox/linux/bpf_dsl/codegen.h"
14 #include "sandbox/linux/bpf_dsl/seccomp_macros.h"
15 #include "sandbox/linux/bpf_dsl/trap_registry.h"
16 #include "sandbox/linux/system_headers/linux_filter.h"
17 #include "sandbox/linux/system_headers/linux_seccomp.h"
19 namespace sandbox {
20 namespace bpf_dsl {
22 namespace {
24 const char* AluOpToken(uint32_t code) {
25 switch (BPF_OP(code)) {
26 case BPF_ADD:
27 return "+";
28 case BPF_SUB:
29 return "-";
30 case BPF_MUL:
31 return "*";
32 case BPF_DIV:
33 return "/";
34 case BPF_MOD:
35 return "%";
36 case BPF_OR:
37 return "|";
38 case BPF_XOR:
39 return "^";
40 case BPF_AND:
41 return "&";
42 case BPF_LSH:
43 return "<<";
44 case BPF_RSH:
45 return ">>";
46 default:
47 return "???";
51 const char* JmpOpToken(uint32_t code) {
52 switch (BPF_OP(code)) {
53 case BPF_JSET:
54 return "&";
55 case BPF_JEQ:
56 return "==";
57 case BPF_JGE:
58 return ">=";
59 default:
60 return "???";
64 const char* DataOffsetName(size_t off) {
65 switch (off) {
66 case SECCOMP_NR_IDX:
67 return "System call number";
68 case SECCOMP_ARCH_IDX:
69 return "Architecture";
70 case SECCOMP_IP_LSB_IDX:
71 return "Instruction pointer (LSB)";
72 case SECCOMP_IP_MSB_IDX:
73 return "Instruction pointer (MSB)";
74 default:
75 return "???";
79 void AppendInstruction(std::string* dst, size_t pc, const sock_filter& insn) {
80 base::StringAppendF(dst, "%3zu) ", pc);
81 switch (BPF_CLASS(insn.code)) {
82 case BPF_LD:
83 if (insn.code == BPF_LD + BPF_W + BPF_ABS) {
84 base::StringAppendF(dst, "LOAD %" PRIu32 " // ", insn.k);
85 size_t maybe_argno =
86 (insn.k - offsetof(struct arch_seccomp_data, args)) /
87 sizeof(uint64_t);
88 if (maybe_argno < 6 && insn.k == SECCOMP_ARG_LSB_IDX(maybe_argno)) {
89 base::StringAppendF(dst, "Argument %zu (LSB)\n", maybe_argno);
90 } else if (maybe_argno < 6 &&
91 insn.k == SECCOMP_ARG_MSB_IDX(maybe_argno)) {
92 base::StringAppendF(dst, "Argument %zu (MSB)\n", maybe_argno);
93 } else {
94 base::StringAppendF(dst, "%s\n", DataOffsetName(insn.k));
96 } else {
97 base::StringAppendF(dst, "Load ???\n");
99 break;
100 case BPF_JMP:
101 if (BPF_OP(insn.code) == BPF_JA) {
102 base::StringAppendF(dst, "JMP %zu\n", pc + insn.k + 1);
103 } else {
104 base::StringAppendF(
105 dst, "if A %s 0x%" PRIx32 "; then JMP %zu else JMP %zu\n",
106 JmpOpToken(insn.code), insn.k, pc + insn.jt + 1, pc + insn.jf + 1);
108 break;
109 case BPF_RET:
110 base::StringAppendF(dst, "RET 0x%" PRIx32 " // ", insn.k);
111 if ((insn.k & SECCOMP_RET_ACTION) == SECCOMP_RET_TRAP) {
112 base::StringAppendF(dst, "Trap #%" PRIu32 "\n",
113 insn.k & SECCOMP_RET_DATA);
114 } else if ((insn.k & SECCOMP_RET_ACTION) == SECCOMP_RET_ERRNO) {
115 base::StringAppendF(dst, "errno = %" PRIu32 "\n",
116 insn.k & SECCOMP_RET_DATA);
117 } else if ((insn.k & SECCOMP_RET_ACTION) == SECCOMP_RET_TRACE) {
118 base::StringAppendF(dst, "Trace #%" PRIu32 "\n",
119 insn.k & SECCOMP_RET_DATA);
120 } else if (insn.k == SECCOMP_RET_ALLOW) {
121 base::StringAppendF(dst, "Allowed\n");
122 } else if (insn.k == SECCOMP_RET_KILL) {
123 base::StringAppendF(dst, "Kill\n");
124 } else {
125 base::StringAppendF(dst, "???\n");
127 break;
128 case BPF_ALU:
129 if (BPF_OP(insn.code) == BPF_NEG) {
130 base::StringAppendF(dst, "A := -A\n");
131 } else {
132 base::StringAppendF(dst, "A := A %s 0x%" PRIx32 "\n",
133 AluOpToken(insn.code), insn.k);
135 break;
136 default:
137 base::StringAppendF(dst, "???\n");
138 break;
142 } // namespace
144 void DumpBPF::PrintProgram(const CodeGen::Program& program) {
145 fputs(StringPrintProgram(program).c_str(), stderr);
148 std::string DumpBPF::StringPrintProgram(const CodeGen::Program& program) {
149 std::string res;
150 for (size_t i = 0; i < program.size(); i++) {
151 AppendInstruction(&res, i + 1, program[i]);
153 return res;
156 } // namespace bpf_dsl
157 } // namespace sandbox