• 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,missing_atom)1172 TEST(FilterTest, missing_atom) {
1173   struct sock_fprog actual;
1174   const char* policy = "open:\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   ASSERT_NE(res, 0);
1182 }
1183 
TEST(FilterTest,whitespace_atom)1184 TEST(FilterTest, whitespace_atom) {
1185   struct sock_fprog actual;
1186   const char* policy = "open:\t    \n";
1187 
1188   FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
1189   ASSERT_NE(policy_file, nullptr);
1190 
1191   int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
1192   fclose(policy_file);
1193   ASSERT_NE(res, 0);
1194 }
1195 
TEST(FilterTest,invalid_name)1196 TEST(FilterTest, invalid_name) {
1197   struct sock_fprog actual;
1198   const char *policy = "notasyscall: 1\n";
1199 
1200   FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
1201   ASSERT_NE(policy_file, nullptr);
1202 
1203   int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
1204   fclose(policy_file);
1205   ASSERT_NE(res, 0);
1206 }
1207 
TEST(FilterTest,invalid_arg)1208 TEST(FilterTest, invalid_arg) {
1209   struct sock_fprog actual;
1210   const char *policy = "open: argnn ==\n";
1211 
1212   FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
1213   ASSERT_NE(policy_file, nullptr);
1214 
1215   int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
1216   fclose(policy_file);
1217   ASSERT_NE(res, 0);
1218 }
1219 
TEST(FilterTest,nonexistent)1220 TEST(FilterTest, nonexistent) {
1221   struct sock_fprog actual;
1222   int res = compile_filter(NULL, &actual, USE_RET_KILL, NO_LOGGING);
1223   ASSERT_NE(res, 0);
1224 }
1225 
TEST(FilterTest,log)1226 TEST(FilterTest, log) {
1227   struct sock_fprog actual;
1228   const char *policy =
1229       "read: 1\n"
1230       "write: 1\n"
1231       "rt_sigreturn: 1\n"
1232       "exit: 1\n";
1233 
1234   FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
1235   ASSERT_NE(policy_file, nullptr);
1236 
1237   int res = compile_filter(policy_file, &actual, USE_RET_TRAP, USE_LOGGING);
1238   fclose(policy_file);
1239 
1240   size_t i;
1241   size_t index = 0;
1242   /*
1243    * Checks return value, filter length, and that the filter
1244    * validates arch, loads syscall number, only allows expected syscalls,
1245    * and returns TRAP on failure.
1246    * NOTE(jorgelo): the filter is longer since we add the syscalls needed
1247    * for logging.
1248    */
1249   ASSERT_EQ(res, 0);
1250   EXPECT_EQ(actual.len, 13 + 2 * log_syscalls_len);
1251   EXPECT_ARCH_VALIDATION(actual.filter);
1252   EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
1253                  BPF_LD + BPF_W + BPF_ABS,
1254                  syscall_nr);
1255 
1256   index = ARCH_VALIDATION_LEN + 1;
1257   for (i = 0; i < log_syscalls_len; i++)
1258     EXPECT_ALLOW_SYSCALL(actual.filter + (index + 2 * i),
1259                          lookup_syscall(log_syscalls[i]));
1260 
1261   index += 2 * log_syscalls_len;
1262 
1263   EXPECT_ALLOW_SYSCALL(actual.filter + index, __NR_read);
1264   EXPECT_ALLOW_SYSCALL(actual.filter + index + 2, __NR_write);
1265   EXPECT_ALLOW_SYSCALL(actual.filter + index + 4, __NR_rt_sigreturn);
1266   EXPECT_ALLOW_SYSCALL(actual.filter + index + 6, __NR_exit);
1267   EXPECT_EQ_STMT(actual.filter + index + 8, BPF_RET + BPF_K, SECCOMP_RET_TRAP);
1268 
1269   free(actual.filter);
1270 }
1271 
TEST(FilterTest,allow_log_but_kill)1272 TEST(FilterTest, allow_log_but_kill) {
1273   struct sock_fprog actual;
1274   const char *policy =
1275     "read: 1\n"
1276     "write: 1\n"
1277     "rt_sigreturn: 1\n"
1278     "exit: 1\n";
1279 
1280   FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
1281   ASSERT_NE(policy_file, nullptr);
1282 
1283   int res = compile_filter(policy_file, &actual, USE_RET_KILL, USE_LOGGING);
1284   fclose(policy_file);
1285 
1286   size_t i;
1287   size_t index = 0;
1288   /*
1289    * Checks return value, filter length, and that the filter
1290    * validates arch, loads syscall number, only allows expected syscalls,
1291    * and returns TRAP on failure.
1292    * NOTE(jorgelo): the filter is longer since we add the syscalls needed
1293    * for logging.
1294    */
1295   ASSERT_EQ(res, 0);
1296   EXPECT_EQ(actual.len, 13 + 2 * log_syscalls_len);
1297   EXPECT_ARCH_VALIDATION(actual.filter);
1298   EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
1299       BPF_LD+BPF_W+BPF_ABS, syscall_nr);
1300 
1301   index = ARCH_VALIDATION_LEN + 1;
1302   for (i = 0; i < log_syscalls_len; i++)
1303     EXPECT_ALLOW_SYSCALL(actual.filter + (index + 2 * i),
1304              lookup_syscall(log_syscalls[i]));
1305 
1306   index += 2 * log_syscalls_len;
1307 
1308   EXPECT_ALLOW_SYSCALL(actual.filter + index, __NR_read);
1309   EXPECT_ALLOW_SYSCALL(actual.filter + index + 2, __NR_write);
1310   EXPECT_ALLOW_SYSCALL(actual.filter + index + 4, __NR_rt_sigreturn);
1311   EXPECT_ALLOW_SYSCALL(actual.filter + index + 6, __NR_exit);
1312   EXPECT_EQ_STMT(actual.filter + index + 8, BPF_RET+BPF_K,
1313       SECCOMP_RET_KILL);
1314 
1315   free(actual.filter);
1316 }
1317 
TEST(FilterTest,include_invalid_token)1318 TEST(FilterTest, include_invalid_token) {
1319   struct sock_fprog actual;
1320   const char *invalid_token = "@unclude ./test/seccomp.policy\n";
1321 
1322   FILE *policy_file =
1323       write_policy_to_pipe(invalid_token, strlen(invalid_token));
1324   ASSERT_NE(policy_file, nullptr);
1325   int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
1326   fclose(policy_file);
1327   EXPECT_NE(res, 0);
1328 }
1329 
TEST(FilterTest,include_no_space)1330 TEST(FilterTest, include_no_space) {
1331   struct sock_fprog actual;
1332   const char *no_space = "@includetest/seccomp.policy\n";
1333 
1334   FILE *policy_file = write_policy_to_pipe(no_space, strlen(no_space));
1335   ASSERT_NE(policy_file, nullptr);
1336   int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
1337   fclose(policy_file);
1338   EXPECT_NE(res, 0);
1339 }
1340 
TEST(FilterTest,include_double_token)1341 TEST(FilterTest, include_double_token) {
1342   struct sock_fprog actual;
1343   const char *double_token = "@includeinclude ./test/seccomp.policy\n";
1344 
1345   FILE *policy_file = write_policy_to_pipe(double_token, strlen(double_token));
1346   ASSERT_NE(policy_file, nullptr);
1347   int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
1348   fclose(policy_file);
1349   EXPECT_NE(res, 0);
1350 }
1351 
TEST(FilterTest,include_no_file)1352 TEST(FilterTest, include_no_file) {
1353   struct sock_fprog actual;
1354   const char *no_file = "@include\n";
1355 
1356   FILE *policy_file = write_policy_to_pipe(no_file, strlen(no_file));
1357   ASSERT_NE(policy_file, nullptr);
1358   int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
1359   fclose(policy_file);
1360   EXPECT_NE(res, 0);
1361 }
1362 
TEST(FilterTest,include_space_no_file)1363 TEST(FilterTest, include_space_no_file) {
1364   struct sock_fprog actual;
1365   const char *space_no_file = "@include \n";
1366 
1367   FILE *policy_file =
1368       write_policy_to_pipe(space_no_file, strlen(space_no_file));
1369   ASSERT_NE(policy_file, nullptr);
1370   int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
1371   fclose(policy_file);
1372   EXPECT_NE(res, 0);
1373 }
1374 
TEST(FilterTest,include_implicit_relative_path)1375 TEST(FilterTest, include_implicit_relative_path) {
1376   struct sock_fprog actual;
1377   const char *implicit_relative_path = "@include test/seccomp.policy\n";
1378 
1379   FILE *policy_file = write_policy_to_pipe(implicit_relative_path,
1380                                            strlen(implicit_relative_path));
1381   ASSERT_NE(policy_file, nullptr);
1382   int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
1383   fclose(policy_file);
1384   EXPECT_NE(res, 0);
1385 }
1386 
TEST(FilterTest,include_extra_text)1387 TEST(FilterTest, include_extra_text) {
1388   struct sock_fprog actual;
1389   const char *extra_text = "@include /some/file: sneaky comment\n";
1390 
1391   FILE *policy_file =
1392       write_policy_to_pipe(extra_text, strlen(extra_text));
1393   ASSERT_NE(policy_file, nullptr);
1394   int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
1395   fclose(policy_file);
1396   EXPECT_NE(res, 0);
1397 }
1398 
TEST(FilterTest,include_split_filename)1399 TEST(FilterTest, include_split_filename) {
1400   struct sock_fprog actual;
1401   const char *split_filename = "@include /some/file:colon.policy\n";
1402 
1403   FILE *policy_file =
1404       write_policy_to_pipe(split_filename, strlen(split_filename));
1405   ASSERT_NE(policy_file, nullptr);
1406   int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
1407   fclose(policy_file);
1408   EXPECT_NE(res, 0);
1409 }
1410 
TEST(FilterTest,include_nonexistent_file)1411 TEST(FilterTest, include_nonexistent_file) {
1412   struct sock_fprog actual;
1413   const char *include_policy = "@include ./nonexistent.policy\n";
1414 
1415   FILE *policy_file =
1416       write_policy_to_pipe(include_policy, strlen(include_policy));
1417   ASSERT_NE(policy_file, nullptr);
1418 
1419   int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
1420   fclose(policy_file);
1421 
1422   ASSERT_NE(res, 0);
1423 }
1424 
1425 // TODO(jorgelo): Android unit tests don't currently support data files.
1426 // Re-enable by creating a temporary policy file at runtime.
1427 #if !defined(__ANDROID__)
1428 
TEST(FilterTest,include)1429 TEST(FilterTest, include) {
1430   struct sock_fprog compiled_plain;
1431   struct sock_fprog compiled_with_include;
1432 
1433   const char *policy_plain =
1434       "read: 1\n"
1435       "write: 1\n"
1436       "rt_sigreturn: 1\n"
1437       "exit: 1\n";
1438 
1439   const char *policy_with_include = "@include ./test/seccomp.policy\n";
1440 
1441   FILE *file_plain = write_policy_to_pipe(policy_plain, strlen(policy_plain));
1442   ASSERT_NE(file_plain, nullptr);
1443   int res_plain =
1444       compile_filter(file_plain, &compiled_plain, USE_RET_KILL, NO_LOGGING);
1445   fclose(file_plain);
1446 
1447   FILE *file_with_include =
1448       write_policy_to_pipe(policy_with_include, strlen(policy_with_include));
1449   ASSERT_NE(file_with_include, nullptr);
1450   int res_with_include = compile_filter(
1451       file_with_include, &compiled_with_include, USE_RET_KILL, NO_LOGGING);
1452   fclose(file_with_include);
1453 
1454   /*
1455    * Checks that filter length is the same for a plain policy and an equivalent
1456    * policy with an @include statement. Also checks that the filter generated
1457    * from the policy with an @include statement is exactly the same as one
1458    * generated from a plain policy.
1459    */
1460   ASSERT_EQ(res_plain, 0);
1461   ASSERT_EQ(res_with_include, 0);
1462 
1463   EXPECT_EQ(compiled_plain.len, 13);
1464   EXPECT_EQ(compiled_with_include.len, 13);
1465 
1466   EXPECT_ARCH_VALIDATION(compiled_with_include.filter);
1467   EXPECT_EQ_STMT(compiled_with_include.filter + ARCH_VALIDATION_LEN,
1468                  BPF_LD + BPF_W + BPF_ABS,
1469                  syscall_nr);
1470   EXPECT_ALLOW_SYSCALL(compiled_with_include.filter + ARCH_VALIDATION_LEN + 1,
1471                        __NR_read);
1472   EXPECT_ALLOW_SYSCALL(compiled_with_include.filter + ARCH_VALIDATION_LEN + 3,
1473                        __NR_write);
1474   EXPECT_ALLOW_SYSCALL(compiled_with_include.filter + ARCH_VALIDATION_LEN + 5,
1475                        __NR_rt_sigreturn);
1476   EXPECT_ALLOW_SYSCALL(compiled_with_include.filter + ARCH_VALIDATION_LEN + 7,
1477                        __NR_exit);
1478   EXPECT_EQ_STMT(compiled_with_include.filter + ARCH_VALIDATION_LEN + 9,
1479                  BPF_RET + BPF_K,
1480                  SECCOMP_RET_KILL);
1481 
1482   free(compiled_plain.filter);
1483   free(compiled_with_include.filter);
1484 }
1485 
TEST(FilterTest,include_same_syscalls)1486 TEST(FilterTest, include_same_syscalls) {
1487   struct sock_fprog actual;
1488   const char *policy =
1489       "read: 1\n"
1490       "write: 1\n"
1491       "rt_sigreturn: 1\n"
1492       "exit: 1\n"
1493       "@include ./test/seccomp.policy\n";
1494 
1495   FILE *policy_file =
1496       write_policy_to_pipe(policy, strlen(policy));
1497   ASSERT_NE(policy_file, nullptr);
1498 
1499   int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
1500   fclose(policy_file);
1501 
1502   ASSERT_EQ(res, 0);
1503   EXPECT_EQ(actual.len,
1504             ARCH_VALIDATION_LEN + 1 /* load syscall nr */ +
1505                 2 * 8 /* check syscalls twice */ + 1 /* filter return */);
1506   free(actual.filter);
1507 }
1508 
TEST(FilterTest,include_invalid_policy)1509 TEST(FilterTest, include_invalid_policy) {
1510   struct sock_fprog actual;
1511   const char *policy =
1512       "read: 1\n"
1513       "write: 1\n"
1514       "rt_sigreturn: 1\n"
1515       "exit: 1\n"
1516       "@include ./test/invalid_syscall_name.policy\n";
1517 
1518   FILE *policy_file =
1519       write_policy_to_pipe(policy, strlen(policy));
1520   ASSERT_NE(policy_file, nullptr);
1521 
1522   /* Ensure the included (invalid) policy file exists. */
1523   FILE *included_file = fopen("./test/invalid_syscall_name.policy", "r");
1524   ASSERT_NE(included_file, nullptr);
1525   fclose(included_file);
1526 
1527   int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
1528   fclose(policy_file);
1529 
1530   ASSERT_NE(res, 0);
1531 }
1532 
TEST(FilterTest,include_nested)1533 TEST(FilterTest, include_nested) {
1534   struct sock_fprog actual;
1535   const char *policy = "@include ./test/nested.policy\n";
1536 
1537   FILE *policy_file =
1538       write_policy_to_pipe(policy, strlen(policy));
1539   ASSERT_NE(policy_file, nullptr);
1540 
1541   /* Ensure the policy file exists. */
1542   FILE *included_file = fopen("./test/nested.policy", "r");
1543   ASSERT_NE(included_file, nullptr);
1544   fclose(included_file);
1545 
1546   int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
1547   fclose(policy_file);
1548 
1549   ASSERT_NE(res, 0);
1550 }
1551 
1552 #endif  // !__ANDROID__
1553