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