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