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"
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"
24 const char* AluOpToken(uint32_t code
) {
25 switch (BPF_OP(code
)) {
51 const char* JmpOpToken(uint32_t code
) {
52 switch (BPF_OP(code
)) {
64 const char* DataOffsetName(size_t off
) {
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)";
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
)) {
83 if (insn
.code
== BPF_LD
+ BPF_W
+ BPF_ABS
) {
84 base::StringAppendF(dst
, "LOAD %" PRIu32
" // ", insn
.k
);
86 (insn
.k
- offsetof(struct arch_seccomp_data
, args
)) /
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
);
94 base::StringAppendF(dst
, "%s\n", DataOffsetName(insn
.k
));
97 base::StringAppendF(dst
, "Load ???\n");
101 if (BPF_OP(insn
.code
) == BPF_JA
) {
102 base::StringAppendF(dst
, "JMP %zu\n", pc
+ insn
.k
+ 1);
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);
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");
125 base::StringAppendF(dst
, "???\n");
129 if (BPF_OP(insn
.code
) == BPF_NEG
) {
130 base::StringAppendF(dst
, "A := -A\n");
132 base::StringAppendF(dst
, "A := A %s 0x%" PRIx32
"\n",
133 AluOpToken(insn
.code
), insn
.k
);
137 base::StringAppendF(dst
, "???\n");
144 void DumpBPF::PrintProgram(const CodeGen::Program
& program
) {
145 fputs(StringPrintProgram(program
).c_str(), stderr
);
148 std::string
DumpBPF::StringPrintProgram(const CodeGen::Program
& program
) {
150 for (size_t i
= 0; i
< program
.size(); i
++) {
151 AppendInstruction(&res
, i
+ 1, program
[i
]);
156 } // namespace bpf_dsl
157 } // namespace sandbox