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