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