blob: 6bc044d95fba1bdebe9fbf809894cc029e8382c7 [file] [log] [blame]
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001// syscall_filter_unittest.cpp
2// Copyright (C) 2016 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16// Test syscall filtering using gtest.
17
18#include <asm/unistd.h>
19#include <errno.h>
20#include <fcntl.h> /* For O_WRONLY. */
21
22#include <gtest/gtest.h>
Jorge Lucangeli Obes07459372016-10-19 15:33:31 -040023#include <string>
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -040024
25#include "bpf.h"
26#include "syscall_filter.h"
27#include "syscall_filter_unittest_macros.h"
28#include "util.h"
29
Jorge Lucangeli Obes07459372016-10-19 15:33:31 -040030TEST(util, parse_constant_unsigned) {
31 char *end;
32 long int c = 0;
33 std::string constant;
34
35#if defined(BITS32)
36 constant = "0x80000000";
37 c = parse_constant(const_cast<char*>(constant.c_str()), &end);
38 EXPECT_EQ(0x80000000U, static_cast<unsigned long int>(c));
39
40#elif defined(BITS64)
41 constant = "0x8000000000000000";
42 c = parse_constant(const_cast<char*>(constant.c_str()), &end);
43 EXPECT_EQ(0x8000000000000000UL, static_cast<unsigned long int>(c));
44#endif
45}
46
47TEST(util, parse_constant_unsigned_toobig) {
48 char *end;
49 long int c = 0;
50 std::string constant;
51
52#if defined(BITS32)
53 constant = "0x100000000"; // Too big for 32-bit unsigned long int.
54 c = parse_constant(const_cast<char*>(constant.c_str()), &end);
55 // Error case should return 0.
56 EXPECT_EQ(0, c);
57
58#elif defined(BITS64)
59 constant = "0x10000000000000000";
60 c = parse_constant(const_cast<char*>(constant.c_str()), &end);
61 // Error case should return 0.
62 EXPECT_EQ(0, c);
63#endif
64}
65
66TEST(util, parse_constant_signed) {
67 char *end;
68 long int c = 0;
69 std::string constant = "-1";
70 c = parse_constant(const_cast<char*>(constant.c_str()), &end);
71 EXPECT_EQ(-1, c);
72}
73
74TEST(util, parse_constant_signed_toonegative) {
75 char *end;
76 long int c = 0;
77 std::string constant;
78
79#if defined(BITS32)
80 constant = "-0x80000001";
81 c = parse_constant(const_cast<char*>(constant.c_str()), &end);
82 // Error case should return 0.
83 EXPECT_EQ(0, c);
84
85#elif defined(BITS64)
86 constant = "-0x8000000000000001";
87 c = parse_constant(const_cast<char*>(constant.c_str()), &end);
88 // Error case should return 0.
89 EXPECT_EQ(0, c);
90#endif
91}
92
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -040093/* Test that setting one BPF instruction works. */
94TEST(bpf, set_bpf_instr) {
95 struct sock_filter instr;
96 unsigned char code = BPF_LD + BPF_W + BPF_ABS;
97 unsigned int k = 4;
98 unsigned char jt = 1, jf = 2;
99
100 size_t len = set_bpf_instr(&instr, code, k, jt, jf);
101
102 EXPECT_EQ(len, 1U);
103 EXPECT_EQ_BLOCK(&instr, code, k, jt, jf);
104}
105
106TEST(bpf, bpf_load_arg) {
107 struct sock_filter load_arg[BPF_LOAD_ARG_LEN];
Jorge Lucangeli Obes9bd316b2017-01-26 17:21:16 -0500108 const int argidx = 1;
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400109 size_t len = bpf_load_arg(load_arg, argidx);
110
111 EXPECT_EQ(len, BPF_LOAD_ARG_LEN);
112
113#if defined(BITS32)
114 EXPECT_EQ_STMT(&load_arg[0], BPF_LD + BPF_W + BPF_ABS, LO_ARG(argidx));
115#elif defined(BITS64)
116 EXPECT_EQ_STMT(&load_arg[0], BPF_LD + BPF_W + BPF_ABS, LO_ARG(argidx));
117 EXPECT_EQ_STMT(&load_arg[1], BPF_ST, 0);
118 EXPECT_EQ_STMT(&load_arg[2], BPF_LD + BPF_W + BPF_ABS, HI_ARG(argidx));
119 EXPECT_EQ_STMT(&load_arg[3], BPF_ST, 1);
120#endif
121}
122
123TEST(bpf, bpf_comp_jeq) {
124 struct sock_filter comp_jeq[BPF_COMP_LEN];
125 unsigned long c = 1;
126 unsigned char jt = 1;
127 unsigned char jf = 2;
128
129 size_t len = bpf_comp_jeq(comp_jeq, c, jt, jf);
130
131 EXPECT_EQ(len, BPF_COMP_LEN);
132
133#if defined(BITS32)
134 EXPECT_EQ_BLOCK(&comp_jeq[0], BPF_JMP + BPF_JEQ + BPF_K, c, jt, jf);
135#elif defined(BITS64)
136 EXPECT_EQ_BLOCK(&comp_jeq[0], BPF_JMP + BPF_JEQ + BPF_K, 0, 0, jf + 2);
137 EXPECT_EQ_STMT(&comp_jeq[1], BPF_LD + BPF_MEM, 0);
138 EXPECT_EQ_BLOCK(&comp_jeq[2], BPF_JMP + BPF_JEQ + BPF_K, c, jt, jf);
139#endif
140}
141
142TEST(bpf, bpf_comp_jset) {
143 struct sock_filter comp_jset[BPF_COMP_LEN];
Jorge Lucangeli Obesfd6f8e32016-10-12 11:19:28 -0400144 unsigned long mask = (1UL << (sizeof(unsigned long) * 8 - 1)) | O_WRONLY;
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400145 unsigned char jt = 1;
146 unsigned char jf = 2;
147
148 size_t len = bpf_comp_jset(comp_jset, mask, jt, jf);
149
150 EXPECT_EQ(len, BPF_COMP_LEN);
151
152#if defined(BITS32)
153 EXPECT_EQ_BLOCK(&comp_jset[0], BPF_JMP + BPF_JSET + BPF_K, mask, jt, jf);
154#elif defined(BITS64)
Jorge Lucangeli Obesfd6f8e32016-10-12 11:19:28 -0400155 EXPECT_EQ_BLOCK(
156 &comp_jset[0], BPF_JMP + BPF_JSET + BPF_K, 0x80000000, jt + 2, 0);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400157 EXPECT_EQ_STMT(&comp_jset[1], BPF_LD + BPF_MEM, 0);
Jorge Lucangeli Obesfd6f8e32016-10-12 11:19:28 -0400158 EXPECT_EQ_BLOCK(&comp_jset[2], BPF_JMP + BPF_JSET + BPF_K, O_WRONLY, jt, jf);
159#endif
160}
161
162TEST(bpf, bpf_comp_jin) {
163 struct sock_filter comp_jin[BPF_COMP_LEN];
164 unsigned long mask = (1UL << (sizeof(unsigned long) * 8 - 1)) | O_WRONLY;
165 unsigned char jt = 10;
166 unsigned char jf = 20;
167
168 size_t len = bpf_comp_jin(comp_jin, mask, jt, jf);
169
170 EXPECT_EQ(len, BPF_COMP_LEN);
171
172#if defined(BITS32)
173 EXPECT_EQ_BLOCK(&comp_jin[0], BPF_JMP + BPF_JSET + BPF_K, ~mask, jf, jt);
174#elif defined(BITS64)
175 EXPECT_EQ_BLOCK(
176 &comp_jin[0], BPF_JMP + BPF_JSET + BPF_K, 0x7FFFFFFF, jf + 2, 0);
177 EXPECT_EQ_STMT(&comp_jin[1], BPF_LD + BPF_MEM, 0);
178 EXPECT_EQ_BLOCK(&comp_jin[2], BPF_JMP + BPF_JSET + BPF_K, ~O_WRONLY, jf, jt);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400179#endif
180}
181
182TEST(bpf, bpf_arg_comp) {
183 struct sock_filter *arg_comp;
184 int op = EQ;
Jorge Lucangeli Obes9bd316b2017-01-26 17:21:16 -0500185 const int argidx = 1;
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400186 unsigned long c = 3;
187 unsigned int label_id = 0;
188
189 size_t len = bpf_arg_comp(&arg_comp, op, argidx, c, label_id);
190
191 EXPECT_EQ(len, BPF_ARG_COMP_LEN + 1);
192
193#if defined(BITS32)
194 EXPECT_EQ_STMT(&arg_comp[0], BPF_LD + BPF_W + BPF_ABS, LO_ARG(argidx));
195 EXPECT_EQ_BLOCK(&arg_comp[1], BPF_JMP + BPF_JEQ + BPF_K, c, 1, 0);
196 EXPECT_JUMP_LBL(&arg_comp[2]);
197#elif defined(BITS64)
198 EXPECT_EQ_STMT(&arg_comp[0], BPF_LD + BPF_W + BPF_ABS, LO_ARG(argidx));
199 EXPECT_EQ_STMT(&arg_comp[1], BPF_ST, 0);
200 EXPECT_EQ_STMT(&arg_comp[2], BPF_LD + BPF_W + BPF_ABS, HI_ARG(argidx));
201 EXPECT_EQ_STMT(&arg_comp[3], BPF_ST, 1);
202
203 EXPECT_EQ_BLOCK(&arg_comp[4], BPF_JMP + BPF_JEQ + BPF_K, 0, 0, 2);
204 EXPECT_EQ_STMT(&arg_comp[5], BPF_LD + BPF_MEM, 0);
205 EXPECT_EQ_BLOCK(&arg_comp[6], BPF_JMP + BPF_JEQ + BPF_K, c, 1, 0);
206 EXPECT_JUMP_LBL(&arg_comp[7]);
207#endif
208 free(arg_comp);
209}
210
211TEST(bpf, bpf_validate_arch) {
212 struct sock_filter validate_arch[ARCH_VALIDATION_LEN];
213
214 size_t len = bpf_validate_arch(validate_arch);
215
216 EXPECT_EQ(len, ARCH_VALIDATION_LEN);
217 EXPECT_ARCH_VALIDATION(validate_arch);
218}
219
220TEST(bpf, bpf_allow_syscall) {
221 struct sock_filter allow_syscall[ALLOW_SYSCALL_LEN];
222 int nr = 1;
223
224 size_t len = bpf_allow_syscall(allow_syscall, nr);
225
226 EXPECT_EQ(len, ALLOW_SYSCALL_LEN);
227 EXPECT_ALLOW_SYSCALL(allow_syscall, nr);
228}
229
230TEST(bpf, bpf_allow_syscall_args) {
231 struct sock_filter allow_syscall[ALLOW_SYSCALL_LEN];
232 int nr = 1;
233 unsigned int id = 1024;
234
235 size_t len = bpf_allow_syscall_args(allow_syscall, nr, id);
236
237 EXPECT_EQ(len, ALLOW_SYSCALL_LEN);
238 EXPECT_ALLOW_SYSCALL_ARGS(allow_syscall, nr, id, JUMP_JT, JUMP_JF);
239}
240
Jorge Lucangeli Obes8cc9d4a2016-10-03 10:00:57 -0400241class BpfLabelTest : public ::testing::Test {
242 protected:
Jorge Lucangeli Obes9bd316b2017-01-26 17:21:16 -0500243 virtual void SetUp() { labels_.count = 0; }
Jorge Lucangeli Obes8cc9d4a2016-10-03 10:00:57 -0400244 virtual void TearDown() { free_label_strings(&labels_); }
245 struct bpf_labels labels_;
246};
247
248TEST_F(BpfLabelTest, zero_length_filter) {
249 int res = bpf_resolve_jumps(&labels_, NULL, 0);
250
251 EXPECT_EQ(res, 0);
252 EXPECT_EQ(labels_.count, 0U);
253}
254
255TEST_F(BpfLabelTest, single_label) {
256 struct sock_filter test_label[1];
257
258 int id = bpf_label_id(&labels_, "test");
259 set_bpf_lbl(test_label, id);
260 int res = bpf_resolve_jumps(&labels_, test_label, 1);
261
262 EXPECT_EQ(res, 0);
263 EXPECT_EQ(labels_.count, 1U);
264}
265
266TEST_F(BpfLabelTest, repeated_label) {
267 struct sock_filter test_label[2];
268
269 int id = bpf_label_id(&labels_, "test");
270 set_bpf_lbl(&test_label[0], id);
271 set_bpf_lbl(&test_label[1], id);
272 int res = bpf_resolve_jumps(&labels_, test_label, 2);
273
274 EXPECT_EQ(res, -1);
275}
276
277TEST_F(BpfLabelTest, jump_with_no_label) {
278 struct sock_filter test_jump[1];
279
280 set_bpf_jump_lbl(test_jump, 14831);
281 int res = bpf_resolve_jumps(&labels_, test_jump, 1);
282
283 EXPECT_EQ(res, -1);
284}
285
286TEST_F(BpfLabelTest, jump_to_valid_label) {
287 struct sock_filter test_jump[2];
288
289 int id = bpf_label_id(&labels_, "test");
290 set_bpf_jump_lbl(&test_jump[0], id);
291 set_bpf_lbl(&test_jump[1], id);
292
293 int res = bpf_resolve_jumps(&labels_, test_jump, 2);
294 EXPECT_EQ(res, 0);
295 EXPECT_EQ(labels_.count, 1U);
296}
297
298TEST_F(BpfLabelTest, jump_to_invalid_label) {
299 struct sock_filter test_jump[2];
300
301 int id = bpf_label_id(&labels_, "test");
302 set_bpf_jump_lbl(&test_jump[0], id + 1);
303 set_bpf_lbl(&test_jump[1], id);
304
305 int res = bpf_resolve_jumps(&labels_, test_jump, 2);
306 EXPECT_EQ(res, -1);
307}
308
309TEST_F(BpfLabelTest, jump_to_unresolved_label) {
310 struct sock_filter test_jump[2];
311
312 int id = bpf_label_id(&labels_, "test");
313 /* Notice the order of the instructions is reversed. */
314 set_bpf_lbl(&test_jump[0], id);
315 set_bpf_jump_lbl(&test_jump[1], id);
316
317 int res = bpf_resolve_jumps(&labels_, test_jump, 2);
318 EXPECT_EQ(res, -1);
319}
320
321TEST_F(BpfLabelTest, too_many_labels) {
322 unsigned int i;
323 char label[20];
324
325 for (i = 0; i < BPF_LABELS_MAX; i++) {
326 snprintf(label, 20, "test%u", i);
327 (void) bpf_label_id(&labels_, label);
328 }
329 int id = bpf_label_id(&labels_, "test");
330
331 /* Insertion failed... */
332 EXPECT_EQ(id, -1);
333 /* ... because the label lookup table is full. */
334 EXPECT_EQ(labels_.count, BPF_LABELS_MAX);
335}
336
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400337class ArgFilterTest : public ::testing::Test {
338 protected:
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700339 virtual void SetUp() {
340 labels_.count = 0;
341 state_.filename = "policy";
342 state_.line_number = 1;
343 }
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400344 virtual void TearDown() { free_label_strings(&labels_); }
345 struct bpf_labels labels_;
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700346 int nr_ = 1;
347 unsigned int id_ = 0;
348 struct parser_state state_;
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400349};
350
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400351TEST_F(ArgFilterTest, empty_atom) {
352 const char* fragment = "";
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400353
354 struct filter_block* block =
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700355 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400356 ASSERT_EQ(block, nullptr);
357}
358
359TEST_F(ArgFilterTest, whitespace_atom) {
360 const char* fragment = "\t ";
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400361
362 struct filter_block* block =
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700363 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400364 ASSERT_EQ(block, nullptr);
365}
366
367TEST_F(ArgFilterTest, no_comparison) {
368 const char* fragment = "arg0";
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400369
370 struct filter_block* block =
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700371 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400372 ASSERT_EQ(block, nullptr);
373}
374
375TEST_F(ArgFilterTest, no_constant) {
376 const char* fragment = "arg0 ==";
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400377
378 struct filter_block* block =
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700379 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400380 ASSERT_EQ(block, nullptr);
381}
382
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400383TEST_F(ArgFilterTest, arg0_equals) {
384 const char *fragment = "arg0 == 0";
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700385
386 struct filter_block* block =
387 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400388
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400389 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400390 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
391 EXPECT_EQ(block->total_len, exp_total_len);
392
393 /* First block is a label. */
394 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400395 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400396 EXPECT_EQ(curr_block->len, 1U);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400397 EXPECT_LBL(curr_block->instrs);
398
399 /* Second block is a comparison. */
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400400 curr_block = curr_block->next;
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400401 EXPECT_COMP(curr_block);
402
403 /* Third block is a jump and a label (end of AND group). */
404 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400405 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400406 EXPECT_GROUP_END(curr_block);
407
408 /* Fourth block is SECCOMP_RET_KILL. */
409 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400410 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400411 EXPECT_KILL(curr_block);
412
413 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
414 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400415 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400416 EXPECT_ALLOW(curr_block);
417
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400418 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400419
420 free_block_list(block);
421}
422
423TEST_F(ArgFilterTest, arg0_mask) {
424 const char *fragment = "arg1 & O_RDWR";
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700425
426 struct filter_block* block =
427 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400428
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400429 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400430 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
431 EXPECT_EQ(block->total_len, exp_total_len);
432
433 /* First block is a label. */
434 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400435 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400436 EXPECT_EQ(curr_block->len, 1U);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400437 EXPECT_LBL(curr_block->instrs);
438
439 /* Second block is a comparison. */
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400440 curr_block = curr_block->next;
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400441 EXPECT_COMP(curr_block);
442
443 /* Third block is a jump and a label (end of AND group). */
444 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400445 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400446 EXPECT_GROUP_END(curr_block);
447
448 /* Fourth block is SECCOMP_RET_KILL. */
449 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400450 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400451 EXPECT_KILL(curr_block);
452
453 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
454 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400455 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400456 EXPECT_ALLOW(curr_block);
457
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400458 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400459
460 free_block_list(block);
461}
462
Jorge Lucangeli Obesfd6f8e32016-10-12 11:19:28 -0400463TEST_F(ArgFilterTest, arg0_flag_set_inclusion) {
464 const char *fragment = "arg0 in O_RDONLY|O_CREAT";
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700465
466 struct filter_block* block =
467 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obesfd6f8e32016-10-12 11:19:28 -0400468
469 ASSERT_NE(block, nullptr);
470 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
471 EXPECT_EQ(block->total_len, exp_total_len);
472
473 /* First block is a label. */
474 struct filter_block *curr_block = block;
475 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400476 EXPECT_EQ(curr_block->len, 1U);
Jorge Lucangeli Obesfd6f8e32016-10-12 11:19:28 -0400477 EXPECT_LBL(curr_block->instrs);
478
479 /* Second block is a comparison. */
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400480 curr_block = curr_block->next;
Jorge Lucangeli Obesfd6f8e32016-10-12 11:19:28 -0400481 ASSERT_NE(curr_block, nullptr);
482 EXPECT_COMP(curr_block);
483
484 /* Third block is a jump and a label (end of AND group). */
485 curr_block = curr_block->next;
486 ASSERT_NE(curr_block, nullptr);
487 EXPECT_GROUP_END(curr_block);
488
489 /* Fourth block is SECCOMP_RET_KILL. */
490 curr_block = curr_block->next;
491 ASSERT_NE(curr_block, nullptr);
492 EXPECT_KILL(curr_block);
493
494 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
495 curr_block = curr_block->next;
496 ASSERT_NE(curr_block, nullptr);
497 EXPECT_ALLOW(curr_block);
498
499 EXPECT_EQ(curr_block->next, nullptr);
500
501 free_block_list(block);
502}
503
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400504TEST_F(ArgFilterTest, arg0_eq_mask) {
505 const char *fragment = "arg1 == O_WRONLY|O_CREAT";
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400506
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700507 struct filter_block* block =
508 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400509
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400510 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400511 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
512 EXPECT_EQ(block->total_len, exp_total_len);
513
514 /* First block is a label. */
515 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400516 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400517 EXPECT_EQ(curr_block->len, 1U);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400518 EXPECT_LBL(curr_block->instrs);
519
520 /* Second block is a comparison. */
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400521 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400522 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400523 EXPECT_COMP(curr_block);
524 EXPECT_EQ(curr_block->instrs[BPF_ARG_COMP_LEN - 1].k,
525 (unsigned int)(O_WRONLY | O_CREAT));
526
527 /* Third block is a jump and a label (end of AND group). */
528 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400529 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400530 EXPECT_GROUP_END(curr_block);
531
532 /* Fourth block is SECCOMP_RET_KILL. */
533 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400534 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400535 EXPECT_KILL(curr_block);
536
537 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
538 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400539 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400540 EXPECT_ALLOW(curr_block);
541
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400542 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400543
544 free_block_list(block);
545}
546
547TEST_F(ArgFilterTest, and_or) {
548 const char *fragment = "arg0 == 0 && arg1 == 0 || arg0 == 1";
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400549
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700550 struct filter_block* block =
551 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400552 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400553 size_t exp_total_len = 1 + 3 * (BPF_ARG_COMP_LEN + 1) + 2 + 2 + 1 + 2;
554 EXPECT_EQ(block->total_len, exp_total_len);
555
556 /* First block is a label. */
557 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400558 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400559 EXPECT_EQ(curr_block->len, 1U);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400560 EXPECT_LBL(curr_block->instrs);
561
562 /* Second block is a comparison ("arg0 == 0"). */
563 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400564 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400565 EXPECT_COMP(curr_block);
566
567 /* Third block is a comparison ("arg1 == 0"). */
568 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400569 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400570 EXPECT_COMP(curr_block);
571
572 /* Fourth block is a jump and a label (end of AND group). */
573 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400574 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400575 EXPECT_GROUP_END(curr_block);
576
577 /* Fifth block is a comparison ("arg0 == 1"). */
578 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400579 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400580 EXPECT_COMP(curr_block);
581
582 /* Sixth block is a jump and a label (end of AND group). */
583 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400584 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400585 EXPECT_GROUP_END(curr_block);
586
587 /* Seventh block is SECCOMP_RET_KILL. */
588 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400589 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400590 EXPECT_KILL(curr_block);
591
592 /* Eigth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
593 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400594 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400595 EXPECT_ALLOW(curr_block);
596
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400597 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400598
599 free_block_list(block);
600}
601
602TEST_F(ArgFilterTest, ret_errno) {
603 const char *fragment = "arg0 == 0 || arg0 == 1; return 1";
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400604
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700605 struct filter_block* block =
606 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400607 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400608 size_t exp_total_len = 1 + 2 * (BPF_ARG_COMP_LEN + 1) + 2 + 2 + 1 + 2;
609 EXPECT_EQ(block->total_len, exp_total_len);
610
611 /* First block is a label. */
612 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400613 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400614 EXPECT_EQ(curr_block->len, 1U);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400615 EXPECT_LBL(curr_block->instrs);
616
617 /* Second block is a comparison ("arg0 == 0"). */
618 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400619 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400620 EXPECT_COMP(curr_block);
621
622 /* Third block is a jump and a label (end of AND group). */
623 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400624 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400625 EXPECT_GROUP_END(curr_block);
626
627 /* Fourth block is a comparison ("arg0 == 1"). */
628 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400629 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400630 EXPECT_COMP(curr_block);
631
632 /* Fifth block is a jump and a label (end of AND group). */
633 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400634 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400635 EXPECT_GROUP_END(curr_block);
636
637 /* Sixth block is SECCOMP_RET_ERRNO. */
638 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400639 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400640 EXPECT_EQ(curr_block->len, 1U);
641 EXPECT_EQ_STMT(curr_block->instrs,
642 BPF_RET + BPF_K,
643 SECCOMP_RET_ERRNO | (1 & SECCOMP_RET_DATA));
644
645 /* Seventh block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
646 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400647 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400648 EXPECT_ALLOW(curr_block);
649
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400650 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400651
652 free_block_list(block);
653}
654
655TEST_F(ArgFilterTest, unconditional_errno) {
656 const char *fragment = "return 1";
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400657
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700658 struct filter_block* block =
659 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400660 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400661 size_t exp_total_len = 2;
662 EXPECT_EQ(block->total_len, exp_total_len);
663
664 /* First block is a label. */
665 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400666 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400667 EXPECT_EQ(curr_block->len, 1U);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400668 EXPECT_LBL(curr_block->instrs);
669
670 /* Second block is SECCOMP_RET_ERRNO. */
671 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400672 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400673 EXPECT_EQ(curr_block->len, 1U);
674 EXPECT_EQ_STMT(curr_block->instrs,
675 BPF_RET + BPF_K,
676 SECCOMP_RET_ERRNO | (1 & SECCOMP_RET_DATA));
677
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400678 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400679
680 free_block_list(block);
681}
682
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400683TEST_F(ArgFilterTest, invalid_arg_token) {
684 const char *fragment = "org0 == 0";
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400685
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700686 struct filter_block* block =
687 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400688 ASSERT_EQ(block, nullptr);
689}
690
Jorge Lucangeli Obes53895402016-10-18 12:02:58 -0400691TEST_F(ArgFilterTest, invalid_arg_number) {
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400692 const char *fragment = "argnn == 0";
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400693
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700694 struct filter_block* block =
695 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obes53895402016-10-18 12:02:58 -0400696 ASSERT_EQ(block, nullptr);
697}
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400698
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400699TEST_F(ArgFilterTest, extra_chars_in_arg_token) {
700 const char* fragment = "arg0n == 0";
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400701
702 struct filter_block* block =
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700703 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400704 ASSERT_EQ(block, nullptr);
705}
706
707TEST_F(ArgFilterTest, invalid_operator) {
708 const char* fragment = "arg0 invalidop 0";
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400709
710 struct filter_block* block =
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700711 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400712 ASSERT_EQ(block, nullptr);
713}
714
Jorge Lucangeli Obes53895402016-10-18 12:02:58 -0400715TEST_F(ArgFilterTest, invalid_constant) {
716 const char *fragment = "arg0 == INVALIDCONSTANT";
Jorge Lucangeli Obes53895402016-10-18 12:02:58 -0400717
718 struct filter_block* block =
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700719 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obes53895402016-10-18 12:02:58 -0400720 ASSERT_EQ(block, nullptr);
721}
722
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400723TEST_F(ArgFilterTest, extra_tokens) {
724 const char* fragment = "arg0 == 0 EXTRATOKEN";
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400725
726 struct filter_block* block =
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700727 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400728 ASSERT_EQ(block, nullptr);
729}
730
Jorge Lucangeli Obes53895402016-10-18 12:02:58 -0400731TEST_F(ArgFilterTest, invalid_errno) {
732 const char *fragment = "arg0 == 0 && arg1 == 1; return errno";
Jorge Lucangeli Obes53895402016-10-18 12:02:58 -0400733
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700734 struct filter_block* block =
735 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obes53895402016-10-18 12:02:58 -0400736 ASSERT_EQ(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400737}
738
739TEST_F(ArgFilterTest, log_no_ret_error) {
740 const char *fragment = "arg0 == 0";
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700741
742 struct filter_block* block =
743 compile_policy_line(&state_, nr_, fragment, id_, &labels_, USE_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400744
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400745 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400746 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
747 EXPECT_EQ(block->total_len, exp_total_len);
748
749 /* First block is a label. */
750 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400751 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400752 EXPECT_EQ(curr_block->len, 1U);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400753 EXPECT_LBL(curr_block->instrs);
754
755 /* Second block is a comparison. */
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400756 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400757 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400758 EXPECT_COMP(curr_block);
759
760 /* Third block is a jump and a label (end of AND group). */
761 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400762 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400763 EXPECT_GROUP_END(curr_block);
764
765 /* Fourth block is SECCOMP_RET_TRAP, with no errno. */
766 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400767 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400768 EXPECT_TRAP(curr_block);
769
770 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
771 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400772 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400773 EXPECT_ALLOW(curr_block);
774
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400775 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400776
777 free_block_list(block);
778}
779
780TEST_F(ArgFilterTest, log_bad_ret_error) {
781 const char *fragment = "arg0 == 0; return";
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400782
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700783 struct filter_block* block =
784 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400785 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400786 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
787 EXPECT_EQ(block->total_len, exp_total_len);
788
789 /* First block is a label. */
790 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400791 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400792 EXPECT_EQ(curr_block->len, 1U);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400793 EXPECT_LBL(curr_block->instrs);
794
795 /* Second block is a comparison ("arg0 == 0"). */
796 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400797 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400798 EXPECT_COMP(curr_block);
799
800 /* Third block is a jump and a label (end of AND group). */
801 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400802 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400803 EXPECT_GROUP_END(curr_block);
804
805 /*
806 * Sixth block is NOT SECCOMP_RET_ERRNO, it should be SECCOMP_RET_KILL.
807 */
808 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400809 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400810 EXPECT_KILL(curr_block);
811
812 /* Seventh block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
813 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400814 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400815 EXPECT_ALLOW(curr_block);
816
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400817 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400818
819 free_block_list(block);
820}
821
822TEST_F(ArgFilterTest, no_log_bad_ret_error) {
823 const char *fragment = "arg0 == 0; return";
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400824
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700825 struct filter_block* block =
826 compile_policy_line(&state_, nr_, fragment, id_, &labels_, USE_LOGGING);
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400827 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400828 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
829 EXPECT_EQ(block->total_len, exp_total_len);
830
831 /* First block is a label. */
832 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400833 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400834 EXPECT_EQ(curr_block->len, 1U);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400835 EXPECT_LBL(curr_block->instrs);
836
837 /* Second block is a comparison ("arg0 == 0"). */
838 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400839 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400840 EXPECT_COMP(curr_block);
841
842 /* Third block is a jump and a label (end of AND group). */
843 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400844 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400845 EXPECT_GROUP_END(curr_block);
846
847 /*
848 * Sixth block is *not* SECCOMP_RET_ERRNO, it should be
849 * SECCOMP_RET_TRAP.
850 */
851 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400852 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400853 EXPECT_TRAP(curr_block);
854
855 /* Seventh block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
856 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400857 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400858 EXPECT_ALLOW(curr_block);
859
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400860 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400861
862 free_block_list(block);
863}
864
865FILE *write_policy_to_pipe(const char *policy, size_t len) {
866 int pipefd[2];
867 if (pipe(pipefd) == -1) {
868 pwarn("pipe(pipefd) failed");
869 return NULL;
870 }
871
872 size_t i = 0;
873 unsigned int attempts = 0;
874 ssize_t ret;
875 while (i < len) {
876 ret = write(pipefd[1], &policy[i], len - i);
877 if (ret == -1) {
878 close(pipefd[0]);
879 close(pipefd[1]);
880 return NULL;
881 }
882
883 /* If we write 0 bytes three times in a row, fail. */
884 if (ret == 0) {
885 if (++attempts >= 3) {
886 close(pipefd[0]);
887 close(pipefd[1]);
888 warn("write() returned 0 three times in a row");
889 return NULL;
890 }
891 continue;
892 }
893
894 attempts = 0;
895 i += (size_t)ret;
896 }
897
898 close(pipefd[1]);
899 return fdopen(pipefd[0], "r");
900}
901
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400902class FileTest : public ::testing::Test {
903 protected:
904 virtual void SetUp() {
905 labels_.count = 0;
906 head_ = new_filter_block();
907 arg_blocks_ = NULL;
908 }
909 virtual void TearDown() {
910 free_label_strings(&labels_);
911 free_block_list(head_);
912 free_block_list(arg_blocks_);
913 }
914 struct bpf_labels labels_;
915 struct filter_block *head_;
916 struct filter_block *arg_blocks_;
917};
918
lhchavezd0b40702017-09-01 04:17:41 +0000919TEST_F(FileTest, malformed_policy) {
920 const char *policy =
921 "malformed";
922
923 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
924 ASSERT_NE(policy_file, nullptr);
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700925 int res = compile_file("policy", policy_file, head_, &arg_blocks_, &labels_,
926 USE_RET_KILL, NO_LOGGING, 0);
lhchavezd0b40702017-09-01 04:17:41 +0000927 fclose(policy_file);
928
929 /*
930 * Policy is malformed, but process should not crash.
931 */
932 ASSERT_EQ(res, -1);
933}
934
lhchavezd38280c2017-09-01 14:00:05 +0000935TEST_F(FileTest, double_free_on_compile_error) {
936 const char *policy =
937 "read:arg0 == 0\n"
938 "write:0";
939
940 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
941 ASSERT_NE(policy_file, nullptr);
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700942 int res = compile_file("policy", policy_file, head_, &arg_blocks_, &labels_,
943 USE_RET_KILL, NO_LOGGING, 0);
lhchavezd38280c2017-09-01 14:00:05 +0000944 fclose(policy_file);
945
946 /*
947 * Policy is malformed, but process should not crash.
948 */
949 ASSERT_EQ(res, -1);
950}
951
Luis Hector Chavez52f3dd72017-09-01 19:14:22 -0700952TEST_F(FileTest, invalid_return) {
953 const char *policy =
954 "read:arg0 == 0; ;";
955
956 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
957 ASSERT_NE(policy_file, nullptr);
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700958 int res = compile_file("policy", policy_file, head_, &arg_blocks_, &labels_,
959 USE_RET_KILL, NO_LOGGING, 0);
Luis Hector Chavez52f3dd72017-09-01 19:14:22 -0700960 fclose(policy_file);
961
962 /*
963 * Policy is malformed, but process should not crash.
964 */
965 ASSERT_EQ(res, -1);
966}
967
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400968TEST_F(FileTest, seccomp_mode1) {
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400969 const char *policy =
970 "read: 1\n"
971 "write: 1\n"
972 "rt_sigreturn: 1\n"
973 "exit: 1\n";
974
975 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
976 ASSERT_NE(policy_file, nullptr);
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700977 int res = compile_file("policy", policy_file, head_, &arg_blocks_, &labels_,
978 USE_RET_KILL, NO_LOGGING, 0);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400979 fclose(policy_file);
980
981 /*
982 * Checks return value and that the blocks only allow expected syscalls.
983 */
984 ASSERT_EQ(res, 0);
985 struct filter_block *curr_block = head_;
986 ASSERT_NE(curr_block, nullptr);
987 EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_read);
988 curr_block = curr_block->next;
989 ASSERT_NE(curr_block, nullptr);
990 EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_write);
991 curr_block = curr_block->next;
992 ASSERT_NE(curr_block, nullptr);
993 EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_rt_sigreturn);
994 curr_block = curr_block->next;
995 ASSERT_NE(curr_block, nullptr);
996 EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_exit);
997
998 EXPECT_EQ(curr_block->next, nullptr);
999}
1000
1001TEST_F(FileTest, seccomp_read) {
1002 const char *policy =
1003 "read: arg0 == 0\n"
1004 "write: 1\n"
1005 "rt_sigreturn: 1\n"
1006 "exit: 1\n";
1007
1008 const int LABEL_ID = 0;
1009
1010 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
1011 ASSERT_NE(policy_file, nullptr);
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001012 int res = compile_file("policy", policy_file, head_, &arg_blocks_, &labels_,
1013 USE_RET_KILL, NO_LOGGING, 0);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -04001014 fclose(policy_file);
1015
1016 /*
1017 * Checks return value, that the blocks only allow expected syscalls, and that
1018 * labels between |head_| and |arg_blocks_| match.
1019 */
1020 ASSERT_EQ(res, 0);
1021 struct filter_block *curr_block = head_;
1022 ASSERT_NE(curr_block, nullptr);
1023 EXPECT_ALLOW_SYSCALL_ARGS(curr_block->instrs,
1024 __NR_read,
1025 LABEL_ID,
1026 JUMP_JT,
1027 JUMP_JF);
1028 curr_block = curr_block->next;
1029 ASSERT_NE(curr_block, nullptr);
1030 EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_write);
1031 curr_block = curr_block->next;
1032 ASSERT_NE(curr_block, nullptr);
1033 EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_rt_sigreturn);
1034 curr_block = curr_block->next;
1035 ASSERT_NE(curr_block, nullptr);
1036 EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_exit);
1037
1038 ASSERT_NE(arg_blocks_, nullptr);
1039 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
1040 EXPECT_EQ(arg_blocks_->total_len, exp_total_len);
1041
1042 /* First block is a label. */
1043 curr_block = arg_blocks_;
1044 ASSERT_NE(curr_block, nullptr);
1045 EXPECT_EQ(curr_block->len, 1U);
1046 EXPECT_ACTUAL_LBL(curr_block->instrs, LABEL_ID);
1047
1048 /* Second block is a comparison. */
1049 curr_block = curr_block->next;
1050 EXPECT_COMP(curr_block);
1051
1052 /* Third block is a jump and a label (end of AND group). */
1053 curr_block = curr_block->next;
1054 ASSERT_NE(curr_block, nullptr);
1055 EXPECT_GROUP_END(curr_block);
1056
1057 /* Fourth block is SECCOMP_RET_KILL. */
1058 curr_block = curr_block->next;
1059 ASSERT_NE(curr_block, nullptr);
1060 EXPECT_KILL(curr_block);
1061
1062 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
1063 curr_block = curr_block->next;
1064 ASSERT_NE(curr_block, nullptr);
1065 EXPECT_ALLOW(curr_block);
1066
1067 EXPECT_EQ(curr_block->next, nullptr);
1068}
1069
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001070TEST(FilterTest, seccomp_mode1) {
1071 struct sock_fprog actual;
1072 const char *policy =
1073 "read: 1\n"
1074 "write: 1\n"
1075 "rt_sigreturn: 1\n"
1076 "exit: 1\n";
1077
1078 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -04001079 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001080
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001081 int res =
1082 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001083 fclose(policy_file);
1084
1085 /*
1086 * Checks return value, filter length, and that the filter
1087 * validates arch, loads syscall number, and
1088 * only allows expected syscalls.
1089 */
1090 ASSERT_EQ(res, 0);
1091 EXPECT_EQ(actual.len, 13);
1092 EXPECT_ARCH_VALIDATION(actual.filter);
1093 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
1094 BPF_LD + BPF_W + BPF_ABS,
1095 syscall_nr);
1096 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 1, __NR_read);
1097 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 3, __NR_write);
1098 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 5,
1099 __NR_rt_sigreturn);
1100 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 7, __NR_exit);
1101 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN + 9,
1102 BPF_RET + BPF_K,
1103 SECCOMP_RET_KILL);
1104
1105 free(actual.filter);
1106}
1107
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -04001108TEST(FilterTest, seccomp_mode1_trap) {
1109 struct sock_fprog actual;
1110 const char *policy =
1111 "read: 1\n"
1112 "write: 1\n"
1113 "rt_sigreturn: 1\n"
1114 "exit: 1\n";
1115
1116 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -04001117 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -04001118
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001119 int res =
1120 compile_filter("policy", policy_file, &actual, USE_RET_TRAP, NO_LOGGING);
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -04001121 fclose(policy_file);
1122
1123 /*
1124 * Checks return value, filter length, and that the filter
1125 * validates arch, loads syscall number, and
1126 * only allows expected syscalls.
1127 */
1128 ASSERT_EQ(res, 0);
1129 EXPECT_EQ(actual.len, 13);
1130 EXPECT_ARCH_VALIDATION(actual.filter);
1131 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
1132 BPF_LD+BPF_W+BPF_ABS, syscall_nr);
1133 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 1,
1134 __NR_read);
1135 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 3,
1136 __NR_write);
1137 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 5,
1138 __NR_rt_sigreturn);
1139 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 7,
1140 __NR_exit);
1141 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN + 9, BPF_RET+BPF_K,
1142 SECCOMP_RET_TRAP);
1143
1144 free(actual.filter);
1145}
1146
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001147TEST(FilterTest, seccomp_read_write) {
1148 struct sock_fprog actual;
1149 const char *policy =
1150 "read: arg0 == 0\n"
1151 "write: arg0 == 1 || arg0 == 2\n"
1152 "rt_sigreturn: 1\n"
1153 "exit: 1\n";
1154
1155 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -04001156 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001157
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001158 int res =
1159 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001160 fclose(policy_file);
1161
1162 /*
1163 * Checks return value, filter length, and that the filter
1164 * validates arch, loads syscall number, and
1165 * only allows expected syscalls, jumping to correct arg filter
1166 * offsets.
1167 */
1168 ASSERT_EQ(res, 0);
1169 size_t exp_total_len = 27 + 3 * (BPF_ARG_COMP_LEN + 1);
1170 EXPECT_EQ(actual.len, exp_total_len);
1171
1172 EXPECT_ARCH_VALIDATION(actual.filter);
1173 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
1174 BPF_LD + BPF_W + BPF_ABS,
1175 syscall_nr);
1176 EXPECT_ALLOW_SYSCALL_ARGS(
1177 actual.filter + ARCH_VALIDATION_LEN + 1, __NR_read, 7, 0, 0);
1178 EXPECT_ALLOW_SYSCALL_ARGS(actual.filter + ARCH_VALIDATION_LEN + 3,
1179 __NR_write,
1180 12 + BPF_ARG_COMP_LEN,
1181 0,
1182 0);
1183 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 5,
1184 __NR_rt_sigreturn);
1185 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 7, __NR_exit);
1186 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN + 9,
1187 BPF_RET + BPF_K,
1188 SECCOMP_RET_KILL);
1189
1190 free(actual.filter);
1191}
1192
Jorge Lucangeli Obesc4992572017-04-28 10:49:01 -04001193TEST(FilterTest, misplaced_whitespace) {
1194 struct sock_fprog actual;
1195 const char *policy = "open :1\n";
1196
1197 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
1198 ASSERT_NE(policy_file, nullptr);
1199
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001200 int res =
1201 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obesc4992572017-04-28 10:49:01 -04001202 fclose(policy_file);
1203
1204 /* Checks return value and filter length. */
1205 ASSERT_EQ(res, 0);
1206 EXPECT_EQ(actual.len,
1207 ARCH_VALIDATION_LEN + 1 /* load syscall nr */ + ALLOW_SYSCALL_LEN +
1208 1 /* ret kill */);
1209 free(actual.filter);
1210}
1211
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -04001212TEST(FilterTest, missing_atom) {
1213 struct sock_fprog actual;
1214 const char* policy = "open:\n";
1215
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001216 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -04001217 ASSERT_NE(policy_file, nullptr);
1218
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001219 int res =
1220 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -04001221 fclose(policy_file);
1222 ASSERT_NE(res, 0);
1223}
1224
1225TEST(FilterTest, whitespace_atom) {
1226 struct sock_fprog actual;
1227 const char* policy = "open:\t \n";
1228
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001229 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -04001230 ASSERT_NE(policy_file, nullptr);
1231
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001232 int res =
1233 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -04001234 fclose(policy_file);
1235 ASSERT_NE(res, 0);
1236}
1237
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001238TEST(FilterTest, invalid_name) {
1239 struct sock_fprog actual;
1240 const char *policy = "notasyscall: 1\n";
1241
1242 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -04001243 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001244
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001245 int res =
1246 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001247 fclose(policy_file);
1248 ASSERT_NE(res, 0);
1249}
1250
1251TEST(FilterTest, invalid_arg) {
1252 struct sock_fprog actual;
1253 const char *policy = "open: argnn ==\n";
1254
1255 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -04001256 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001257
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001258 int res =
1259 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001260 fclose(policy_file);
1261 ASSERT_NE(res, 0);
1262}
1263
1264TEST(FilterTest, nonexistent) {
1265 struct sock_fprog actual;
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001266 int res = compile_filter("policy", NULL, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001267 ASSERT_NE(res, 0);
1268}
1269
1270TEST(FilterTest, log) {
1271 struct sock_fprog actual;
1272 const char *policy =
1273 "read: 1\n"
1274 "write: 1\n"
1275 "rt_sigreturn: 1\n"
1276 "exit: 1\n";
1277
1278 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -04001279 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001280
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001281 int res =
1282 compile_filter("policy", policy_file, &actual, USE_RET_TRAP, USE_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001283 fclose(policy_file);
1284
1285 size_t i;
1286 size_t index = 0;
1287 /*
1288 * Checks return value, filter length, and that the filter
1289 * validates arch, loads syscall number, only allows expected syscalls,
1290 * and returns TRAP on failure.
1291 * NOTE(jorgelo): the filter is longer since we add the syscalls needed
1292 * for logging.
1293 */
1294 ASSERT_EQ(res, 0);
1295 EXPECT_EQ(actual.len, 13 + 2 * log_syscalls_len);
1296 EXPECT_ARCH_VALIDATION(actual.filter);
1297 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
1298 BPF_LD + BPF_W + BPF_ABS,
1299 syscall_nr);
1300
1301 index = ARCH_VALIDATION_LEN + 1;
1302 for (i = 0; i < log_syscalls_len; i++)
1303 EXPECT_ALLOW_SYSCALL(actual.filter + (index + 2 * i),
1304 lookup_syscall(log_syscalls[i]));
1305
1306 index += 2 * log_syscalls_len;
1307
1308 EXPECT_ALLOW_SYSCALL(actual.filter + index, __NR_read);
1309 EXPECT_ALLOW_SYSCALL(actual.filter + index + 2, __NR_write);
1310 EXPECT_ALLOW_SYSCALL(actual.filter + index + 4, __NR_rt_sigreturn);
1311 EXPECT_ALLOW_SYSCALL(actual.filter + index + 6, __NR_exit);
1312 EXPECT_EQ_STMT(actual.filter + index + 8, BPF_RET + BPF_K, SECCOMP_RET_TRAP);
1313
1314 free(actual.filter);
1315}
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -04001316
1317TEST(FilterTest, allow_log_but_kill) {
1318 struct sock_fprog actual;
1319 const char *policy =
1320 "read: 1\n"
1321 "write: 1\n"
1322 "rt_sigreturn: 1\n"
1323 "exit: 1\n";
1324
1325 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -04001326 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -04001327
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001328 int res =
1329 compile_filter("policy", policy_file, &actual, USE_RET_KILL, USE_LOGGING);
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -04001330 fclose(policy_file);
1331
1332 size_t i;
1333 size_t index = 0;
1334 /*
1335 * Checks return value, filter length, and that the filter
1336 * validates arch, loads syscall number, only allows expected syscalls,
1337 * and returns TRAP on failure.
1338 * NOTE(jorgelo): the filter is longer since we add the syscalls needed
1339 * for logging.
1340 */
1341 ASSERT_EQ(res, 0);
1342 EXPECT_EQ(actual.len, 13 + 2 * log_syscalls_len);
1343 EXPECT_ARCH_VALIDATION(actual.filter);
1344 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
1345 BPF_LD+BPF_W+BPF_ABS, syscall_nr);
1346
1347 index = ARCH_VALIDATION_LEN + 1;
1348 for (i = 0; i < log_syscalls_len; i++)
1349 EXPECT_ALLOW_SYSCALL(actual.filter + (index + 2 * i),
1350 lookup_syscall(log_syscalls[i]));
1351
1352 index += 2 * log_syscalls_len;
1353
1354 EXPECT_ALLOW_SYSCALL(actual.filter + index, __NR_read);
1355 EXPECT_ALLOW_SYSCALL(actual.filter + index + 2, __NR_write);
1356 EXPECT_ALLOW_SYSCALL(actual.filter + index + 4, __NR_rt_sigreturn);
1357 EXPECT_ALLOW_SYSCALL(actual.filter + index + 6, __NR_exit);
1358 EXPECT_EQ_STMT(actual.filter + index + 8, BPF_RET+BPF_K,
1359 SECCOMP_RET_KILL);
1360
1361 free(actual.filter);
1362}
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001363
1364TEST(FilterTest, include_invalid_token) {
1365 struct sock_fprog actual;
1366 const char *invalid_token = "@unclude ./test/seccomp.policy\n";
1367
1368 FILE *policy_file =
1369 write_policy_to_pipe(invalid_token, strlen(invalid_token));
1370 ASSERT_NE(policy_file, nullptr);
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001371 int res =
1372 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001373 fclose(policy_file);
1374 EXPECT_NE(res, 0);
1375}
1376
1377TEST(FilterTest, include_no_space) {
1378 struct sock_fprog actual;
1379 const char *no_space = "@includetest/seccomp.policy\n";
1380
1381 FILE *policy_file = write_policy_to_pipe(no_space, strlen(no_space));
1382 ASSERT_NE(policy_file, nullptr);
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001383 int res =
1384 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001385 fclose(policy_file);
1386 EXPECT_NE(res, 0);
1387}
1388
1389TEST(FilterTest, include_double_token) {
1390 struct sock_fprog actual;
1391 const char *double_token = "@includeinclude ./test/seccomp.policy\n";
1392
1393 FILE *policy_file = write_policy_to_pipe(double_token, strlen(double_token));
1394 ASSERT_NE(policy_file, nullptr);
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001395 int res =
1396 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001397 fclose(policy_file);
1398 EXPECT_NE(res, 0);
1399}
1400
1401TEST(FilterTest, include_no_file) {
1402 struct sock_fprog actual;
1403 const char *no_file = "@include\n";
1404
1405 FILE *policy_file = write_policy_to_pipe(no_file, strlen(no_file));
1406 ASSERT_NE(policy_file, nullptr);
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001407 int res =
1408 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001409 fclose(policy_file);
1410 EXPECT_NE(res, 0);
1411}
1412
1413TEST(FilterTest, include_space_no_file) {
1414 struct sock_fprog actual;
1415 const char *space_no_file = "@include \n";
1416
1417 FILE *policy_file =
1418 write_policy_to_pipe(space_no_file, strlen(space_no_file));
1419 ASSERT_NE(policy_file, nullptr);
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001420 int res =
1421 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001422 fclose(policy_file);
1423 EXPECT_NE(res, 0);
1424}
1425
1426TEST(FilterTest, include_implicit_relative_path) {
1427 struct sock_fprog actual;
1428 const char *implicit_relative_path = "@include test/seccomp.policy\n";
1429
1430 FILE *policy_file = write_policy_to_pipe(implicit_relative_path,
1431 strlen(implicit_relative_path));
1432 ASSERT_NE(policy_file, nullptr);
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001433 int res =
1434 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001435 fclose(policy_file);
1436 EXPECT_NE(res, 0);
1437}
1438
1439TEST(FilterTest, include_extra_text) {
1440 struct sock_fprog actual;
1441 const char *extra_text = "@include /some/file: sneaky comment\n";
1442
1443 FILE *policy_file =
1444 write_policy_to_pipe(extra_text, strlen(extra_text));
1445 ASSERT_NE(policy_file, nullptr);
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001446 int res =
1447 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001448 fclose(policy_file);
1449 EXPECT_NE(res, 0);
1450}
1451
1452TEST(FilterTest, include_split_filename) {
1453 struct sock_fprog actual;
1454 const char *split_filename = "@include /some/file:colon.policy\n";
1455
1456 FILE *policy_file =
1457 write_policy_to_pipe(split_filename, strlen(split_filename));
1458 ASSERT_NE(policy_file, nullptr);
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001459 int res =
1460 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001461 fclose(policy_file);
1462 EXPECT_NE(res, 0);
1463}
1464
1465TEST(FilterTest, include_nonexistent_file) {
1466 struct sock_fprog actual;
1467 const char *include_policy = "@include ./nonexistent.policy\n";
1468
1469 FILE *policy_file =
1470 write_policy_to_pipe(include_policy, strlen(include_policy));
1471 ASSERT_NE(policy_file, nullptr);
1472
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001473 int res =
1474 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001475 fclose(policy_file);
1476
1477 ASSERT_NE(res, 0);
1478}
1479
1480// TODO(jorgelo): Android unit tests don't currently support data files.
1481// Re-enable by creating a temporary policy file at runtime.
1482#if !defined(__ANDROID__)
1483
1484TEST(FilterTest, include) {
1485 struct sock_fprog compiled_plain;
1486 struct sock_fprog compiled_with_include;
1487
1488 const char *policy_plain =
1489 "read: 1\n"
1490 "write: 1\n"
1491 "rt_sigreturn: 1\n"
1492 "exit: 1\n";
1493
1494 const char *policy_with_include = "@include ./test/seccomp.policy\n";
1495
1496 FILE *file_plain = write_policy_to_pipe(policy_plain, strlen(policy_plain));
1497 ASSERT_NE(file_plain, nullptr);
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001498 int res_plain = compile_filter("policy", file_plain, &compiled_plain,
1499 USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001500 fclose(file_plain);
1501
1502 FILE *file_with_include =
1503 write_policy_to_pipe(policy_with_include, strlen(policy_with_include));
1504 ASSERT_NE(file_with_include, nullptr);
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001505 int res_with_include =
1506 compile_filter("policy", file_with_include, &compiled_with_include,
1507 USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001508 fclose(file_with_include);
1509
1510 /*
1511 * Checks that filter length is the same for a plain policy and an equivalent
1512 * policy with an @include statement. Also checks that the filter generated
1513 * from the policy with an @include statement is exactly the same as one
1514 * generated from a plain policy.
1515 */
1516 ASSERT_EQ(res_plain, 0);
1517 ASSERT_EQ(res_with_include, 0);
1518
1519 EXPECT_EQ(compiled_plain.len, 13);
1520 EXPECT_EQ(compiled_with_include.len, 13);
1521
1522 EXPECT_ARCH_VALIDATION(compiled_with_include.filter);
1523 EXPECT_EQ_STMT(compiled_with_include.filter + ARCH_VALIDATION_LEN,
1524 BPF_LD + BPF_W + BPF_ABS,
1525 syscall_nr);
1526 EXPECT_ALLOW_SYSCALL(compiled_with_include.filter + ARCH_VALIDATION_LEN + 1,
1527 __NR_read);
1528 EXPECT_ALLOW_SYSCALL(compiled_with_include.filter + ARCH_VALIDATION_LEN + 3,
1529 __NR_write);
1530 EXPECT_ALLOW_SYSCALL(compiled_with_include.filter + ARCH_VALIDATION_LEN + 5,
1531 __NR_rt_sigreturn);
1532 EXPECT_ALLOW_SYSCALL(compiled_with_include.filter + ARCH_VALIDATION_LEN + 7,
1533 __NR_exit);
1534 EXPECT_EQ_STMT(compiled_with_include.filter + ARCH_VALIDATION_LEN + 9,
1535 BPF_RET + BPF_K,
1536 SECCOMP_RET_KILL);
1537
1538 free(compiled_plain.filter);
1539 free(compiled_with_include.filter);
1540}
1541
1542TEST(FilterTest, include_same_syscalls) {
1543 struct sock_fprog actual;
1544 const char *policy =
1545 "read: 1\n"
1546 "write: 1\n"
1547 "rt_sigreturn: 1\n"
1548 "exit: 1\n"
1549 "@include ./test/seccomp.policy\n";
1550
1551 FILE *policy_file =
1552 write_policy_to_pipe(policy, strlen(policy));
1553 ASSERT_NE(policy_file, nullptr);
1554
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001555 int res =
1556 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001557 fclose(policy_file);
1558
1559 ASSERT_EQ(res, 0);
1560 EXPECT_EQ(actual.len,
1561 ARCH_VALIDATION_LEN + 1 /* load syscall nr */ +
1562 2 * 8 /* check syscalls twice */ + 1 /* filter return */);
1563 free(actual.filter);
1564}
1565
1566TEST(FilterTest, include_invalid_policy) {
1567 struct sock_fprog actual;
1568 const char *policy =
1569 "read: 1\n"
1570 "write: 1\n"
1571 "rt_sigreturn: 1\n"
1572 "exit: 1\n"
1573 "@include ./test/invalid_syscall_name.policy\n";
1574
1575 FILE *policy_file =
1576 write_policy_to_pipe(policy, strlen(policy));
1577 ASSERT_NE(policy_file, nullptr);
1578
1579 /* Ensure the included (invalid) policy file exists. */
1580 FILE *included_file = fopen("./test/invalid_syscall_name.policy", "r");
1581 ASSERT_NE(included_file, nullptr);
1582 fclose(included_file);
1583
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001584 int res =
1585 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001586 fclose(policy_file);
1587
1588 ASSERT_NE(res, 0);
1589}
1590
1591TEST(FilterTest, include_nested) {
1592 struct sock_fprog actual;
1593 const char *policy = "@include ./test/nested.policy\n";
1594
1595 FILE *policy_file =
1596 write_policy_to_pipe(policy, strlen(policy));
1597 ASSERT_NE(policy_file, nullptr);
1598
1599 /* Ensure the policy file exists. */
1600 FILE *included_file = fopen("./test/nested.policy", "r");
1601 ASSERT_NE(included_file, nullptr);
1602 fclose(included_file);
1603
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001604 int res =
1605 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001606 fclose(policy_file);
1607
1608 ASSERT_NE(res, 0);
1609}
1610
Luis Hector Chavez1a87c8a2017-09-02 13:18:31 -07001611TEST(FilterTest, error_cleanup_leak) {
1612 struct sock_fprog actual;
1613 const char *policy =
1614 "read:&&\n"
1615 "read:&&";
1616
1617 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
1618 ASSERT_NE(policy_file, nullptr);
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001619 int res =
1620 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Luis Hector Chavez1a87c8a2017-09-02 13:18:31 -07001621 fclose(policy_file);
1622
1623 /*
1624 * Policy is malformed, but process should not leak.
1625 */
1626 ASSERT_EQ(res, -1);
1627}
1628
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001629#endif // !__ANDROID__