1 /* Copyright 2016 The Chromium OS 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.
4 *
5 * Test syscall filtering using gtest.
6 */
7
8 #include <asm/unistd.h>
9 #include <errno.h>
10 #include <fcntl.h> /* For O_WRONLY. */
11
12 #include <gtest/gtest.h>
13 #include <string>
14
15 #include "bpf.h"
16 #include "syscall_filter.h"
17 #include "syscall_filter_unittest_macros.h"
18 #include "util.h"
19
20 namespace {
21
22 // TODO(jorgelo): Android unit tests don't currently support data files.
23 // Re-enable by creating a temporary policy file at runtime.
24 #if !defined(__ANDROID__)
25
source_path(std::string file)26 std::string source_path(std::string file) {
27 std::string srcdir = getenv("SRC") ? : ".";
28 return srcdir + "/" + file;
29 }
30
31 #endif
32
33 // Simple C++ -> C wrappers to simplify test code.
34
35 enum ret_trap {
36 USE_RET_KILL = 0,
37 USE_RET_TRAP = 1,
38 };
39
40 enum use_logging {
41 NO_LOGGING = 0,
42 USE_LOGGING = 1,
43 };
44
test_compile_filter(std::string filename,FILE * policy_file,struct sock_fprog * prog,enum ret_trap do_ret_trap=USE_RET_KILL,enum use_logging add_logging_syscalls=NO_LOGGING)45 int test_compile_filter(
46 std::string filename,
47 FILE* policy_file,
48 struct sock_fprog* prog,
49 enum ret_trap do_ret_trap = USE_RET_KILL,
50 enum use_logging add_logging_syscalls = NO_LOGGING) {
51 return compile_filter(filename.c_str(), policy_file, prog, do_ret_trap,
52 add_logging_syscalls);
53 }
54
test_compile_file(std::string filename,FILE * policy_file,struct filter_block * head,struct filter_block ** arg_blocks,struct bpf_labels * labels,enum ret_trap use_ret_trap=USE_RET_KILL,enum use_logging allow_logging=NO_LOGGING,unsigned int include_level=0)55 int test_compile_file(
56 std::string filename,
57 FILE* policy_file,
58 struct filter_block* head,
59 struct filter_block** arg_blocks,
60 struct bpf_labels* labels,
61 enum ret_trap use_ret_trap = USE_RET_KILL,
62 enum use_logging allow_logging = NO_LOGGING,
63 unsigned int include_level = 0) {
64 return compile_file(filename.c_str(), policy_file, head, arg_blocks, labels,
65 use_ret_trap, allow_logging, include_level);
66 }
67
test_compile_policy_line(struct parser_state * state,int nr,std::string policy_line,unsigned int label_id,struct bpf_labels * labels,enum ret_trap do_ret_trap=USE_RET_KILL)68 struct filter_block* test_compile_policy_line(
69 struct parser_state* state,
70 int nr,
71 std::string policy_line,
72 unsigned int label_id,
73 struct bpf_labels* labels,
74 enum ret_trap do_ret_trap = USE_RET_KILL) {
75 return compile_policy_line(state, nr, policy_line.c_str(), label_id, labels,
76 do_ret_trap);
77 }
78
79 } // namespace
80
TEST(util,parse_constant_unsigned)81 TEST(util, parse_constant_unsigned) {
82 char *end;
83 long int c = 0;
84 std::string constant;
85
86 #if defined(BITS32)
87 constant = "0x80000000";
88 c = parse_constant(const_cast<char*>(constant.data()), &end);
89 EXPECT_EQ(0x80000000U, static_cast<unsigned long int>(c));
90
91 #elif defined(BITS64)
92 constant = "0x8000000000000000";
93 c = parse_constant(const_cast<char*>(constant.data()), &end);
94 EXPECT_EQ(0x8000000000000000UL, static_cast<unsigned long int>(c));
95 #endif
96 }
97
TEST(util,parse_constant_unsigned_toobig)98 TEST(util, parse_constant_unsigned_toobig) {
99 char *end;
100 long int c = 0;
101 std::string constant;
102
103 #if defined(BITS32)
104 constant = "0x100000000"; // Too big for 32-bit unsigned long int.
105 c = parse_constant(const_cast<char*>(constant.data()), &end);
106 // Error case should return 0.
107 EXPECT_EQ(0, c);
108
109 #elif defined(BITS64)
110 constant = "0x10000000000000000";
111 c = parse_constant(const_cast<char*>(constant.data()), &end);
112 // Error case should return 0.
113 EXPECT_EQ(0, c);
114 #endif
115 }
116
TEST(util,parse_constant_signed)117 TEST(util, parse_constant_signed) {
118 char *end;
119 long int c = 0;
120 std::string constant = "-1";
121 c = parse_constant(const_cast<char*>(constant.data()), &end);
122 EXPECT_EQ(-1, c);
123 }
124
TEST(util,parse_constant_signed_toonegative)125 TEST(util, parse_constant_signed_toonegative) {
126 char *end;
127 long int c = 0;
128 std::string constant;
129
130 #if defined(BITS32)
131 constant = "-0x80000001";
132 c = parse_constant(const_cast<char*>(constant.data()), &end);
133 // Error case should return 0.
134 EXPECT_EQ(0, c);
135
136 #elif defined(BITS64)
137 constant = "-0x8000000000000001";
138 c = parse_constant(const_cast<char*>(constant.data()), &end);
139 // Error case should return 0.
140 EXPECT_EQ(0, c);
141 #endif
142 }
143
TEST(util,parse_constant_complements)144 TEST(util, parse_constant_complements) {
145 char* end;
146 long int c = 0;
147 std::string constant;
148
149 #if defined(BITS32)
150 constant = "~0x005AF0FF|~0xFFA50FFF";
151 c = parse_constant(const_cast<char*>(constant.data()), &end);
152 EXPECT_EQ(c, 0xFFFFFF00);
153 constant = "0x0F|~(0x005AF000|0x00A50FFF)|0xF0";
154 c = parse_constant(const_cast<char*>(constant.data()), &end);
155 EXPECT_EQ(c, 0xFF0000FF);
156
157 #elif defined(BITS64)
158 constant = "~0x00005A5AF0F0FFFF|~0xFFFFA5A50F0FFFFF";
159 c = parse_constant(const_cast<char*>(constant.data()), &end);
160 EXPECT_EQ(c, 0xFFFFFFFFFFFF0000UL);
161 constant = "0x00FF|~(0x00005A5AF0F00000|0x0000A5A50F0FFFFF)|0xFF00";
162 c = parse_constant(const_cast<char*>(constant.data()), &end);
163 EXPECT_EQ(c, 0xFFFF00000000FFFFUL);
164 #endif
165 }
166
TEST(util,parse_parenthesized_expresions)167 TEST(util, parse_parenthesized_expresions) {
168 char* end;
169
170 const std::vector<const char*> bad_expressions = {
171 "(1", "1)", "(1)1", "|(1)", "(1)|", "()",
172 "(", "((", "(()", "(()1", "1(0)",
173 };
174 for (const auto* expression : bad_expressions) {
175 std::string mutable_expression = expression;
176 long int c =
177 parse_constant(const_cast<char*>(mutable_expression.data()), &end);
178 EXPECT_EQ(reinterpret_cast<const void*>(end),
179 reinterpret_cast<const void*>(mutable_expression.data()));
180 // Error case should return 0.
181 EXPECT_EQ(c, 0) << "For expression: \"" << expression << "\"";
182 }
183
184 const std::vector<const char*> good_expressions = {
185 "(3)", "(1)|2", "1|(2)", "(1)|(2)", "((3))", "0|(1|2)", "(0|1|2)",
186 };
187 for (const auto* expression : good_expressions) {
188 std::string mutable_expression = expression;
189 long int c =
190 parse_constant(const_cast<char*>(mutable_expression.data()), &end);
191 EXPECT_EQ(c, 3) << "For expression: \"" << expression << "\"";
192 }
193 }
194
195 /* Test that setting one BPF instruction works. */
TEST(bpf,set_bpf_instr)196 TEST(bpf, set_bpf_instr) {
197 struct sock_filter instr;
198 unsigned char code = BPF_LD + BPF_W + BPF_ABS;
199 unsigned int k = 4;
200 unsigned char jt = 1, jf = 2;
201
202 size_t len = set_bpf_instr(&instr, code, k, jt, jf);
203
204 EXPECT_EQ(len, 1U);
205 EXPECT_EQ_BLOCK(&instr, code, k, jt, jf);
206 }
207
TEST(bpf,bpf_load_arg)208 TEST(bpf, bpf_load_arg) {
209 struct sock_filter load_arg[BPF_LOAD_ARG_LEN];
210 const int argidx = 1;
211 size_t len = bpf_load_arg(load_arg, argidx);
212
213 EXPECT_EQ(len, BPF_LOAD_ARG_LEN);
214
215 #if defined(BITS32)
216 EXPECT_EQ_STMT(&load_arg[0], BPF_LD + BPF_W + BPF_ABS, LO_ARG(argidx));
217 #elif defined(BITS64)
218 EXPECT_EQ_STMT(&load_arg[0], BPF_LD + BPF_W + BPF_ABS, LO_ARG(argidx));
219 EXPECT_EQ_STMT(&load_arg[1], BPF_ST, 0);
220 EXPECT_EQ_STMT(&load_arg[2], BPF_LD + BPF_W + BPF_ABS, HI_ARG(argidx));
221 EXPECT_EQ_STMT(&load_arg[3], BPF_ST, 1);
222 #endif
223 }
224
TEST(bpf,bpf_comp_jeq)225 TEST(bpf, bpf_comp_jeq) {
226 struct sock_filter comp_jeq[BPF_COMP_LEN];
227 unsigned long c = 1;
228 unsigned char jt = 1;
229 unsigned char jf = 2;
230
231 size_t len = bpf_comp_jeq(comp_jeq, c, jt, jf);
232
233 EXPECT_EQ(len, BPF_COMP_LEN);
234
235 #if defined(BITS32)
236 EXPECT_EQ_BLOCK(&comp_jeq[0], BPF_JMP + BPF_JEQ + BPF_K, c, jt, jf);
237 #elif defined(BITS64)
238 EXPECT_EQ_BLOCK(&comp_jeq[0], BPF_JMP + BPF_JEQ + BPF_K, 0, 0, jf + 2);
239 EXPECT_EQ_STMT(&comp_jeq[1], BPF_LD + BPF_MEM, 0);
240 EXPECT_EQ_BLOCK(&comp_jeq[2], BPF_JMP + BPF_JEQ + BPF_K, c, jt, jf);
241 #endif
242 }
243
TEST(bpf,bpf_comp_jset)244 TEST(bpf, bpf_comp_jset) {
245 struct sock_filter comp_jset[BPF_COMP_LEN];
246 unsigned long mask = (1UL << (sizeof(unsigned long) * 8 - 1)) | O_WRONLY;
247 unsigned char jt = 1;
248 unsigned char jf = 2;
249
250 size_t len = bpf_comp_jset(comp_jset, mask, jt, jf);
251
252 EXPECT_EQ(len, BPF_COMP_LEN);
253
254 #if defined(BITS32)
255 EXPECT_EQ_BLOCK(&comp_jset[0], BPF_JMP + BPF_JSET + BPF_K, mask, jt, jf);
256 #elif defined(BITS64)
257 EXPECT_EQ_BLOCK(
258 &comp_jset[0], BPF_JMP + BPF_JSET + BPF_K, 0x80000000, jt + 2, 0);
259 EXPECT_EQ_STMT(&comp_jset[1], BPF_LD + BPF_MEM, 0);
260 EXPECT_EQ_BLOCK(&comp_jset[2], BPF_JMP + BPF_JSET + BPF_K, O_WRONLY, jt, jf);
261 #endif
262 }
263
TEST(bpf,bpf_comp_jin)264 TEST(bpf, bpf_comp_jin) {
265 struct sock_filter comp_jin[BPF_COMP_LEN];
266 unsigned long mask = (1UL << (sizeof(unsigned long) * 8 - 1)) | O_WRONLY;
267 unsigned char jt = 10;
268 unsigned char jf = 20;
269
270 size_t len = bpf_comp_jin(comp_jin, mask, jt, jf);
271
272 EXPECT_EQ(len, BPF_COMP_LEN);
273
274 #if defined(BITS32)
275 EXPECT_EQ_BLOCK(&comp_jin[0], BPF_JMP + BPF_JSET + BPF_K, ~mask, jf, jt);
276 #elif defined(BITS64)
277 EXPECT_EQ_BLOCK(
278 &comp_jin[0], BPF_JMP + BPF_JSET + BPF_K, 0x7FFFFFFF, jf + 2, 0);
279 EXPECT_EQ_STMT(&comp_jin[1], BPF_LD + BPF_MEM, 0);
280 EXPECT_EQ_BLOCK(&comp_jin[2], BPF_JMP + BPF_JSET + BPF_K, ~O_WRONLY, jf, jt);
281 #endif
282 }
283
TEST(bpf,bpf_arg_comp)284 TEST(bpf, bpf_arg_comp) {
285 struct sock_filter *arg_comp;
286 int op = EQ;
287 const int argidx = 1;
288 unsigned long c = 3;
289 unsigned int label_id = 0;
290
291 size_t len = bpf_arg_comp(&arg_comp, op, argidx, c, label_id);
292
293 EXPECT_EQ(len, BPF_ARG_COMP_LEN + 1);
294
295 #if defined(BITS32)
296 EXPECT_EQ_STMT(&arg_comp[0], BPF_LD + BPF_W + BPF_ABS, LO_ARG(argidx));
297 EXPECT_EQ_BLOCK(&arg_comp[1], BPF_JMP + BPF_JEQ + BPF_K, c, 1, 0);
298 EXPECT_JUMP_LBL(&arg_comp[2]);
299 #elif defined(BITS64)
300 EXPECT_EQ_STMT(&arg_comp[0], BPF_LD + BPF_W + BPF_ABS, LO_ARG(argidx));
301 EXPECT_EQ_STMT(&arg_comp[1], BPF_ST, 0);
302 EXPECT_EQ_STMT(&arg_comp[2], BPF_LD + BPF_W + BPF_ABS, HI_ARG(argidx));
303 EXPECT_EQ_STMT(&arg_comp[3], BPF_ST, 1);
304
305 EXPECT_EQ_BLOCK(&arg_comp[4], BPF_JMP + BPF_JEQ + BPF_K, 0, 0, 2);
306 EXPECT_EQ_STMT(&arg_comp[5], BPF_LD + BPF_MEM, 0);
307 EXPECT_EQ_BLOCK(&arg_comp[6], BPF_JMP + BPF_JEQ + BPF_K, c, 1, 0);
308 EXPECT_JUMP_LBL(&arg_comp[7]);
309 #endif
310 free(arg_comp);
311 }
312
TEST(bpf,bpf_validate_arch)313 TEST(bpf, bpf_validate_arch) {
314 struct sock_filter validate_arch[ARCH_VALIDATION_LEN];
315
316 size_t len = bpf_validate_arch(validate_arch);
317
318 EXPECT_EQ(len, ARCH_VALIDATION_LEN);
319 EXPECT_ARCH_VALIDATION(validate_arch);
320 }
321
TEST(bpf,bpf_allow_syscall)322 TEST(bpf, bpf_allow_syscall) {
323 struct sock_filter allow_syscall[ALLOW_SYSCALL_LEN];
324 int nr = 1;
325
326 size_t len = bpf_allow_syscall(allow_syscall, nr);
327
328 EXPECT_EQ(len, ALLOW_SYSCALL_LEN);
329 EXPECT_ALLOW_SYSCALL(allow_syscall, nr);
330 }
331
TEST(bpf,bpf_allow_syscall_args)332 TEST(bpf, bpf_allow_syscall_args) {
333 struct sock_filter allow_syscall[ALLOW_SYSCALL_LEN];
334 int nr = 1;
335 unsigned int id = 1024;
336
337 size_t len = bpf_allow_syscall_args(allow_syscall, nr, id);
338
339 EXPECT_EQ(len, ALLOW_SYSCALL_LEN);
340 EXPECT_ALLOW_SYSCALL_ARGS(allow_syscall, nr, id, JUMP_JT, JUMP_JF);
341 }
342
343 class BpfLabelTest : public ::testing::Test {
344 protected:
SetUp()345 virtual void SetUp() { labels_.count = 0; }
TearDown()346 virtual void TearDown() { free_label_strings(&labels_); }
347 struct bpf_labels labels_;
348 };
349
TEST_F(BpfLabelTest,zero_length_filter)350 TEST_F(BpfLabelTest, zero_length_filter) {
351 int res = bpf_resolve_jumps(&labels_, nullptr, 0);
352
353 EXPECT_EQ(res, 0);
354 EXPECT_EQ(labels_.count, 0U);
355 }
356
TEST_F(BpfLabelTest,single_label)357 TEST_F(BpfLabelTest, single_label) {
358 struct sock_filter test_label[1];
359
360 int id = bpf_label_id(&labels_, "test");
361 set_bpf_lbl(test_label, id);
362 int res = bpf_resolve_jumps(&labels_, test_label, 1);
363
364 EXPECT_EQ(res, 0);
365 EXPECT_EQ(labels_.count, 1U);
366 }
367
TEST_F(BpfLabelTest,repeated_label)368 TEST_F(BpfLabelTest, repeated_label) {
369 struct sock_filter test_label[2];
370
371 int id = bpf_label_id(&labels_, "test");
372 set_bpf_lbl(&test_label[0], id);
373 set_bpf_lbl(&test_label[1], id);
374 int res = bpf_resolve_jumps(&labels_, test_label, 2);
375
376 EXPECT_EQ(res, -1);
377 }
378
TEST_F(BpfLabelTest,jump_with_no_label)379 TEST_F(BpfLabelTest, jump_with_no_label) {
380 struct sock_filter test_jump[1];
381
382 set_bpf_jump_lbl(test_jump, 14831);
383 int res = bpf_resolve_jumps(&labels_, test_jump, 1);
384
385 EXPECT_EQ(res, -1);
386 }
387
TEST_F(BpfLabelTest,jump_to_valid_label)388 TEST_F(BpfLabelTest, jump_to_valid_label) {
389 struct sock_filter test_jump[2];
390
391 int id = bpf_label_id(&labels_, "test");
392 set_bpf_jump_lbl(&test_jump[0], id);
393 set_bpf_lbl(&test_jump[1], id);
394
395 int res = bpf_resolve_jumps(&labels_, test_jump, 2);
396 EXPECT_EQ(res, 0);
397 EXPECT_EQ(labels_.count, 1U);
398 }
399
TEST_F(BpfLabelTest,jump_to_invalid_label)400 TEST_F(BpfLabelTest, jump_to_invalid_label) {
401 struct sock_filter test_jump[2];
402
403 int id = bpf_label_id(&labels_, "test");
404 set_bpf_jump_lbl(&test_jump[0], id + 1);
405 set_bpf_lbl(&test_jump[1], id);
406
407 int res = bpf_resolve_jumps(&labels_, test_jump, 2);
408 EXPECT_EQ(res, -1);
409 }
410
TEST_F(BpfLabelTest,jump_to_unresolved_label)411 TEST_F(BpfLabelTest, jump_to_unresolved_label) {
412 struct sock_filter test_jump[2];
413
414 int id = bpf_label_id(&labels_, "test");
415 /* Notice the order of the instructions is reversed. */
416 set_bpf_lbl(&test_jump[0], id);
417 set_bpf_jump_lbl(&test_jump[1], id);
418
419 int res = bpf_resolve_jumps(&labels_, test_jump, 2);
420 EXPECT_EQ(res, -1);
421 }
422
TEST_F(BpfLabelTest,too_many_labels)423 TEST_F(BpfLabelTest, too_many_labels) {
424 unsigned int i;
425 char label[20];
426
427 for (i = 0; i < BPF_LABELS_MAX; i++) {
428 snprintf(label, 20, "test%u", i);
429 (void) bpf_label_id(&labels_, label);
430 }
431 int id = bpf_label_id(&labels_, "test");
432
433 /* Insertion failed... */
434 EXPECT_EQ(id, -1);
435 /* ... because the label lookup table is full. */
436 EXPECT_EQ(labels_.count, BPF_LABELS_MAX);
437 }
438
439 class ArgFilterTest : public ::testing::Test {
440 protected:
SetUp()441 virtual void SetUp() {
442 labels_.count = 0;
443 state_.filename = "policy";
444 state_.line_number = 1;
445 }
TearDown()446 virtual void TearDown() { free_label_strings(&labels_); }
447 struct bpf_labels labels_;
448 int nr_ = 1;
449 unsigned int id_ = 0;
450 struct parser_state state_;
451 };
452
TEST_F(ArgFilterTest,empty_atom)453 TEST_F(ArgFilterTest, empty_atom) {
454 std::string fragment = "";
455
456 struct filter_block* block =
457 test_compile_policy_line(&state_, nr_, fragment, id_, &labels_);
458 ASSERT_EQ(block, nullptr);
459 }
460
TEST_F(ArgFilterTest,whitespace_atom)461 TEST_F(ArgFilterTest, whitespace_atom) {
462 std::string fragment = "\t ";
463
464 struct filter_block* block =
465 test_compile_policy_line(&state_, nr_, fragment, id_, &labels_);
466 ASSERT_EQ(block, nullptr);
467 }
468
TEST_F(ArgFilterTest,no_comparison)469 TEST_F(ArgFilterTest, no_comparison) {
470 std::string fragment = "arg0";
471
472 struct filter_block* block =
473 test_compile_policy_line(&state_, nr_, fragment, id_, &labels_);
474 ASSERT_EQ(block, nullptr);
475 }
476
TEST_F(ArgFilterTest,no_constant)477 TEST_F(ArgFilterTest, no_constant) {
478 std::string fragment = "arg0 ==";
479
480 struct filter_block* block =
481 test_compile_policy_line(&state_, nr_, fragment, id_, &labels_);
482 ASSERT_EQ(block, nullptr);
483 }
484
TEST_F(ArgFilterTest,arg0_equals)485 TEST_F(ArgFilterTest, arg0_equals) {
486 std::string fragment = "arg0 == 0";
487
488 struct filter_block* block =
489 test_compile_policy_line(&state_, nr_, fragment, id_, &labels_);
490
491 ASSERT_NE(block, nullptr);
492 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
493 EXPECT_EQ(block->total_len, exp_total_len);
494
495 /* First block is a label. */
496 struct filter_block *curr_block = block;
497 ASSERT_NE(curr_block, nullptr);
498 EXPECT_EQ(curr_block->len, 1U);
499 EXPECT_LBL(curr_block->instrs);
500
501 /* Second block is a comparison. */
502 curr_block = curr_block->next;
503 EXPECT_COMP(curr_block);
504
505 /* Third block is a jump and a label (end of AND group). */
506 curr_block = curr_block->next;
507 ASSERT_NE(curr_block, nullptr);
508 EXPECT_GROUP_END(curr_block);
509
510 /* Fourth block is SECCOMP_RET_KILL. */
511 curr_block = curr_block->next;
512 ASSERT_NE(curr_block, nullptr);
513 EXPECT_KILL(curr_block);
514
515 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
516 curr_block = curr_block->next;
517 ASSERT_NE(curr_block, nullptr);
518 EXPECT_ALLOW(curr_block);
519
520 EXPECT_EQ(curr_block->next, nullptr);
521
522 free_block_list(block);
523 }
524
TEST_F(ArgFilterTest,arg0_short_gt_ge_comparisons)525 TEST_F(ArgFilterTest, arg0_short_gt_ge_comparisons) {
526 for (std::string fragment :
527 {"arg1 < 0xff", "arg1 <= 0xff", "arg1 > 0xff", "arg1 >= 0xff"}) {
528 struct filter_block* block =
529 test_compile_policy_line(&state_, nr_, fragment, id_, &labels_);
530
531 ASSERT_NE(block, nullptr);
532 size_t exp_total_len = 1 + (BPF_ARG_SHORT_GT_GE_COMP_LEN + 1) + 2 + 1 + 2;
533 EXPECT_EQ(block->total_len, exp_total_len);
534
535 // First block is a label.
536 struct filter_block* curr_block = block;
537 ASSERT_NE(curr_block, nullptr);
538 EXPECT_EQ(curr_block->len, 1U);
539 EXPECT_LBL(curr_block->instrs);
540
541 // Second block is a short gt/ge comparison.
542 curr_block = curr_block->next;
543 EXPECT_SHORT_GT_GE_COMP(curr_block);
544
545 // Third block is a jump and a label (end of AND group).
546 curr_block = curr_block->next;
547 ASSERT_NE(curr_block, nullptr);
548 EXPECT_GROUP_END(curr_block);
549
550 // Fourth block is SECCOMP_RET_KILL.
551 curr_block = curr_block->next;
552 ASSERT_NE(curr_block, nullptr);
553 EXPECT_KILL(curr_block);
554
555 // Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW.
556 curr_block = curr_block->next;
557 ASSERT_NE(curr_block, nullptr);
558 EXPECT_ALLOW(curr_block);
559
560 EXPECT_EQ(curr_block->next, nullptr);
561
562 free_block_list(block);
563 }
564 }
565
566 #if defined(BITS64)
TEST_F(ArgFilterTest,arg0_long_gt_ge_comparisons)567 TEST_F(ArgFilterTest, arg0_long_gt_ge_comparisons) {
568 for (std::string fragment :
569 {"arg1 < 0xbadc0ffee0ddf00d", "arg1 <= 0xbadc0ffee0ddf00d",
570 "arg1 > 0xbadc0ffee0ddf00d", "arg1 >= 0xbadc0ffee0ddf00d"}) {
571 struct filter_block* block =
572 test_compile_policy_line(&state_, nr_, fragment, id_, &labels_);
573
574 ASSERT_NE(block, nullptr);
575 size_t exp_total_len = 1 + (BPF_ARG_GT_GE_COMP_LEN + 1) + 2 + 1 + 2;
576 EXPECT_EQ(block->total_len, exp_total_len);
577
578 // First block is a label.
579 struct filter_block* curr_block = block;
580 ASSERT_NE(curr_block, nullptr);
581 EXPECT_EQ(curr_block->len, 1U);
582 EXPECT_LBL(curr_block->instrs);
583
584 // Second block is a gt/ge comparison.
585 curr_block = curr_block->next;
586 EXPECT_GT_GE_COMP(curr_block);
587
588 // Third block is a jump and a label (end of AND group).
589 curr_block = curr_block->next;
590 ASSERT_NE(curr_block, nullptr);
591 EXPECT_GROUP_END(curr_block);
592
593 // Fourth block is SECCOMP_RET_KILL.
594 curr_block = curr_block->next;
595 ASSERT_NE(curr_block, nullptr);
596 EXPECT_KILL(curr_block);
597
598 // Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW.
599 curr_block = curr_block->next;
600 ASSERT_NE(curr_block, nullptr);
601 EXPECT_ALLOW(curr_block);
602
603 EXPECT_EQ(curr_block->next, nullptr);
604
605 free_block_list(block);
606 }
607 }
608 #endif
609
TEST_F(ArgFilterTest,arg0_mask)610 TEST_F(ArgFilterTest, arg0_mask) {
611 std::string fragment = "arg1 & O_RDWR";
612
613 struct filter_block* block =
614 test_compile_policy_line(&state_, nr_, fragment, id_, &labels_);
615
616 ASSERT_NE(block, nullptr);
617 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
618 EXPECT_EQ(block->total_len, exp_total_len);
619
620 /* First block is a label. */
621 struct filter_block *curr_block = block;
622 ASSERT_NE(curr_block, nullptr);
623 EXPECT_EQ(curr_block->len, 1U);
624 EXPECT_LBL(curr_block->instrs);
625
626 /* Second block is a comparison. */
627 curr_block = curr_block->next;
628 EXPECT_COMP(curr_block);
629
630 /* Third block is a jump and a label (end of AND group). */
631 curr_block = curr_block->next;
632 ASSERT_NE(curr_block, nullptr);
633 EXPECT_GROUP_END(curr_block);
634
635 /* Fourth block is SECCOMP_RET_KILL. */
636 curr_block = curr_block->next;
637 ASSERT_NE(curr_block, nullptr);
638 EXPECT_KILL(curr_block);
639
640 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
641 curr_block = curr_block->next;
642 ASSERT_NE(curr_block, nullptr);
643 EXPECT_ALLOW(curr_block);
644
645 EXPECT_EQ(curr_block->next, nullptr);
646
647 free_block_list(block);
648 }
649
TEST_F(ArgFilterTest,arg0_flag_set_inclusion)650 TEST_F(ArgFilterTest, arg0_flag_set_inclusion) {
651 std::string fragment = "arg0 in O_RDONLY|O_CREAT";
652
653 struct filter_block* block =
654 test_compile_policy_line(&state_, nr_, fragment, id_, &labels_);
655
656 ASSERT_NE(block, nullptr);
657 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
658 EXPECT_EQ(block->total_len, exp_total_len);
659
660 /* First block is a label. */
661 struct filter_block *curr_block = block;
662 ASSERT_NE(curr_block, nullptr);
663 EXPECT_EQ(curr_block->len, 1U);
664 EXPECT_LBL(curr_block->instrs);
665
666 /* Second block is a comparison. */
667 curr_block = curr_block->next;
668 ASSERT_NE(curr_block, nullptr);
669 EXPECT_COMP(curr_block);
670
671 /* Third block is a jump and a label (end of AND group). */
672 curr_block = curr_block->next;
673 ASSERT_NE(curr_block, nullptr);
674 EXPECT_GROUP_END(curr_block);
675
676 /* Fourth block is SECCOMP_RET_KILL. */
677 curr_block = curr_block->next;
678 ASSERT_NE(curr_block, nullptr);
679 EXPECT_KILL(curr_block);
680
681 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
682 curr_block = curr_block->next;
683 ASSERT_NE(curr_block, nullptr);
684 EXPECT_ALLOW(curr_block);
685
686 EXPECT_EQ(curr_block->next, nullptr);
687
688 free_block_list(block);
689 }
690
TEST_F(ArgFilterTest,arg0_eq_mask)691 TEST_F(ArgFilterTest, arg0_eq_mask) {
692 std::string fragment = "arg1 == O_WRONLY|O_CREAT";
693
694 struct filter_block* block =
695 test_compile_policy_line(&state_, nr_, fragment, id_, &labels_);
696
697 ASSERT_NE(block, nullptr);
698 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
699 EXPECT_EQ(block->total_len, exp_total_len);
700
701 /* First block is a label. */
702 struct filter_block *curr_block = block;
703 ASSERT_NE(curr_block, nullptr);
704 EXPECT_EQ(curr_block->len, 1U);
705 EXPECT_LBL(curr_block->instrs);
706
707 /* Second block is a comparison. */
708 curr_block = curr_block->next;
709 ASSERT_NE(curr_block, nullptr);
710 EXPECT_COMP(curr_block);
711 EXPECT_EQ(curr_block->instrs[BPF_ARG_COMP_LEN - 1].k,
712 (unsigned int)(O_WRONLY | O_CREAT));
713
714 /* Third block is a jump and a label (end of AND group). */
715 curr_block = curr_block->next;
716 ASSERT_NE(curr_block, nullptr);
717 EXPECT_GROUP_END(curr_block);
718
719 /* Fourth block is SECCOMP_RET_KILL. */
720 curr_block = curr_block->next;
721 ASSERT_NE(curr_block, nullptr);
722 EXPECT_KILL(curr_block);
723
724 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
725 curr_block = curr_block->next;
726 ASSERT_NE(curr_block, nullptr);
727 EXPECT_ALLOW(curr_block);
728
729 EXPECT_EQ(curr_block->next, nullptr);
730
731 free_block_list(block);
732 }
733
TEST_F(ArgFilterTest,and_or)734 TEST_F(ArgFilterTest, and_or) {
735 std::string fragment = "arg0 == 0 && arg1 == 0 || arg0 == 1";
736
737 struct filter_block* block =
738 test_compile_policy_line(&state_, nr_, fragment, id_, &labels_);
739 ASSERT_NE(block, nullptr);
740 size_t exp_total_len = 1 + 3 * (BPF_ARG_COMP_LEN + 1) + 2 + 2 + 1 + 2;
741 EXPECT_EQ(block->total_len, exp_total_len);
742
743 /* First block is a label. */
744 struct filter_block *curr_block = block;
745 ASSERT_NE(curr_block, nullptr);
746 EXPECT_EQ(curr_block->len, 1U);
747 EXPECT_LBL(curr_block->instrs);
748
749 /* Second block is a comparison ("arg0 == 0"). */
750 curr_block = curr_block->next;
751 ASSERT_NE(curr_block, nullptr);
752 EXPECT_COMP(curr_block);
753
754 /* Third block is a comparison ("arg1 == 0"). */
755 curr_block = curr_block->next;
756 ASSERT_NE(curr_block, nullptr);
757 EXPECT_COMP(curr_block);
758
759 /* Fourth block is a jump and a label (end of AND group). */
760 curr_block = curr_block->next;
761 ASSERT_NE(curr_block, nullptr);
762 EXPECT_GROUP_END(curr_block);
763
764 /* Fifth block is a comparison ("arg0 == 1"). */
765 curr_block = curr_block->next;
766 ASSERT_NE(curr_block, nullptr);
767 EXPECT_COMP(curr_block);
768
769 /* Sixth block is a jump and a label (end of AND group). */
770 curr_block = curr_block->next;
771 ASSERT_NE(curr_block, nullptr);
772 EXPECT_GROUP_END(curr_block);
773
774 /* Seventh block is SECCOMP_RET_KILL. */
775 curr_block = curr_block->next;
776 ASSERT_NE(curr_block, nullptr);
777 EXPECT_KILL(curr_block);
778
779 /* Eigth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
780 curr_block = curr_block->next;
781 ASSERT_NE(curr_block, nullptr);
782 EXPECT_ALLOW(curr_block);
783
784 EXPECT_EQ(curr_block->next, nullptr);
785
786 free_block_list(block);
787 }
788
TEST_F(ArgFilterTest,ret_errno)789 TEST_F(ArgFilterTest, ret_errno) {
790 std::string fragment = "arg0 == 0 || arg0 == 1; return 1";
791
792 struct filter_block* block =
793 test_compile_policy_line(&state_, nr_, fragment, id_, &labels_);
794 ASSERT_NE(block, nullptr);
795 size_t exp_total_len = 1 + 2 * (BPF_ARG_COMP_LEN + 1) + 2 + 2 + 1 + 2;
796 EXPECT_EQ(block->total_len, exp_total_len);
797
798 /* First block is a label. */
799 struct filter_block *curr_block = block;
800 ASSERT_NE(curr_block, nullptr);
801 EXPECT_EQ(curr_block->len, 1U);
802 EXPECT_LBL(curr_block->instrs);
803
804 /* Second block is a comparison ("arg0 == 0"). */
805 curr_block = curr_block->next;
806 ASSERT_NE(curr_block, nullptr);
807 EXPECT_COMP(curr_block);
808
809 /* Third block is a jump and a label (end of AND group). */
810 curr_block = curr_block->next;
811 ASSERT_NE(curr_block, nullptr);
812 EXPECT_GROUP_END(curr_block);
813
814 /* Fourth block is a comparison ("arg0 == 1"). */
815 curr_block = curr_block->next;
816 ASSERT_NE(curr_block, nullptr);
817 EXPECT_COMP(curr_block);
818
819 /* Fifth block is a jump and a label (end of AND group). */
820 curr_block = curr_block->next;
821 ASSERT_NE(curr_block, nullptr);
822 EXPECT_GROUP_END(curr_block);
823
824 /* Sixth block is SECCOMP_RET_ERRNO. */
825 curr_block = curr_block->next;
826 ASSERT_NE(curr_block, nullptr);
827 EXPECT_EQ(curr_block->len, 1U);
828 EXPECT_EQ_STMT(curr_block->instrs,
829 BPF_RET + BPF_K,
830 SECCOMP_RET_ERRNO | (1 & SECCOMP_RET_DATA));
831
832 /* Seventh block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
833 curr_block = curr_block->next;
834 ASSERT_NE(curr_block, nullptr);
835 EXPECT_ALLOW(curr_block);
836
837 EXPECT_EQ(curr_block->next, nullptr);
838
839 free_block_list(block);
840 }
841
TEST_F(ArgFilterTest,unconditional_errno)842 TEST_F(ArgFilterTest, unconditional_errno) {
843 std::string fragment = "return 1";
844
845 struct filter_block* block =
846 test_compile_policy_line(&state_, nr_, fragment, id_, &labels_);
847 ASSERT_NE(block, nullptr);
848 size_t exp_total_len = 2;
849 EXPECT_EQ(block->total_len, exp_total_len);
850
851 /* First block is a label. */
852 struct filter_block *curr_block = block;
853 ASSERT_NE(curr_block, nullptr);
854 EXPECT_EQ(curr_block->len, 1U);
855 EXPECT_LBL(curr_block->instrs);
856
857 /* Second block is SECCOMP_RET_ERRNO. */
858 curr_block = curr_block->next;
859 ASSERT_NE(curr_block, nullptr);
860 EXPECT_EQ(curr_block->len, 1U);
861 EXPECT_EQ_STMT(curr_block->instrs,
862 BPF_RET + BPF_K,
863 SECCOMP_RET_ERRNO | (1 & SECCOMP_RET_DATA));
864
865 EXPECT_EQ(curr_block->next, nullptr);
866
867 free_block_list(block);
868 }
869
TEST_F(ArgFilterTest,invalid_arg_token)870 TEST_F(ArgFilterTest, invalid_arg_token) {
871 std::string fragment = "org0 == 0";
872
873 struct filter_block* block =
874 test_compile_policy_line(&state_, nr_, fragment, id_, &labels_);
875 ASSERT_EQ(block, nullptr);
876 }
877
TEST_F(ArgFilterTest,invalid_arg_number)878 TEST_F(ArgFilterTest, invalid_arg_number) {
879 std::string fragment = "argnn == 0";
880
881 struct filter_block* block =
882 test_compile_policy_line(&state_, nr_, fragment, id_, &labels_);
883 ASSERT_EQ(block, nullptr);
884 }
885
TEST_F(ArgFilterTest,extra_chars_in_arg_token)886 TEST_F(ArgFilterTest, extra_chars_in_arg_token) {
887 std::string fragment = "arg0n == 0";
888
889 struct filter_block* block =
890 test_compile_policy_line(&state_, nr_, fragment, id_, &labels_);
891 ASSERT_EQ(block, nullptr);
892 }
893
TEST_F(ArgFilterTest,invalid_operator)894 TEST_F(ArgFilterTest, invalid_operator) {
895 std::string fragment = "arg0 invalidop 0";
896
897 struct filter_block* block =
898 test_compile_policy_line(&state_, nr_, fragment, id_, &labels_);
899 ASSERT_EQ(block, nullptr);
900 }
901
TEST_F(ArgFilterTest,invalid_constant)902 TEST_F(ArgFilterTest, invalid_constant) {
903 std::string fragment = "arg0 == INVALIDCONSTANT";
904
905 struct filter_block* block =
906 test_compile_policy_line(&state_, nr_, fragment, id_, &labels_);
907 ASSERT_EQ(block, nullptr);
908 }
909
TEST_F(ArgFilterTest,extra_tokens)910 TEST_F(ArgFilterTest, extra_tokens) {
911 std::string fragment = "arg0 == 0 EXTRATOKEN";
912
913 struct filter_block* block =
914 test_compile_policy_line(&state_, nr_, fragment, id_, &labels_);
915 ASSERT_EQ(block, nullptr);
916 }
917
TEST_F(ArgFilterTest,invalid_errno)918 TEST_F(ArgFilterTest, invalid_errno) {
919 std::string fragment = "arg0 == 0 && arg1 == 1; return errno";
920
921 struct filter_block* block =
922 test_compile_policy_line(&state_, nr_, fragment, id_, &labels_);
923 ASSERT_EQ(block, nullptr);
924 }
925
TEST_F(ArgFilterTest,log_no_ret_error)926 TEST_F(ArgFilterTest, log_no_ret_error) {
927 std::string fragment = "arg0 == 0";
928
929 struct filter_block* block =
930 test_compile_policy_line(&state_, nr_, fragment, id_, &labels_,
931 USE_RET_TRAP);
932
933 ASSERT_NE(block, nullptr);
934 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
935 EXPECT_EQ(block->total_len, exp_total_len);
936
937 /* First block is a label. */
938 struct filter_block *curr_block = block;
939 ASSERT_NE(curr_block, nullptr);
940 EXPECT_EQ(curr_block->len, 1U);
941 EXPECT_LBL(curr_block->instrs);
942
943 /* Second block is a comparison. */
944 curr_block = curr_block->next;
945 ASSERT_NE(curr_block, nullptr);
946 EXPECT_COMP(curr_block);
947
948 /* Third block is a jump and a label (end of AND group). */
949 curr_block = curr_block->next;
950 ASSERT_NE(curr_block, nullptr);
951 EXPECT_GROUP_END(curr_block);
952
953 /* Fourth block is SECCOMP_RET_TRAP, with no errno. */
954 curr_block = curr_block->next;
955 ASSERT_NE(curr_block, nullptr);
956 EXPECT_TRAP(curr_block);
957
958 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
959 curr_block = curr_block->next;
960 ASSERT_NE(curr_block, nullptr);
961 EXPECT_ALLOW(curr_block);
962
963 EXPECT_EQ(curr_block->next, nullptr);
964
965 free_block_list(block);
966 }
967
TEST_F(ArgFilterTest,log_bad_ret_error)968 TEST_F(ArgFilterTest, log_bad_ret_error) {
969 std::string fragment = "arg0 == 0; return";
970
971 struct filter_block* block =
972 test_compile_policy_line(&state_, nr_, fragment, id_, &labels_);
973 ASSERT_NE(block, nullptr);
974 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
975 EXPECT_EQ(block->total_len, exp_total_len);
976
977 /* First block is a label. */
978 struct filter_block *curr_block = block;
979 ASSERT_NE(curr_block, nullptr);
980 EXPECT_EQ(curr_block->len, 1U);
981 EXPECT_LBL(curr_block->instrs);
982
983 /* Second block is a comparison ("arg0 == 0"). */
984 curr_block = curr_block->next;
985 ASSERT_NE(curr_block, nullptr);
986 EXPECT_COMP(curr_block);
987
988 /* Third block is a jump and a label (end of AND group). */
989 curr_block = curr_block->next;
990 ASSERT_NE(curr_block, nullptr);
991 EXPECT_GROUP_END(curr_block);
992
993 /*
994 * Sixth block is NOT SECCOMP_RET_ERRNO, it should be SECCOMP_RET_KILL.
995 */
996 curr_block = curr_block->next;
997 ASSERT_NE(curr_block, nullptr);
998 EXPECT_KILL(curr_block);
999
1000 /* Seventh block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
1001 curr_block = curr_block->next;
1002 ASSERT_NE(curr_block, nullptr);
1003 EXPECT_ALLOW(curr_block);
1004
1005 EXPECT_EQ(curr_block->next, nullptr);
1006
1007 free_block_list(block);
1008 }
1009
TEST_F(ArgFilterTest,no_log_bad_ret_error)1010 TEST_F(ArgFilterTest, no_log_bad_ret_error) {
1011 std::string fragment = "arg0 == 0; return";
1012
1013 struct filter_block* block =
1014 test_compile_policy_line(&state_, nr_, fragment, id_, &labels_,
1015 USE_RET_TRAP);
1016 ASSERT_NE(block, nullptr);
1017 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
1018 EXPECT_EQ(block->total_len, exp_total_len);
1019
1020 /* First block is a label. */
1021 struct filter_block *curr_block = block;
1022 ASSERT_NE(curr_block, nullptr);
1023 EXPECT_EQ(curr_block->len, 1U);
1024 EXPECT_LBL(curr_block->instrs);
1025
1026 /* Second block is a comparison ("arg0 == 0"). */
1027 curr_block = curr_block->next;
1028 ASSERT_NE(curr_block, nullptr);
1029 EXPECT_COMP(curr_block);
1030
1031 /* Third block is a jump and a label (end of AND group). */
1032 curr_block = curr_block->next;
1033 ASSERT_NE(curr_block, nullptr);
1034 EXPECT_GROUP_END(curr_block);
1035
1036 /*
1037 * Sixth block is *not* SECCOMP_RET_ERRNO, it should be
1038 * SECCOMP_RET_TRAP.
1039 */
1040 curr_block = curr_block->next;
1041 ASSERT_NE(curr_block, nullptr);
1042 EXPECT_TRAP(curr_block);
1043
1044 /* Seventh block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
1045 curr_block = curr_block->next;
1046 ASSERT_NE(curr_block, nullptr);
1047 EXPECT_ALLOW(curr_block);
1048
1049 EXPECT_EQ(curr_block->next, nullptr);
1050
1051 free_block_list(block);
1052 }
1053
1054 namespace {
1055
write_policy_to_pipe(std::string policy)1056 FILE* write_policy_to_pipe(std::string policy) {
1057 int pipefd[2];
1058 if (pipe(pipefd) == -1) {
1059 pwarn("pipe(pipefd) failed");
1060 return nullptr;
1061 }
1062
1063 size_t len = policy.length();
1064 size_t i = 0;
1065 unsigned int attempts = 0;
1066 ssize_t ret;
1067 while (i < len) {
1068 ret = write(pipefd[1], policy.c_str() + i, len - i);
1069 if (ret == -1) {
1070 close(pipefd[0]);
1071 close(pipefd[1]);
1072 return nullptr;
1073 }
1074
1075 /* If we write 0 bytes three times in a row, fail. */
1076 if (ret == 0) {
1077 if (++attempts >= 3) {
1078 close(pipefd[0]);
1079 close(pipefd[1]);
1080 warn("write() returned 0 three times in a row");
1081 return nullptr;
1082 }
1083 continue;
1084 }
1085
1086 attempts = 0;
1087 i += (size_t)ret;
1088 }
1089
1090 close(pipefd[1]);
1091 return fdopen(pipefd[0], "r");
1092 }
1093
1094 class FileTest : public ::testing::Test {
1095 protected:
SetUp()1096 virtual void SetUp() {
1097 labels_.count = 0;
1098 head_ = new_filter_block();
1099 arg_blocks_ = nullptr;
1100 }
TearDown()1101 virtual void TearDown() {
1102 free_label_strings(&labels_);
1103 free_block_list(head_);
1104 free_block_list(arg_blocks_);
1105 }
1106 struct bpf_labels labels_;
1107 struct filter_block *head_;
1108 struct filter_block *arg_blocks_;
1109 };
1110
1111 } // namespace
1112
TEST_F(FileTest,malformed_policy)1113 TEST_F(FileTest, malformed_policy) {
1114 std::string policy =
1115 "malformed";
1116
1117 FILE* policy_file = write_policy_to_pipe(policy);
1118 ASSERT_NE(policy_file, nullptr);
1119 int res = test_compile_file("policy", policy_file, head_, &arg_blocks_,
1120 &labels_);
1121 fclose(policy_file);
1122
1123 /*
1124 * Policy is malformed, but process should not crash.
1125 */
1126 ASSERT_EQ(res, -1);
1127 }
1128
TEST_F(FileTest,double_free_on_compile_error)1129 TEST_F(FileTest, double_free_on_compile_error) {
1130 std::string policy =
1131 "read:arg0 == 0\n"
1132 "write:0";
1133
1134 FILE* policy_file = write_policy_to_pipe(policy);
1135 ASSERT_NE(policy_file, nullptr);
1136 int res = test_compile_file("policy", policy_file, head_, &arg_blocks_,
1137 &labels_);
1138 fclose(policy_file);
1139
1140 /*
1141 * Policy is malformed, but process should not crash.
1142 */
1143 ASSERT_EQ(res, -1);
1144 }
1145
TEST_F(FileTest,invalid_return)1146 TEST_F(FileTest, invalid_return) {
1147 std::string policy =
1148 "read:arg0 == 0; ;";
1149
1150 FILE* policy_file = write_policy_to_pipe(policy);
1151 ASSERT_NE(policy_file, nullptr);
1152 int res = test_compile_file("policy", policy_file, head_, &arg_blocks_,
1153 &labels_);
1154 fclose(policy_file);
1155
1156 /*
1157 * Policy is malformed, but process should not crash.
1158 */
1159 ASSERT_EQ(res, -1);
1160 }
1161
TEST_F(FileTest,seccomp_mode1)1162 TEST_F(FileTest, seccomp_mode1) {
1163 std::string policy =
1164 "read: 1\n"
1165 "write: 1\n"
1166 "rt_sigreturn: 1\n"
1167 "exit: 1\n";
1168
1169 FILE* policy_file = write_policy_to_pipe(policy);
1170 ASSERT_NE(policy_file, nullptr);
1171 int res = test_compile_file("policy", policy_file, head_, &arg_blocks_,
1172 &labels_);
1173 fclose(policy_file);
1174
1175 /*
1176 * Checks return value and that the blocks only allow expected syscalls.
1177 */
1178 ASSERT_EQ(res, 0);
1179 struct filter_block *curr_block = head_;
1180 ASSERT_NE(curr_block, nullptr);
1181 EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_read);
1182 curr_block = curr_block->next;
1183 ASSERT_NE(curr_block, nullptr);
1184 EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_write);
1185 curr_block = curr_block->next;
1186 ASSERT_NE(curr_block, nullptr);
1187 EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_rt_sigreturn);
1188 curr_block = curr_block->next;
1189 ASSERT_NE(curr_block, nullptr);
1190 EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_exit);
1191
1192 EXPECT_EQ(curr_block->next, nullptr);
1193 }
1194
TEST_F(FileTest,seccomp_read)1195 TEST_F(FileTest, seccomp_read) {
1196 std::string policy =
1197 "read: arg0 == 0\n"
1198 "write: 1\n"
1199 "rt_sigreturn: 1\n"
1200 "exit: 1\n";
1201
1202 const int LABEL_ID = 0;
1203
1204 FILE* policy_file = write_policy_to_pipe(policy);
1205 ASSERT_NE(policy_file, nullptr);
1206 int res = test_compile_file("policy", policy_file, head_, &arg_blocks_,
1207 &labels_);
1208 fclose(policy_file);
1209
1210 /*
1211 * Checks return value, that the blocks only allow expected syscalls, and that
1212 * labels between |head_| and |arg_blocks_| match.
1213 */
1214 ASSERT_EQ(res, 0);
1215 struct filter_block *curr_block = head_;
1216 ASSERT_NE(curr_block, nullptr);
1217 EXPECT_ALLOW_SYSCALL_ARGS(curr_block->instrs,
1218 __NR_read,
1219 LABEL_ID,
1220 JUMP_JT,
1221 JUMP_JF);
1222 curr_block = curr_block->next;
1223 ASSERT_NE(curr_block, nullptr);
1224 EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_write);
1225 curr_block = curr_block->next;
1226 ASSERT_NE(curr_block, nullptr);
1227 EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_rt_sigreturn);
1228 curr_block = curr_block->next;
1229 ASSERT_NE(curr_block, nullptr);
1230 EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_exit);
1231
1232 ASSERT_NE(arg_blocks_, nullptr);
1233 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
1234 EXPECT_EQ(arg_blocks_->total_len, exp_total_len);
1235
1236 /* First block is a label. */
1237 curr_block = arg_blocks_;
1238 ASSERT_NE(curr_block, nullptr);
1239 EXPECT_EQ(curr_block->len, 1U);
1240 EXPECT_ACTUAL_LBL(curr_block->instrs, LABEL_ID);
1241
1242 /* Second block is a comparison. */
1243 curr_block = curr_block->next;
1244 EXPECT_COMP(curr_block);
1245
1246 /* Third block is a jump and a label (end of AND group). */
1247 curr_block = curr_block->next;
1248 ASSERT_NE(curr_block, nullptr);
1249 EXPECT_GROUP_END(curr_block);
1250
1251 /* Fourth block is SECCOMP_RET_KILL. */
1252 curr_block = curr_block->next;
1253 ASSERT_NE(curr_block, nullptr);
1254 EXPECT_KILL(curr_block);
1255
1256 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
1257 curr_block = curr_block->next;
1258 ASSERT_NE(curr_block, nullptr);
1259 EXPECT_ALLOW(curr_block);
1260
1261 EXPECT_EQ(curr_block->next, nullptr);
1262 }
1263
TEST_F(FileTest,multiline)1264 TEST_F(FileTest, multiline) {
1265 std::string policy =
1266 "read:\\\n1\n"
1267 "openat:arg0 in\\\n5";
1268
1269 const int LABEL_ID = 0;
1270
1271 FILE* policy_file = write_policy_to_pipe(policy);
1272 ASSERT_NE(policy_file, nullptr);
1273 int res = test_compile_file("policy", policy_file, head_, &arg_blocks_,
1274 &labels_);
1275 fclose(policy_file);
1276
1277 /*
1278 * Policy should be valid.
1279 */
1280 ASSERT_EQ(res, 0);
1281
1282 /* First block is the read. */
1283 struct filter_block *curr_block = head_;
1284 ASSERT_NE(curr_block, nullptr);
1285 EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_read);
1286
1287 /* Second block is the open. */
1288 curr_block = curr_block->next;
1289 ASSERT_NE(curr_block, nullptr);
1290 EXPECT_ALLOW_SYSCALL_ARGS(curr_block->instrs,
1291 __NR_openat,
1292 LABEL_ID,
1293 JUMP_JT,
1294 JUMP_JF);
1295
1296 EXPECT_EQ(curr_block->next, nullptr);
1297 }
1298
TEST(FilterTest,seccomp_mode1)1299 TEST(FilterTest, seccomp_mode1) {
1300 struct sock_fprog actual;
1301 std::string policy =
1302 "read: 1\n"
1303 "write: 1\n"
1304 "rt_sigreturn: 1\n"
1305 "exit: 1\n";
1306
1307 FILE* policy_file = write_policy_to_pipe(policy);
1308 ASSERT_NE(policy_file, nullptr);
1309
1310 int res = test_compile_filter("policy", policy_file, &actual);
1311 fclose(policy_file);
1312
1313 /*
1314 * Checks return value, filter length, and that the filter
1315 * validates arch, loads syscall number, and
1316 * only allows expected syscalls.
1317 */
1318 ASSERT_EQ(res, 0);
1319 EXPECT_EQ(actual.len, 13);
1320 EXPECT_ARCH_VALIDATION(actual.filter);
1321 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
1322 BPF_LD + BPF_W + BPF_ABS,
1323 syscall_nr);
1324 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 1, __NR_read);
1325 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 3, __NR_write);
1326 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 5,
1327 __NR_rt_sigreturn);
1328 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 7, __NR_exit);
1329 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN + 9,
1330 BPF_RET + BPF_K,
1331 SECCOMP_RET_KILL);
1332
1333 free(actual.filter);
1334 }
1335
TEST(FilterTest,seccomp_mode1_trap)1336 TEST(FilterTest, seccomp_mode1_trap) {
1337 struct sock_fprog actual;
1338 std::string policy =
1339 "read: 1\n"
1340 "write: 1\n"
1341 "rt_sigreturn: 1\n"
1342 "exit: 1\n";
1343
1344 FILE* policy_file = write_policy_to_pipe(policy);
1345 ASSERT_NE(policy_file, nullptr);
1346
1347 int res = test_compile_filter("policy", policy_file, &actual, USE_RET_TRAP);
1348 fclose(policy_file);
1349
1350 /*
1351 * Checks return value, filter length, and that the filter
1352 * validates arch, loads syscall number, and
1353 * only allows expected syscalls.
1354 */
1355 ASSERT_EQ(res, 0);
1356 EXPECT_EQ(actual.len, 13);
1357 EXPECT_ARCH_VALIDATION(actual.filter);
1358 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
1359 BPF_LD+BPF_W+BPF_ABS, syscall_nr);
1360 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 1,
1361 __NR_read);
1362 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 3,
1363 __NR_write);
1364 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 5,
1365 __NR_rt_sigreturn);
1366 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 7,
1367 __NR_exit);
1368 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN + 9, BPF_RET+BPF_K,
1369 SECCOMP_RET_TRAP);
1370
1371 free(actual.filter);
1372 }
1373
TEST(FilterTest,seccomp_read_write)1374 TEST(FilterTest, seccomp_read_write) {
1375 struct sock_fprog actual;
1376 std::string policy =
1377 "read: arg0 == 0\n"
1378 "write: arg0 == 1 || arg0 == 2\n"
1379 "rt_sigreturn: 1\n"
1380 "exit: 1\n";
1381
1382 FILE* policy_file = write_policy_to_pipe(policy);
1383 ASSERT_NE(policy_file, nullptr);
1384
1385 int res = test_compile_filter("policy", policy_file, &actual);
1386 fclose(policy_file);
1387
1388 /*
1389 * Checks return value, filter length, and that the filter
1390 * validates arch, loads syscall number, and
1391 * only allows expected syscalls, jumping to correct arg filter
1392 * offsets.
1393 */
1394 ASSERT_EQ(res, 0);
1395 size_t exp_total_len = 27 + 3 * (BPF_ARG_COMP_LEN + 1);
1396 EXPECT_EQ(actual.len, exp_total_len);
1397
1398 EXPECT_ARCH_VALIDATION(actual.filter);
1399 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
1400 BPF_LD + BPF_W + BPF_ABS,
1401 syscall_nr);
1402 EXPECT_ALLOW_SYSCALL_ARGS(
1403 actual.filter + ARCH_VALIDATION_LEN + 1, __NR_read, 7, 0, 0);
1404 EXPECT_ALLOW_SYSCALL_ARGS(actual.filter + ARCH_VALIDATION_LEN + 3,
1405 __NR_write,
1406 12 + BPF_ARG_COMP_LEN,
1407 0,
1408 0);
1409 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 5,
1410 __NR_rt_sigreturn);
1411 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 7, __NR_exit);
1412 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN + 9,
1413 BPF_RET + BPF_K,
1414 SECCOMP_RET_KILL);
1415
1416 free(actual.filter);
1417 }
1418
TEST(FilterTest,misplaced_whitespace)1419 TEST(FilterTest, misplaced_whitespace) {
1420 struct sock_fprog actual;
1421 std::string policy = "read :1\n";
1422
1423 FILE* policy_file = write_policy_to_pipe(policy);
1424 ASSERT_NE(policy_file, nullptr);
1425
1426 int res = test_compile_filter("policy", policy_file, &actual);
1427 fclose(policy_file);
1428
1429 /* Checks return value and filter length. */
1430 ASSERT_EQ(res, 0);
1431 EXPECT_EQ(actual.len,
1432 ARCH_VALIDATION_LEN + 1 /* load syscall nr */ + ALLOW_SYSCALL_LEN +
1433 1 /* ret kill */);
1434 free(actual.filter);
1435 }
1436
TEST(FilterTest,missing_atom)1437 TEST(FilterTest, missing_atom) {
1438 struct sock_fprog actual;
1439 std::string policy = "open:\n";
1440
1441 FILE* policy_file = write_policy_to_pipe(policy);
1442 ASSERT_NE(policy_file, nullptr);
1443
1444 int res = test_compile_filter("policy", policy_file, &actual);
1445 fclose(policy_file);
1446 ASSERT_NE(res, 0);
1447 }
1448
TEST(FilterTest,whitespace_atom)1449 TEST(FilterTest, whitespace_atom) {
1450 struct sock_fprog actual;
1451 std::string policy = "open:\t \n";
1452
1453 FILE* policy_file = write_policy_to_pipe(policy);
1454 ASSERT_NE(policy_file, nullptr);
1455
1456 int res = test_compile_filter("policy", policy_file, &actual);
1457 fclose(policy_file);
1458 ASSERT_NE(res, 0);
1459 }
1460
TEST(FilterTest,invalid_name)1461 TEST(FilterTest, invalid_name) {
1462 struct sock_fprog actual;
1463 std::string policy = "notasyscall: 1\n";
1464
1465 FILE* policy_file = write_policy_to_pipe(policy);
1466 ASSERT_NE(policy_file, nullptr);
1467
1468 int res = test_compile_filter("policy", policy_file, &actual);
1469 fclose(policy_file);
1470 ASSERT_NE(res, 0);
1471 }
1472
TEST(FilterTest,invalid_arg)1473 TEST(FilterTest, invalid_arg) {
1474 struct sock_fprog actual;
1475 std::string policy = "open: argnn ==\n";
1476
1477 FILE* policy_file = write_policy_to_pipe(policy);
1478 ASSERT_NE(policy_file, nullptr);
1479
1480 int res = test_compile_filter("policy", policy_file, &actual);
1481 fclose(policy_file);
1482 ASSERT_NE(res, 0);
1483 }
1484
TEST(FilterTest,invalid_tokens)1485 TEST(FilterTest, invalid_tokens) {
1486 struct sock_fprog actual;
1487 std::string policy = "read: arg0 == 1 |||| arg0 == 2\n";
1488
1489 FILE* policy_file = write_policy_to_pipe(policy);
1490 ASSERT_NE(policy_file, nullptr);
1491
1492 int res = test_compile_filter("policy", policy_file, &actual);
1493 fclose(policy_file);
1494 ASSERT_NE(res, 0);
1495 }
1496
TEST(FilterTest,nonexistent)1497 TEST(FilterTest, nonexistent) {
1498 struct sock_fprog actual;
1499 int res = test_compile_filter("policy", nullptr, &actual);
1500 ASSERT_NE(res, 0);
1501 }
1502
TEST(FilterTest,log)1503 TEST(FilterTest, log) {
1504 struct sock_fprog actual;
1505 std::string policy =
1506 "read: 1\n"
1507 "write: 1\n"
1508 "rt_sigreturn: 1\n"
1509 "exit: 1\n";
1510
1511 FILE* policy_file = write_policy_to_pipe(policy);
1512 ASSERT_NE(policy_file, nullptr);
1513
1514 int res = test_compile_filter("policy", policy_file, &actual, USE_RET_TRAP,
1515 USE_LOGGING);
1516 fclose(policy_file);
1517
1518 size_t i;
1519 size_t index = 0;
1520 /*
1521 * Checks return value, filter length, and that the filter
1522 * validates arch, loads syscall number, only allows expected syscalls,
1523 * and returns TRAP on failure.
1524 * NOTE(jorgelo): the filter is longer since we add the syscalls needed
1525 * for logging.
1526 */
1527 ASSERT_EQ(res, 0);
1528 EXPECT_EQ(actual.len, 13 + 2 * log_syscalls_len);
1529 EXPECT_ARCH_VALIDATION(actual.filter);
1530 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
1531 BPF_LD + BPF_W + BPF_ABS,
1532 syscall_nr);
1533
1534 index = ARCH_VALIDATION_LEN + 1;
1535 for (i = 0; i < log_syscalls_len; i++)
1536 EXPECT_ALLOW_SYSCALL(actual.filter + (index + 2 * i),
1537 lookup_syscall(log_syscalls[i]));
1538
1539 index += 2 * log_syscalls_len;
1540
1541 EXPECT_ALLOW_SYSCALL(actual.filter + index, __NR_read);
1542 EXPECT_ALLOW_SYSCALL(actual.filter + index + 2, __NR_write);
1543 EXPECT_ALLOW_SYSCALL(actual.filter + index + 4, __NR_rt_sigreturn);
1544 EXPECT_ALLOW_SYSCALL(actual.filter + index + 6, __NR_exit);
1545 EXPECT_EQ_STMT(actual.filter + index + 8, BPF_RET + BPF_K, SECCOMP_RET_TRAP);
1546
1547 free(actual.filter);
1548 }
1549
TEST(FilterTest,allow_log_but_kill)1550 TEST(FilterTest, allow_log_but_kill) {
1551 struct sock_fprog actual;
1552 std::string policy =
1553 "read: 1\n"
1554 "write: 1\n"
1555 "rt_sigreturn: 1\n"
1556 "exit: 1\n";
1557
1558 FILE* policy_file = write_policy_to_pipe(policy);
1559 ASSERT_NE(policy_file, nullptr);
1560
1561 int res = test_compile_filter("policy", policy_file, &actual, USE_RET_KILL,
1562 USE_LOGGING);
1563 fclose(policy_file);
1564
1565 size_t i;
1566 size_t index = 0;
1567 /*
1568 * Checks return value, filter length, and that the filter
1569 * validates arch, loads syscall number, only allows expected syscalls,
1570 * and returns TRAP on failure.
1571 * NOTE(jorgelo): the filter is longer since we add the syscalls needed
1572 * for logging.
1573 */
1574 ASSERT_EQ(res, 0);
1575 EXPECT_EQ(actual.len, 13 + 2 * log_syscalls_len);
1576 EXPECT_ARCH_VALIDATION(actual.filter);
1577 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
1578 BPF_LD+BPF_W+BPF_ABS, syscall_nr);
1579
1580 index = ARCH_VALIDATION_LEN + 1;
1581 for (i = 0; i < log_syscalls_len; i++)
1582 EXPECT_ALLOW_SYSCALL(actual.filter + (index + 2 * i),
1583 lookup_syscall(log_syscalls[i]));
1584
1585 index += 2 * log_syscalls_len;
1586
1587 EXPECT_ALLOW_SYSCALL(actual.filter + index, __NR_read);
1588 EXPECT_ALLOW_SYSCALL(actual.filter + index + 2, __NR_write);
1589 EXPECT_ALLOW_SYSCALL(actual.filter + index + 4, __NR_rt_sigreturn);
1590 EXPECT_ALLOW_SYSCALL(actual.filter + index + 6, __NR_exit);
1591 EXPECT_EQ_STMT(actual.filter + index + 8, BPF_RET+BPF_K,
1592 SECCOMP_RET_KILL);
1593
1594 free(actual.filter);
1595 }
1596
TEST(FilterTest,include_invalid_token)1597 TEST(FilterTest, include_invalid_token) {
1598 struct sock_fprog actual;
1599 std::string invalid_token = "@unclude ./test/seccomp.policy\n";
1600
1601 FILE* policy_file = write_policy_to_pipe(invalid_token);
1602 ASSERT_NE(policy_file, nullptr);
1603 int res = test_compile_filter("policy", policy_file, &actual);
1604 fclose(policy_file);
1605 EXPECT_NE(res, 0);
1606 }
1607
TEST(FilterTest,include_no_space)1608 TEST(FilterTest, include_no_space) {
1609 struct sock_fprog actual;
1610 std::string no_space = "@includetest/seccomp.policy\n";
1611
1612 FILE* policy_file = write_policy_to_pipe(no_space);
1613 ASSERT_NE(policy_file, nullptr);
1614 int res = test_compile_filter("policy", policy_file, &actual);
1615 fclose(policy_file);
1616 EXPECT_NE(res, 0);
1617 }
1618
TEST(FilterTest,include_double_token)1619 TEST(FilterTest, include_double_token) {
1620 struct sock_fprog actual;
1621 std::string double_token = "@includeinclude ./test/seccomp.policy\n";
1622
1623 FILE* policy_file = write_policy_to_pipe(double_token);
1624 ASSERT_NE(policy_file, nullptr);
1625 int res = test_compile_filter("policy", policy_file, &actual);
1626 fclose(policy_file);
1627 EXPECT_NE(res, 0);
1628 }
1629
TEST(FilterTest,include_no_file)1630 TEST(FilterTest, include_no_file) {
1631 struct sock_fprog actual;
1632 std::string no_file = "@include\n";
1633
1634 FILE* policy_file = write_policy_to_pipe(no_file);
1635 ASSERT_NE(policy_file, nullptr);
1636 int res = test_compile_filter("policy", policy_file, &actual);
1637 fclose(policy_file);
1638 EXPECT_NE(res, 0);
1639 }
1640
TEST(FilterTest,include_space_no_file)1641 TEST(FilterTest, include_space_no_file) {
1642 struct sock_fprog actual;
1643 std::string space_no_file = "@include \n";
1644
1645 FILE* policy_file = write_policy_to_pipe(space_no_file);
1646 ASSERT_NE(policy_file, nullptr);
1647 int res = test_compile_filter("policy", policy_file, &actual);
1648 fclose(policy_file);
1649 EXPECT_NE(res, 0);
1650 }
1651
TEST(FilterTest,include_implicit_relative_path)1652 TEST(FilterTest, include_implicit_relative_path) {
1653 struct sock_fprog actual;
1654 std::string implicit_relative_path = "@include test/seccomp.policy\n";
1655
1656 FILE* policy_file = write_policy_to_pipe(implicit_relative_path);
1657 ASSERT_NE(policy_file, nullptr);
1658 int res = test_compile_filter("policy", policy_file, &actual);
1659 fclose(policy_file);
1660 EXPECT_NE(res, 0);
1661 }
1662
TEST(FilterTest,include_extra_text)1663 TEST(FilterTest, include_extra_text) {
1664 struct sock_fprog actual;
1665 std::string extra_text = "@include /some/file: sneaky comment\n";
1666
1667 FILE* policy_file = write_policy_to_pipe(extra_text);
1668 ASSERT_NE(policy_file, nullptr);
1669 int res = test_compile_filter("policy", policy_file, &actual);
1670 fclose(policy_file);
1671 EXPECT_NE(res, 0);
1672 }
1673
TEST(FilterTest,include_split_filename)1674 TEST(FilterTest, include_split_filename) {
1675 struct sock_fprog actual;
1676 std::string split_filename = "@include /some/file:colon.policy\n";
1677
1678 FILE* policy_file = write_policy_to_pipe(split_filename);
1679 ASSERT_NE(policy_file, nullptr);
1680 int res = test_compile_filter("policy", policy_file, &actual);
1681 fclose(policy_file);
1682 EXPECT_NE(res, 0);
1683 }
1684
TEST(FilterTest,include_nonexistent_file)1685 TEST(FilterTest, include_nonexistent_file) {
1686 struct sock_fprog actual;
1687 std::string include_policy = "@include ./nonexistent.policy\n";
1688
1689 FILE* policy_file = write_policy_to_pipe(include_policy);
1690 ASSERT_NE(policy_file, nullptr);
1691
1692 int res = test_compile_filter("policy", policy_file, &actual);
1693 fclose(policy_file);
1694
1695 ASSERT_NE(res, 0);
1696 }
1697
1698 // TODO(jorgelo): Android unit tests don't currently support data files.
1699 // Re-enable by creating a temporary policy file at runtime.
1700 #if !defined(__ANDROID__)
1701
TEST(FilterTest,include)1702 TEST(FilterTest, include) {
1703 struct sock_fprog compiled_plain;
1704 struct sock_fprog compiled_with_include;
1705
1706 std::string policy_plain =
1707 "read: 1\n"
1708 "write: 1\n"
1709 "rt_sigreturn: 1\n"
1710 "exit: 1\n";
1711
1712 FILE* file_plain = write_policy_to_pipe(policy_plain);
1713 ASSERT_NE(file_plain, nullptr);
1714 int res_plain = test_compile_filter("policy", file_plain, &compiled_plain,
1715 USE_RET_KILL);
1716 fclose(file_plain);
1717
1718 std::string policy_with_include =
1719 "@include " + source_path("test/seccomp.policy") + "\n";
1720
1721 FILE* file_with_include = write_policy_to_pipe(policy_with_include);
1722 ASSERT_NE(file_with_include, nullptr);
1723 int res_with_include =
1724 test_compile_filter("policy", file_with_include, &compiled_with_include,
1725 USE_RET_KILL);
1726 fclose(file_with_include);
1727
1728 /*
1729 * Checks that filter length is the same for a plain policy and an equivalent
1730 * policy with an @include statement. Also checks that the filter generated
1731 * from the policy with an @include statement is exactly the same as one
1732 * generated from a plain policy.
1733 */
1734 ASSERT_EQ(res_plain, 0);
1735 ASSERT_EQ(res_with_include, 0);
1736
1737 EXPECT_EQ(compiled_plain.len, 13);
1738 EXPECT_EQ(compiled_with_include.len, 13);
1739
1740 EXPECT_ARCH_VALIDATION(compiled_with_include.filter);
1741 EXPECT_EQ_STMT(compiled_with_include.filter + ARCH_VALIDATION_LEN,
1742 BPF_LD + BPF_W + BPF_ABS,
1743 syscall_nr);
1744 EXPECT_ALLOW_SYSCALL(compiled_with_include.filter + ARCH_VALIDATION_LEN + 1,
1745 __NR_read);
1746 EXPECT_ALLOW_SYSCALL(compiled_with_include.filter + ARCH_VALIDATION_LEN + 3,
1747 __NR_write);
1748 EXPECT_ALLOW_SYSCALL(compiled_with_include.filter + ARCH_VALIDATION_LEN + 5,
1749 __NR_rt_sigreturn);
1750 EXPECT_ALLOW_SYSCALL(compiled_with_include.filter + ARCH_VALIDATION_LEN + 7,
1751 __NR_exit);
1752 EXPECT_EQ_STMT(compiled_with_include.filter + ARCH_VALIDATION_LEN + 9,
1753 BPF_RET + BPF_K,
1754 SECCOMP_RET_KILL);
1755
1756 free(compiled_plain.filter);
1757 free(compiled_with_include.filter);
1758 }
1759
TEST(FilterTest,include_same_syscalls)1760 TEST(FilterTest, include_same_syscalls) {
1761 struct sock_fprog actual;
1762 std::string policy =
1763 "read: 1\n"
1764 "write: 1\n"
1765 "rt_sigreturn: 1\n"
1766 "exit: 1\n"
1767 "@include " + source_path("test/seccomp.policy") + "\n";
1768
1769 FILE* policy_file = write_policy_to_pipe(policy);
1770 ASSERT_NE(policy_file, nullptr);
1771
1772 int res = test_compile_filter("policy", policy_file, &actual);
1773 fclose(policy_file);
1774
1775 ASSERT_EQ(res, 0);
1776 EXPECT_EQ(actual.len,
1777 ARCH_VALIDATION_LEN + 1 /* load syscall nr */ +
1778 2 * 8 /* check syscalls twice */ + 1 /* filter return */);
1779 free(actual.filter);
1780 }
1781
TEST(FilterTest,include_two)1782 TEST(FilterTest, include_two) {
1783 struct sock_fprog actual;
1784 std::string policy =
1785 "@include " + source_path("test/seccomp.policy") + "\n" +
1786 "@include " + source_path("test/seccomp.policy") + "\n";
1787
1788 FILE* policy_file = write_policy_to_pipe(policy);
1789 ASSERT_NE(policy_file, nullptr);
1790
1791 int res = test_compile_filter("policy", policy_file, &actual);
1792 fclose(policy_file);
1793
1794 ASSERT_EQ(res, 0);
1795 EXPECT_EQ(actual.len,
1796 ARCH_VALIDATION_LEN + 1 /* load syscall nr */ +
1797 2 * 8 /* check syscalls twice */ + 1 /* filter return */);
1798 free(actual.filter);
1799 }
1800
TEST(FilterTest,include_invalid_policy)1801 TEST(FilterTest, include_invalid_policy) {
1802 struct sock_fprog actual;
1803 std::string policy =
1804 "read: 1\n"
1805 "write: 1\n"
1806 "rt_sigreturn: 1\n"
1807 "exit: 1\n"
1808 "@include ./test/invalid_syscall_name.policy\n";
1809
1810 FILE* policy_file = write_policy_to_pipe(policy);
1811 ASSERT_NE(policy_file, nullptr);
1812
1813 /* Ensure the included (invalid) policy file exists. */
1814 FILE* included_file = fopen(
1815 source_path("test/invalid_syscall_name.policy").c_str(), "re");
1816 ASSERT_NE(included_file, nullptr);
1817 fclose(included_file);
1818
1819 int res = test_compile_filter("policy", policy_file, &actual);
1820 fclose(policy_file);
1821
1822 ASSERT_NE(res, 0);
1823 }
1824
TEST(FilterTest,include_nested)1825 TEST(FilterTest, include_nested) {
1826 struct sock_fprog actual;
1827 std::string policy = "@include ./test/nested.policy\n";
1828
1829 FILE* policy_file = write_policy_to_pipe(policy);
1830 ASSERT_NE(policy_file, nullptr);
1831
1832 /* Ensure the policy file exists. */
1833 FILE* included_file = fopen(source_path("test/nested.policy").c_str(), "re");
1834 ASSERT_NE(included_file, nullptr);
1835 fclose(included_file);
1836
1837 int res = test_compile_filter("policy", policy_file, &actual);
1838 fclose(policy_file);
1839
1840 ASSERT_NE(res, 0);
1841 }
1842
1843 #endif // !__ANDROID__
1844
TEST(FilterTest,error_cleanup_leak)1845 TEST(FilterTest, error_cleanup_leak) {
1846 struct sock_fprog actual;
1847 std::string policy =
1848 "read:&&\n"
1849 "read:&&";
1850
1851 FILE* policy_file = write_policy_to_pipe(policy);
1852 ASSERT_NE(policy_file, nullptr);
1853 int res = test_compile_filter("policy", policy_file, &actual);
1854 fclose(policy_file);
1855
1856 /*
1857 * Policy is malformed, but process should not leak.
1858 */
1859 ASSERT_EQ(res, -1);
1860 }
1861