1*ec63e07aSXin Li #include "sandboxed_api/sandbox2/bpfdisassembler.h"
2*ec63e07aSXin Li
3*ec63e07aSXin Li #include <linux/bpf_common.h>
4*ec63e07aSXin Li #include <linux/filter.h>
5*ec63e07aSXin Li #include <linux/seccomp.h>
6*ec63e07aSXin Li
7*ec63e07aSXin Li #include "gmock/gmock.h"
8*ec63e07aSXin Li #include "gtest/gtest.h"
9*ec63e07aSXin Li #include "sandboxed_api/sandbox2/util/bpf_helper.h"
10*ec63e07aSXin Li
11*ec63e07aSXin Li namespace sandbox2 {
12*ec63e07aSXin Li namespace bpf {
13*ec63e07aSXin Li namespace {
14*ec63e07aSXin Li
15*ec63e07aSXin Li using ::testing::Eq;
16*ec63e07aSXin Li using ::testing::StartsWith;
17*ec63e07aSXin Li
18*ec63e07aSXin Li #ifndef SECCOMP_RET_USER_NOTIF
19*ec63e07aSXin Li #define SECCOMP_RET_USER_NOTIF 0x7fc00000U /* notifies userspace */
20*ec63e07aSXin Li #endif
21*ec63e07aSXin Li
22*ec63e07aSXin Li #ifndef SECCOMP_RET_KILL_PROCESS
23*ec63e07aSXin Li #define SECCOMP_RET_KILL_PROCESS 0x80000000U /* kill the process */
24*ec63e07aSXin Li #endif
25*ec63e07aSXin Li
26*ec63e07aSXin Li #ifndef SECCOMP_RET_LOG
27*ec63e07aSXin Li #define SECCOMP_RET_LOG 0x7ffc0000U /* allow after logging */
28*ec63e07aSXin Li #endif
29*ec63e07aSXin Li
TEST(DecodeInstructionTest,Loads)30*ec63e07aSXin Li TEST(DecodeInstructionTest, Loads) {
31*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(LOAD_ARCH, 1), Eq("A := architecture"));
32*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(LOAD_SYSCALL_NR, 1), Eq("A := syscall number"));
33*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(ARG_32(0), 1), Eq("A := arg 0 low"));
34*ec63e07aSXin Li EXPECT_THAT(
35*ec63e07aSXin Li DecodeInstruction(BPF_STMT(BPF_LD | BPF_W | BPF_ABS, HI_ARG(0)), 1),
36*ec63e07aSXin Li Eq("A := arg 0 high"));
37*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(BPF_STMT(BPF_LD | BPF_W | BPF_LEN, 0), 1),
38*ec63e07aSXin Li Eq("A := sizeof(seccomp_data)"));
39*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(BPF_STMT(BPF_LDX | BPF_W | BPF_LEN, 0), 1),
40*ec63e07aSXin Li Eq("X := sizeof(seccomp_data)"));
41*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(BPF_STMT(BPF_LD | BPF_IMM, 0x1234), 1),
42*ec63e07aSXin Li Eq("A := 0x1234"));
43*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(BPF_STMT(BPF_LDX | BPF_IMM, 0x1234), 1),
44*ec63e07aSXin Li Eq("X := 0x1234"));
45*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(BPF_STMT(BPF_MISC | BPF_TAX, 0), 1),
46*ec63e07aSXin Li Eq("X := A"));
47*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(BPF_STMT(BPF_MISC | BPF_TXA, 0), 1),
48*ec63e07aSXin Li Eq("A := X"));
49*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(BPF_STMT(BPF_LD | BPF_W | BPF_ABS, 0x1), 1),
50*ec63e07aSXin Li Eq("A := data[0x1] (misaligned load)"));
51*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(BPF_STMT(BPF_LD | BPF_W | BPF_ABS, 0x1234), 1),
52*ec63e07aSXin Li Eq("A := data[0x1234] (invalid load)"));
53*ec63e07aSXin Li }
54*ec63e07aSXin Li
TEST(DecodeInstructionTest,Memory)55*ec63e07aSXin Li TEST(DecodeInstructionTest, Memory) {
56*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(BPF_STMT(BPF_ST, 1), 1), Eq("M[1] := A"));
57*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(BPF_STMT(BPF_STX, 1), 1), Eq("M[1] := X"));
58*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(BPF_STMT(BPF_LD | BPF_MEM, 1), 1),
59*ec63e07aSXin Li Eq("A := M[1]"));
60*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(BPF_STMT(BPF_LDX | BPF_MEM, 1), 1),
61*ec63e07aSXin Li Eq("X := M[1]"));
62*ec63e07aSXin Li }
63*ec63e07aSXin Li
TEST(DecodeInstructionTest,Returns)64*ec63e07aSXin Li TEST(DecodeInstructionTest, Returns) {
65*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(KILL, 1), Eq("KILL"));
66*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(ALLOW, 1), Eq("ALLOW"));
67*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(TRAP(0x12), 1), Eq("TRAP 0x12"));
68*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(ERRNO(0x23), 1), Eq("ERRNO 0x23"));
69*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(TRACE(0x34), 1), Eq("TRACE 0x34"));
70*ec63e07aSXin Li EXPECT_THAT(
71*ec63e07aSXin Li DecodeInstruction(BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_USER_NOTIF), 1),
72*ec63e07aSXin Li Eq("USER_NOTIF"));
73*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_LOG), 1),
74*ec63e07aSXin Li Eq("LOG"));
75*ec63e07aSXin Li EXPECT_THAT(
76*ec63e07aSXin Li DecodeInstruction(BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_KILL_PROCESS), 1),
77*ec63e07aSXin Li Eq("KILL_PROCESS"));
78*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(BPF_STMT(BPF_RET + BPF_A, 0), 1),
79*ec63e07aSXin Li Eq("return A"));
80*ec63e07aSXin Li }
81*ec63e07aSXin Li
TEST(DecodeInstructionTest,Alu)82*ec63e07aSXin Li TEST(DecodeInstructionTest, Alu) {
83*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(BPF_STMT(BPF_ALU | BPF_NEG, 0), 1),
84*ec63e07aSXin Li Eq("A := -A"));
85*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(BPF_STMT(BPF_ALU | BPF_ADD | BPF_K, 5), 1),
86*ec63e07aSXin Li Eq("A := A + 0x5"));
87*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(BPF_STMT(BPF_ALU | BPF_SUB | BPF_K, 5), 1),
88*ec63e07aSXin Li Eq("A := A - 0x5"));
89*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(BPF_STMT(BPF_ALU | BPF_DIV | BPF_X, 0), 1),
90*ec63e07aSXin Li Eq("A := A / X"));
91*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(BPF_STMT(BPF_ALU | BPF_MUL | BPF_X, 0), 1),
92*ec63e07aSXin Li Eq("A := A * X"));
93*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 6), 1),
94*ec63e07aSXin Li Eq("A := A & 0x6"));
95*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(BPF_STMT(BPF_ALU | BPF_OR | BPF_K, 7), 1),
96*ec63e07aSXin Li Eq("A := A | 0x7"));
97*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(BPF_STMT(BPF_ALU | BPF_XOR | BPF_K, 8), 1),
98*ec63e07aSXin Li Eq("A := A ^ 0x8"));
99*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(BPF_STMT(BPF_ALU | BPF_RSH | BPF_K, 9), 1),
100*ec63e07aSXin Li Eq("A := A >> 0x9"));
101*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(BPF_STMT(BPF_ALU | BPF_LSH | BPF_K, 1), 1),
102*ec63e07aSXin Li Eq("A := A << 0x1"));
103*ec63e07aSXin Li }
104*ec63e07aSXin Li
TEST(DecodeInstructionTest,Jump)105*ec63e07aSXin Li TEST(DecodeInstructionTest, Jump) {
106*ec63e07aSXin Li EXPECT_THAT(
107*ec63e07aSXin Li DecodeInstruction(BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x1234, 1, 0), 1),
108*ec63e07aSXin Li Eq("if A == 0x1234 goto 3"));
109*ec63e07aSXin Li EXPECT_THAT(
110*ec63e07aSXin Li DecodeInstruction(BPF_JUMP(BPF_JMP | BPF_JGT | BPF_K, 0x1234, 0, 1), 1),
111*ec63e07aSXin Li Eq("if A <= 0x1234 goto 3"));
112*ec63e07aSXin Li EXPECT_THAT(
113*ec63e07aSXin Li DecodeInstruction(BPF_JUMP(BPF_JMP | BPF_JGT | BPF_K, 0x1234, 1, 2), 1),
114*ec63e07aSXin Li Eq("if A > 0x1234 then 3 else 4"));
115*ec63e07aSXin Li EXPECT_THAT(
116*ec63e07aSXin Li DecodeInstruction(BPF_JUMP(BPF_JMP | BPF_JSET | BPF_X, 1, 1, 0), 1),
117*ec63e07aSXin Li Eq("if A & X goto 3"));
118*ec63e07aSXin Li EXPECT_THAT(
119*ec63e07aSXin Li DecodeInstruction(BPF_JUMP(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 1), 1),
120*ec63e07aSXin Li Eq("if A < X goto 3"));
121*ec63e07aSXin Li EXPECT_THAT(
122*ec63e07aSXin Li DecodeInstruction(BPF_JUMP(BPF_JMP | BPF_JGE | BPF_X, 0, 1, 2), 1),
123*ec63e07aSXin Li Eq("if A >= X then 3 else 4"));
124*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(BPF_STMT(BPF_JMP | BPF_K, 3), 1),
125*ec63e07aSXin Li Eq("jump to 5"));
126*ec63e07aSXin Li }
127*ec63e07aSXin Li
TEST(DecodeInstructionTest,Invalid)128*ec63e07aSXin Li TEST(DecodeInstructionTest, Invalid) {
129*ec63e07aSXin Li EXPECT_THAT(DecodeInstruction(BPF_STMT(BPF_LDX | BPF_W | BPF_ABS, 0), 1),
130*ec63e07aSXin Li StartsWith("Invalid instruction"));
131*ec63e07aSXin Li }
132*ec63e07aSXin Li
TEST(DisasmTest,Simple)133*ec63e07aSXin Li TEST(DisasmTest, Simple) {
134*ec63e07aSXin Li EXPECT_THAT(Disasm({ALLOW}), Eq("000: ALLOW\n"));
135*ec63e07aSXin Li EXPECT_THAT(Disasm({KILL}), Eq("000: KILL\n"));
136*ec63e07aSXin Li }
137*ec63e07aSXin Li
TEST(DisasmTest,Complex)138*ec63e07aSXin Li TEST(DisasmTest, Complex) {
139*ec63e07aSXin Li EXPECT_THAT(Disasm({LOAD_ARCH, JNE32(0x1, KILL), LOAD_SYSCALL_NR,
140*ec63e07aSXin Li JEQ32(0x1234, ERRNO(0x33)), TRACE(0x22)}),
141*ec63e07aSXin Li Eq(R"(000: A := architecture
142*ec63e07aSXin Li 001: if A == 0x1 goto 3
143*ec63e07aSXin Li 002: KILL
144*ec63e07aSXin Li 003: A := syscall number
145*ec63e07aSXin Li 004: if A != 0x1234 goto 6
146*ec63e07aSXin Li 005: ERRNO 0x33
147*ec63e07aSXin Li 006: TRACE 0x22
148*ec63e07aSXin Li )"));
149*ec63e07aSXin Li }
150*ec63e07aSXin Li
151*ec63e07aSXin Li } // namespace
152*ec63e07aSXin Li } // namespace bpf
153*ec63e07aSXin Li } // namespace sandbox2
154