blob: 98a1835181cfa1e6cb332d90a49f3642552beb77 [file] [log] [blame]
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001// 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>
Jorge Lucangeli Obes07459372016-10-19 15:33:31 -040023#include <string>
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -040024
25#include "bpf.h"
26#include "syscall_filter.h"
27#include "syscall_filter_unittest_macros.h"
28#include "util.h"
29
Jorge Lucangeli Obes07459372016-10-19 15:33:31 -040030TEST(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
47TEST(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
66TEST(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
74TEST(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
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -040093/* Test that setting one BPF instruction works. */
94TEST(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
106TEST(bpf, bpf_load_arg) {
107 struct sock_filter load_arg[BPF_LOAD_ARG_LEN];
Jorge Lucangeli Obes9bd316b2017-01-26 17:21:16 -0500108 const int argidx = 1;
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400109 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
123TEST(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
142TEST(bpf, bpf_comp_jset) {
143 struct sock_filter comp_jset[BPF_COMP_LEN];
Jorge Lucangeli Obesfd6f8e32016-10-12 11:19:28 -0400144 unsigned long mask = (1UL << (sizeof(unsigned long) * 8 - 1)) | O_WRONLY;
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400145 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)
Jorge Lucangeli Obesfd6f8e32016-10-12 11:19:28 -0400155 EXPECT_EQ_BLOCK(
156 &comp_jset[0], BPF_JMP + BPF_JSET + BPF_K, 0x80000000, jt + 2, 0);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400157 EXPECT_EQ_STMT(&comp_jset[1], BPF_LD + BPF_MEM, 0);
Jorge Lucangeli Obesfd6f8e32016-10-12 11:19:28 -0400158 EXPECT_EQ_BLOCK(&comp_jset[2], BPF_JMP + BPF_JSET + BPF_K, O_WRONLY, jt, jf);
159#endif
160}
161
162TEST(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);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400179#endif
180}
181
182TEST(bpf, bpf_arg_comp) {
183 struct sock_filter *arg_comp;
184 int op = EQ;
Jorge Lucangeli Obes9bd316b2017-01-26 17:21:16 -0500185 const int argidx = 1;
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400186 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
211TEST(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
220TEST(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
230TEST(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
Jorge Lucangeli Obes8cc9d4a2016-10-03 10:00:57 -0400241class BpfLabelTest : public ::testing::Test {
242 protected:
Jorge Lucangeli Obes9bd316b2017-01-26 17:21:16 -0500243 virtual void SetUp() { labels_.count = 0; }
Jorge Lucangeli Obes8cc9d4a2016-10-03 10:00:57 -0400244 virtual void TearDown() { free_label_strings(&labels_); }
245 struct bpf_labels labels_;
246};
247
248TEST_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
255TEST_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
266TEST_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
277TEST_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
286TEST_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
298TEST_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
309TEST_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
321TEST_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
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400337class ArgFilterTest : public ::testing::Test {
338 protected:
Jorge Lucangeli Obes9bd316b2017-01-26 17:21:16 -0500339 virtual void SetUp() { labels_.count = 0; }
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400340 virtual void TearDown() { free_label_strings(&labels_); }
341 struct bpf_labels labels_;
342};
343
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400344TEST_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_section(nr, fragment, id, &labels_, NO_LOGGING);
351 ASSERT_EQ(block, nullptr);
352}
353
354TEST_F(ArgFilterTest, no_comparison) {
355 const char* fragment = "arg0";
356 int nr = 1;
357 unsigned int id = 0;
358
359 struct filter_block* block =
360 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
361 ASSERT_EQ(block, nullptr);
362}
363
364TEST_F(ArgFilterTest, no_constant) {
365 const char* fragment = "arg0 ==";
366 int nr = 1;
367 unsigned int id = 0;
368
369 struct filter_block* block =
370 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
371 ASSERT_EQ(block, nullptr);
372}
373
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400374TEST_F(ArgFilterTest, arg0_equals) {
375 const char *fragment = "arg0 == 0";
376 int nr = 1;
377 unsigned int id = 0;
378 struct filter_block *block =
379 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
380
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400381 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400382 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
383 EXPECT_EQ(block->total_len, exp_total_len);
384
385 /* First block is a label. */
386 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400387 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400388 EXPECT_EQ(block->len, 1U);
389 EXPECT_LBL(curr_block->instrs);
390
391 /* Second block is a comparison. */
392 curr_block = block->next;
393 EXPECT_COMP(curr_block);
394
395 /* Third block is a jump and a label (end of AND group). */
396 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400397 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400398 EXPECT_GROUP_END(curr_block);
399
400 /* Fourth block is SECCOMP_RET_KILL. */
401 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400402 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400403 EXPECT_KILL(curr_block);
404
405 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
406 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400407 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400408 EXPECT_ALLOW(curr_block);
409
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400410 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400411
412 free_block_list(block);
413}
414
415TEST_F(ArgFilterTest, arg0_mask) {
416 const char *fragment = "arg1 & O_RDWR";
417 int nr = 1;
418 unsigned int id = 0;
419 struct filter_block *block =
420 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
421
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400422 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400423 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
424 EXPECT_EQ(block->total_len, exp_total_len);
425
426 /* First block is a label. */
427 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400428 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400429 EXPECT_EQ(block->len, 1U);
430 EXPECT_LBL(curr_block->instrs);
431
432 /* Second block is a comparison. */
433 curr_block = block->next;
434 EXPECT_COMP(curr_block);
435
436 /* Third block is a jump and a label (end of AND group). */
437 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400438 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400439 EXPECT_GROUP_END(curr_block);
440
441 /* Fourth block is SECCOMP_RET_KILL. */
442 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400443 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400444 EXPECT_KILL(curr_block);
445
446 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
447 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400448 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400449 EXPECT_ALLOW(curr_block);
450
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400451 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400452
453 free_block_list(block);
454}
455
Jorge Lucangeli Obesfd6f8e32016-10-12 11:19:28 -0400456TEST_F(ArgFilterTest, arg0_flag_set_inclusion) {
457 const char *fragment = "arg0 in O_RDONLY|O_CREAT";
458 int nr = 1;
459 unsigned int id = 0;
460 struct filter_block *block =
461 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
462
463 ASSERT_NE(block, nullptr);
464 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
465 EXPECT_EQ(block->total_len, exp_total_len);
466
467 /* First block is a label. */
468 struct filter_block *curr_block = block;
469 ASSERT_NE(curr_block, nullptr);
470 EXPECT_EQ(block->len, 1U);
471 EXPECT_LBL(curr_block->instrs);
472
473 /* Second block is a comparison. */
474 curr_block = block->next;
475 ASSERT_NE(curr_block, nullptr);
476 EXPECT_COMP(curr_block);
477
478 /* Third block is a jump and a label (end of AND group). */
479 curr_block = curr_block->next;
480 ASSERT_NE(curr_block, nullptr);
481 EXPECT_GROUP_END(curr_block);
482
483 /* Fourth block is SECCOMP_RET_KILL. */
484 curr_block = curr_block->next;
485 ASSERT_NE(curr_block, nullptr);
486 EXPECT_KILL(curr_block);
487
488 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
489 curr_block = curr_block->next;
490 ASSERT_NE(curr_block, nullptr);
491 EXPECT_ALLOW(curr_block);
492
493 EXPECT_EQ(curr_block->next, nullptr);
494
495 free_block_list(block);
496}
497
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400498TEST_F(ArgFilterTest, arg0_eq_mask) {
499 const char *fragment = "arg1 == O_WRONLY|O_CREAT";
500 int nr = 1;
501 unsigned int id = 0;
502
503 struct filter_block *block =
504 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
505
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400506 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400507 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
508 EXPECT_EQ(block->total_len, exp_total_len);
509
510 /* First block is a label. */
511 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400512 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400513 EXPECT_EQ(block->len, 1U);
514 EXPECT_LBL(curr_block->instrs);
515
516 /* Second block is a comparison. */
517 curr_block = block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400518 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400519 EXPECT_COMP(curr_block);
520 EXPECT_EQ(curr_block->instrs[BPF_ARG_COMP_LEN - 1].k,
521 (unsigned int)(O_WRONLY | O_CREAT));
522
523 /* Third block is a jump and a label (end of AND group). */
524 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400525 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400526 EXPECT_GROUP_END(curr_block);
527
528 /* Fourth block is SECCOMP_RET_KILL. */
529 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400530 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400531 EXPECT_KILL(curr_block);
532
533 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
534 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400535 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400536 EXPECT_ALLOW(curr_block);
537
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400538 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400539
540 free_block_list(block);
541}
542
543TEST_F(ArgFilterTest, and_or) {
544 const char *fragment = "arg0 == 0 && arg1 == 0 || arg0 == 1";
545 int nr = 1;
546 unsigned int id = 0;
547
548 struct filter_block *block =
549 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400550 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400551 size_t exp_total_len = 1 + 3 * (BPF_ARG_COMP_LEN + 1) + 2 + 2 + 1 + 2;
552 EXPECT_EQ(block->total_len, exp_total_len);
553
554 /* First block is a label. */
555 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400556 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400557 EXPECT_EQ(block->len, 1U);
558 EXPECT_LBL(curr_block->instrs);
559
560 /* Second block is a comparison ("arg0 == 0"). */
561 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400562 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400563 EXPECT_COMP(curr_block);
564
565 /* Third block is a comparison ("arg1 == 0"). */
566 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400567 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400568 EXPECT_COMP(curr_block);
569
570 /* Fourth block is a jump and a label (end of AND group). */
571 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400572 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400573 EXPECT_GROUP_END(curr_block);
574
575 /* Fifth block is a comparison ("arg0 == 1"). */
576 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400577 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400578 EXPECT_COMP(curr_block);
579
580 /* Sixth block is a jump and a label (end of AND group). */
581 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400582 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400583 EXPECT_GROUP_END(curr_block);
584
585 /* Seventh block is SECCOMP_RET_KILL. */
586 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400587 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400588 EXPECT_KILL(curr_block);
589
590 /* Eigth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
591 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400592 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400593 EXPECT_ALLOW(curr_block);
594
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400595 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400596
597 free_block_list(block);
598}
599
600TEST_F(ArgFilterTest, ret_errno) {
601 const char *fragment = "arg0 == 0 || arg0 == 1; return 1";
602 int nr = 1;
603 unsigned int id = 0;
604
605 struct filter_block *block =
606 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400607 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400608 size_t exp_total_len = 1 + 2 * (BPF_ARG_COMP_LEN + 1) + 2 + 2 + 1 + 2;
609 EXPECT_EQ(block->total_len, exp_total_len);
610
611 /* First block is a label. */
612 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400613 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400614 EXPECT_EQ(block->len, 1U);
615 EXPECT_LBL(curr_block->instrs);
616
617 /* Second block is a comparison ("arg0 == 0"). */
618 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400619 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400620 EXPECT_COMP(curr_block);
621
622 /* Third block is a jump and a label (end of AND group). */
623 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400624 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400625 EXPECT_GROUP_END(curr_block);
626
627 /* Fourth block is a comparison ("arg0 == 1"). */
628 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400629 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400630 EXPECT_COMP(curr_block);
631
632 /* Fifth block is a jump and a label (end of AND group). */
633 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400634 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400635 EXPECT_GROUP_END(curr_block);
636
637 /* Sixth block is SECCOMP_RET_ERRNO. */
638 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400639 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400640 EXPECT_EQ(curr_block->len, 1U);
641 EXPECT_EQ_STMT(curr_block->instrs,
642 BPF_RET + BPF_K,
643 SECCOMP_RET_ERRNO | (1 & SECCOMP_RET_DATA));
644
645 /* Seventh block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
646 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400647 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400648 EXPECT_ALLOW(curr_block);
649
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400650 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400651
652 free_block_list(block);
653}
654
655TEST_F(ArgFilterTest, unconditional_errno) {
656 const char *fragment = "return 1";
657 int nr = 1;
658 unsigned int id = 0;
659
660 struct filter_block *block =
661 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400662 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400663 size_t exp_total_len = 2;
664 EXPECT_EQ(block->total_len, exp_total_len);
665
666 /* First block is a label. */
667 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400668 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400669 EXPECT_EQ(block->len, 1U);
670 EXPECT_LBL(curr_block->instrs);
671
672 /* Second block is SECCOMP_RET_ERRNO. */
673 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400674 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400675 EXPECT_EQ(curr_block->len, 1U);
676 EXPECT_EQ_STMT(curr_block->instrs,
677 BPF_RET + BPF_K,
678 SECCOMP_RET_ERRNO | (1 & SECCOMP_RET_DATA));
679
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400680 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400681
682 free_block_list(block);
683}
684
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400685TEST_F(ArgFilterTest, invalid_arg_token) {
686 const char *fragment = "org0 == 0";
687 int nr = 1;
688 unsigned int id = 0;
689
690 struct filter_block *block =
691 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
692 ASSERT_EQ(block, nullptr);
693}
694
Jorge Lucangeli Obes53895402016-10-18 12:02:58 -0400695TEST_F(ArgFilterTest, invalid_arg_number) {
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400696 const char *fragment = "argnn == 0";
697 int nr = 1;
698 unsigned int id = 0;
699
700 struct filter_block *block =
701 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
Jorge Lucangeli Obes53895402016-10-18 12:02:58 -0400702 ASSERT_EQ(block, nullptr);
703}
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400704
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400705TEST_F(ArgFilterTest, extra_chars_in_arg_token) {
706 const char* fragment = "arg0n == 0";
707 int nr = 1;
708 unsigned int id = 0;
709
710 struct filter_block* block =
711 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
712 ASSERT_EQ(block, nullptr);
713}
714
715TEST_F(ArgFilterTest, invalid_operator) {
716 const char* fragment = "arg0 invalidop 0";
717 int nr = 1;
718 unsigned int id = 0;
719
720 struct filter_block* block =
721 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
722 ASSERT_EQ(block, nullptr);
723}
724
Jorge Lucangeli Obes53895402016-10-18 12:02:58 -0400725TEST_F(ArgFilterTest, invalid_constant) {
726 const char *fragment = "arg0 == INVALIDCONSTANT";
727 int nr = 1;
728 unsigned int id = 0;
729
730 struct filter_block* block =
731 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
732 ASSERT_EQ(block, nullptr);
733}
734
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400735TEST_F(ArgFilterTest, extra_tokens) {
736 const char* fragment = "arg0 == 0 EXTRATOKEN";
737 int nr = 1;
738 unsigned int id = 0;
739
740 struct filter_block* block =
741 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
742 ASSERT_EQ(block, nullptr);
743}
744
Jorge Lucangeli Obes53895402016-10-18 12:02:58 -0400745TEST_F(ArgFilterTest, invalid_errno) {
746 const char *fragment = "arg0 == 0 && arg1 == 1; return errno";
747 int nr = 1;
748 unsigned int id = 0;
749
750 struct filter_block *block =
751 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
752 ASSERT_EQ(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400753}
754
755TEST_F(ArgFilterTest, log_no_ret_error) {
756 const char *fragment = "arg0 == 0";
757 int nr = 1;
758 unsigned int id = 0;
759 struct filter_block *block =
760 compile_section(nr, fragment, id, &labels_, USE_LOGGING);
761
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400762 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400763 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
764 EXPECT_EQ(block->total_len, exp_total_len);
765
766 /* First block is a label. */
767 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400768 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400769 EXPECT_EQ(block->len, 1U);
770 EXPECT_LBL(curr_block->instrs);
771
772 /* Second block is a comparison. */
773 curr_block = block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400774 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400775 EXPECT_COMP(curr_block);
776
777 /* Third block is a jump and a label (end of AND group). */
778 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400779 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400780 EXPECT_GROUP_END(curr_block);
781
782 /* Fourth block is SECCOMP_RET_TRAP, with no errno. */
783 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400784 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400785 EXPECT_TRAP(curr_block);
786
787 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
788 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400789 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400790 EXPECT_ALLOW(curr_block);
791
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400792 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400793
794 free_block_list(block);
795}
796
797TEST_F(ArgFilterTest, log_bad_ret_error) {
798 const char *fragment = "arg0 == 0; return";
799 int nr = 1;
800 unsigned int id = 0;
801
802 struct filter_block *block =
803 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400804 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400805 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
806 EXPECT_EQ(block->total_len, exp_total_len);
807
808 /* First block is a label. */
809 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400810 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400811 EXPECT_EQ(block->len, 1U);
812 EXPECT_LBL(curr_block->instrs);
813
814 /* Second block is a comparison ("arg0 == 0"). */
815 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400816 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400817 EXPECT_COMP(curr_block);
818
819 /* Third block is a jump and a label (end of AND group). */
820 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400821 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400822 EXPECT_GROUP_END(curr_block);
823
824 /*
825 * Sixth block is NOT SECCOMP_RET_ERRNO, it should be SECCOMP_RET_KILL.
826 */
827 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400828 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400829 EXPECT_KILL(curr_block);
830
831 /* Seventh block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
832 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400833 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400834 EXPECT_ALLOW(curr_block);
835
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400836 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400837
838 free_block_list(block);
839}
840
841TEST_F(ArgFilterTest, no_log_bad_ret_error) {
842 const char *fragment = "arg0 == 0; return";
843 int nr = 1;
844 unsigned int id = 0;
845
846 struct filter_block *block =
847 compile_section(nr, fragment, id, &labels_, USE_LOGGING);
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400848 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400849 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
850 EXPECT_EQ(block->total_len, exp_total_len);
851
852 /* First block is a label. */
853 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400854 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400855 EXPECT_EQ(block->len, 1U);
856 EXPECT_LBL(curr_block->instrs);
857
858 /* Second block is a comparison ("arg0 == 0"). */
859 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400860 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400861 EXPECT_COMP(curr_block);
862
863 /* Third block is a jump and a label (end of AND group). */
864 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400865 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400866 EXPECT_GROUP_END(curr_block);
867
868 /*
869 * Sixth block is *not* SECCOMP_RET_ERRNO, it should be
870 * SECCOMP_RET_TRAP.
871 */
872 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400873 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400874 EXPECT_TRAP(curr_block);
875
876 /* Seventh block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
877 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400878 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400879 EXPECT_ALLOW(curr_block);
880
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400881 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400882
883 free_block_list(block);
884}
885
886FILE *write_policy_to_pipe(const char *policy, size_t len) {
887 int pipefd[2];
888 if (pipe(pipefd) == -1) {
889 pwarn("pipe(pipefd) failed");
890 return NULL;
891 }
892
893 size_t i = 0;
894 unsigned int attempts = 0;
895 ssize_t ret;
896 while (i < len) {
897 ret = write(pipefd[1], &policy[i], len - i);
898 if (ret == -1) {
899 close(pipefd[0]);
900 close(pipefd[1]);
901 return NULL;
902 }
903
904 /* If we write 0 bytes three times in a row, fail. */
905 if (ret == 0) {
906 if (++attempts >= 3) {
907 close(pipefd[0]);
908 close(pipefd[1]);
909 warn("write() returned 0 three times in a row");
910 return NULL;
911 }
912 continue;
913 }
914
915 attempts = 0;
916 i += (size_t)ret;
917 }
918
919 close(pipefd[1]);
920 return fdopen(pipefd[0], "r");
921}
922
923TEST(FilterTest, seccomp_mode1) {
924 struct sock_fprog actual;
925 const char *policy =
926 "read: 1\n"
927 "write: 1\n"
928 "rt_sigreturn: 1\n"
929 "exit: 1\n";
930
931 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400932 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400933
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -0400934 int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400935 fclose(policy_file);
936
937 /*
938 * Checks return value, filter length, and that the filter
939 * validates arch, loads syscall number, and
940 * only allows expected syscalls.
941 */
942 ASSERT_EQ(res, 0);
943 EXPECT_EQ(actual.len, 13);
944 EXPECT_ARCH_VALIDATION(actual.filter);
945 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
946 BPF_LD + BPF_W + BPF_ABS,
947 syscall_nr);
948 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 1, __NR_read);
949 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 3, __NR_write);
950 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 5,
951 __NR_rt_sigreturn);
952 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 7, __NR_exit);
953 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN + 9,
954 BPF_RET + BPF_K,
955 SECCOMP_RET_KILL);
956
957 free(actual.filter);
958}
959
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -0400960TEST(FilterTest, seccomp_mode1_trap) {
961 struct sock_fprog actual;
962 const char *policy =
963 "read: 1\n"
964 "write: 1\n"
965 "rt_sigreturn: 1\n"
966 "exit: 1\n";
967
968 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400969 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -0400970
971 int res = compile_filter(policy_file, &actual, USE_RET_TRAP, NO_LOGGING);
972 fclose(policy_file);
973
974 /*
975 * Checks return value, filter length, and that the filter
976 * validates arch, loads syscall number, and
977 * only allows expected syscalls.
978 */
979 ASSERT_EQ(res, 0);
980 EXPECT_EQ(actual.len, 13);
981 EXPECT_ARCH_VALIDATION(actual.filter);
982 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
983 BPF_LD+BPF_W+BPF_ABS, syscall_nr);
984 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 1,
985 __NR_read);
986 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 3,
987 __NR_write);
988 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 5,
989 __NR_rt_sigreturn);
990 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 7,
991 __NR_exit);
992 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN + 9, BPF_RET+BPF_K,
993 SECCOMP_RET_TRAP);
994
995 free(actual.filter);
996}
997
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400998TEST(FilterTest, seccomp_read_write) {
999 struct sock_fprog actual;
1000 const char *policy =
1001 "read: arg0 == 0\n"
1002 "write: arg0 == 1 || arg0 == 2\n"
1003 "rt_sigreturn: 1\n"
1004 "exit: 1\n";
1005
1006 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -04001007 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001008
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -04001009 int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001010 fclose(policy_file);
1011
1012 /*
1013 * Checks return value, filter length, and that the filter
1014 * validates arch, loads syscall number, and
1015 * only allows expected syscalls, jumping to correct arg filter
1016 * offsets.
1017 */
1018 ASSERT_EQ(res, 0);
1019 size_t exp_total_len = 27 + 3 * (BPF_ARG_COMP_LEN + 1);
1020 EXPECT_EQ(actual.len, exp_total_len);
1021
1022 EXPECT_ARCH_VALIDATION(actual.filter);
1023 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
1024 BPF_LD + BPF_W + BPF_ABS,
1025 syscall_nr);
1026 EXPECT_ALLOW_SYSCALL_ARGS(
1027 actual.filter + ARCH_VALIDATION_LEN + 1, __NR_read, 7, 0, 0);
1028 EXPECT_ALLOW_SYSCALL_ARGS(actual.filter + ARCH_VALIDATION_LEN + 3,
1029 __NR_write,
1030 12 + BPF_ARG_COMP_LEN,
1031 0,
1032 0);
1033 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 5,
1034 __NR_rt_sigreturn);
1035 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 7, __NR_exit);
1036 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN + 9,
1037 BPF_RET + BPF_K,
1038 SECCOMP_RET_KILL);
1039
1040 free(actual.filter);
1041}
1042
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -04001043TEST(FilterTest, missing_atom) {
1044 struct sock_fprog actual;
1045 const char* policy = "open:\n";
1046
1047 FILE* policy_file = write_policy_to_pipe(policy, strlen(policy));
1048 ASSERT_NE(policy_file, nullptr);
1049
1050 int res = compile_filter(policy_file, &actual, 0, NO_LOGGING);
1051 fclose(policy_file);
1052 ASSERT_NE(res, 0);
1053}
1054
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001055TEST(FilterTest, invalid_name) {
1056 struct sock_fprog actual;
1057 const char *policy = "notasyscall: 1\n";
1058
1059 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -04001060 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001061
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -04001062 int res = compile_filter(policy_file, &actual, 0, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001063 fclose(policy_file);
1064 ASSERT_NE(res, 0);
1065}
1066
1067TEST(FilterTest, invalid_arg) {
1068 struct sock_fprog actual;
1069 const char *policy = "open: argnn ==\n";
1070
1071 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -04001072 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001073
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -04001074 int res = compile_filter(policy_file, &actual, 0, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001075 fclose(policy_file);
1076 ASSERT_NE(res, 0);
1077}
1078
1079TEST(FilterTest, nonexistent) {
1080 struct sock_fprog actual;
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -04001081 int res = compile_filter(NULL, &actual, 0, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001082 ASSERT_NE(res, 0);
1083}
1084
1085TEST(FilterTest, log) {
1086 struct sock_fprog actual;
1087 const char *policy =
1088 "read: 1\n"
1089 "write: 1\n"
1090 "rt_sigreturn: 1\n"
1091 "exit: 1\n";
1092
1093 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -04001094 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001095
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -04001096 int res = compile_filter(policy_file, &actual, USE_RET_TRAP, USE_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001097 fclose(policy_file);
1098
1099 size_t i;
1100 size_t index = 0;
1101 /*
1102 * Checks return value, filter length, and that the filter
1103 * validates arch, loads syscall number, only allows expected syscalls,
1104 * and returns TRAP on failure.
1105 * NOTE(jorgelo): the filter is longer since we add the syscalls needed
1106 * for logging.
1107 */
1108 ASSERT_EQ(res, 0);
1109 EXPECT_EQ(actual.len, 13 + 2 * log_syscalls_len);
1110 EXPECT_ARCH_VALIDATION(actual.filter);
1111 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
1112 BPF_LD + BPF_W + BPF_ABS,
1113 syscall_nr);
1114
1115 index = ARCH_VALIDATION_LEN + 1;
1116 for (i = 0; i < log_syscalls_len; i++)
1117 EXPECT_ALLOW_SYSCALL(actual.filter + (index + 2 * i),
1118 lookup_syscall(log_syscalls[i]));
1119
1120 index += 2 * log_syscalls_len;
1121
1122 EXPECT_ALLOW_SYSCALL(actual.filter + index, __NR_read);
1123 EXPECT_ALLOW_SYSCALL(actual.filter + index + 2, __NR_write);
1124 EXPECT_ALLOW_SYSCALL(actual.filter + index + 4, __NR_rt_sigreturn);
1125 EXPECT_ALLOW_SYSCALL(actual.filter + index + 6, __NR_exit);
1126 EXPECT_EQ_STMT(actual.filter + index + 8, BPF_RET + BPF_K, SECCOMP_RET_TRAP);
1127
1128 free(actual.filter);
1129}
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -04001130
1131TEST(FilterTest, allow_log_but_kill) {
1132 struct sock_fprog actual;
1133 const char *policy =
1134 "read: 1\n"
1135 "write: 1\n"
1136 "rt_sigreturn: 1\n"
1137 "exit: 1\n";
1138
1139 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -04001140 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -04001141
1142 int res = compile_filter(policy_file, &actual, USE_RET_KILL, USE_LOGGING);
1143 fclose(policy_file);
1144
1145 size_t i;
1146 size_t index = 0;
1147 /*
1148 * Checks return value, filter length, and that the filter
1149 * validates arch, loads syscall number, only allows expected syscalls,
1150 * and returns TRAP on failure.
1151 * NOTE(jorgelo): the filter is longer since we add the syscalls needed
1152 * for logging.
1153 */
1154 ASSERT_EQ(res, 0);
1155 EXPECT_EQ(actual.len, 13 + 2 * log_syscalls_len);
1156 EXPECT_ARCH_VALIDATION(actual.filter);
1157 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
1158 BPF_LD+BPF_W+BPF_ABS, syscall_nr);
1159
1160 index = ARCH_VALIDATION_LEN + 1;
1161 for (i = 0; i < log_syscalls_len; i++)
1162 EXPECT_ALLOW_SYSCALL(actual.filter + (index + 2 * i),
1163 lookup_syscall(log_syscalls[i]));
1164
1165 index += 2 * log_syscalls_len;
1166
1167 EXPECT_ALLOW_SYSCALL(actual.filter + index, __NR_read);
1168 EXPECT_ALLOW_SYSCALL(actual.filter + index + 2, __NR_write);
1169 EXPECT_ALLOW_SYSCALL(actual.filter + index + 4, __NR_rt_sigreturn);
1170 EXPECT_ALLOW_SYSCALL(actual.filter + index + 6, __NR_exit);
1171 EXPECT_EQ_STMT(actual.filter + index + 8, BPF_RET+BPF_K,
1172 SECCOMP_RET_KILL);
1173
1174 free(actual.filter);
1175}