• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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