blob: 3b99b021c14380cd90ccea3db849aedda3cc0988 [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];
108 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
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;
185 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
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:
243 virtual void TearDown() { free_label_strings(&labels_); }
244 struct bpf_labels labels_;
245};
246
247TEST_F(BpfLabelTest, zero_length_filter) {
248 int res = bpf_resolve_jumps(&labels_, NULL, 0);
249
250 EXPECT_EQ(res, 0);
251 EXPECT_EQ(labels_.count, 0U);
252}
253
254TEST_F(BpfLabelTest, single_label) {
255 struct sock_filter test_label[1];
256
257 int id = bpf_label_id(&labels_, "test");
258 set_bpf_lbl(test_label, id);
259 int res = bpf_resolve_jumps(&labels_, test_label, 1);
260
261 EXPECT_EQ(res, 0);
262 EXPECT_EQ(labels_.count, 1U);
263}
264
265TEST_F(BpfLabelTest, repeated_label) {
266 struct sock_filter test_label[2];
267
268 int id = bpf_label_id(&labels_, "test");
269 set_bpf_lbl(&test_label[0], id);
270 set_bpf_lbl(&test_label[1], id);
271 int res = bpf_resolve_jumps(&labels_, test_label, 2);
272
273 EXPECT_EQ(res, -1);
274}
275
276TEST_F(BpfLabelTest, jump_with_no_label) {
277 struct sock_filter test_jump[1];
278
279 set_bpf_jump_lbl(test_jump, 14831);
280 int res = bpf_resolve_jumps(&labels_, test_jump, 1);
281
282 EXPECT_EQ(res, -1);
283}
284
285TEST_F(BpfLabelTest, jump_to_valid_label) {
286 struct sock_filter test_jump[2];
287
288 int id = bpf_label_id(&labels_, "test");
289 set_bpf_jump_lbl(&test_jump[0], id);
290 set_bpf_lbl(&test_jump[1], id);
291
292 int res = bpf_resolve_jumps(&labels_, test_jump, 2);
293 EXPECT_EQ(res, 0);
294 EXPECT_EQ(labels_.count, 1U);
295}
296
297TEST_F(BpfLabelTest, jump_to_invalid_label) {
298 struct sock_filter test_jump[2];
299
300 int id = bpf_label_id(&labels_, "test");
301 set_bpf_jump_lbl(&test_jump[0], id + 1);
302 set_bpf_lbl(&test_jump[1], id);
303
304 int res = bpf_resolve_jumps(&labels_, test_jump, 2);
305 EXPECT_EQ(res, -1);
306}
307
308TEST_F(BpfLabelTest, jump_to_unresolved_label) {
309 struct sock_filter test_jump[2];
310
311 int id = bpf_label_id(&labels_, "test");
312 /* Notice the order of the instructions is reversed. */
313 set_bpf_lbl(&test_jump[0], id);
314 set_bpf_jump_lbl(&test_jump[1], id);
315
316 int res = bpf_resolve_jumps(&labels_, test_jump, 2);
317 EXPECT_EQ(res, -1);
318}
319
320TEST_F(BpfLabelTest, too_many_labels) {
321 unsigned int i;
322 char label[20];
323
324 for (i = 0; i < BPF_LABELS_MAX; i++) {
325 snprintf(label, 20, "test%u", i);
326 (void) bpf_label_id(&labels_, label);
327 }
328 int id = bpf_label_id(&labels_, "test");
329
330 /* Insertion failed... */
331 EXPECT_EQ(id, -1);
332 /* ... because the label lookup table is full. */
333 EXPECT_EQ(labels_.count, BPF_LABELS_MAX);
334}
335
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400336class ArgFilterTest : public ::testing::Test {
337 protected:
338 virtual void TearDown() { free_label_strings(&labels_); }
339 struct bpf_labels labels_;
340};
341
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400342TEST_F(ArgFilterTest, empty_atom) {
343 const char* fragment = "";
344 int nr = 1;
345 unsigned int id = 0;
346
347 struct filter_block* block =
348 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
349 ASSERT_EQ(block, nullptr);
350}
351
352TEST_F(ArgFilterTest, no_comparison) {
353 const char* fragment = "arg0";
354 int nr = 1;
355 unsigned int id = 0;
356
357 struct filter_block* block =
358 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
359 ASSERT_EQ(block, nullptr);
360}
361
362TEST_F(ArgFilterTest, no_constant) {
363 const char* fragment = "arg0 ==";
364 int nr = 1;
365 unsigned int id = 0;
366
367 struct filter_block* block =
368 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
369 ASSERT_EQ(block, nullptr);
370}
371
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400372TEST_F(ArgFilterTest, arg0_equals) {
373 const char *fragment = "arg0 == 0";
374 int nr = 1;
375 unsigned int id = 0;
376 struct filter_block *block =
377 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
378
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400379 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400380 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
381 EXPECT_EQ(block->total_len, exp_total_len);
382
383 /* First block is a label. */
384 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400385 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400386 EXPECT_EQ(block->len, 1U);
387 EXPECT_LBL(curr_block->instrs);
388
389 /* Second block is a comparison. */
390 curr_block = block->next;
391 EXPECT_COMP(curr_block);
392
393 /* Third block is a jump and a label (end of AND group). */
394 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400395 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400396 EXPECT_GROUP_END(curr_block);
397
398 /* Fourth block is SECCOMP_RET_KILL. */
399 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400400 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400401 EXPECT_KILL(curr_block);
402
403 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
404 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400405 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400406 EXPECT_ALLOW(curr_block);
407
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400408 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400409
410 free_block_list(block);
411}
412
413TEST_F(ArgFilterTest, arg0_mask) {
414 const char *fragment = "arg1 & O_RDWR";
415 int nr = 1;
416 unsigned int id = 0;
417 struct filter_block *block =
418 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
419
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400420 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400421 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
422 EXPECT_EQ(block->total_len, exp_total_len);
423
424 /* First block is a label. */
425 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400426 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400427 EXPECT_EQ(block->len, 1U);
428 EXPECT_LBL(curr_block->instrs);
429
430 /* Second block is a comparison. */
431 curr_block = block->next;
432 EXPECT_COMP(curr_block);
433
434 /* Third block is a jump and a label (end of AND group). */
435 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400436 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400437 EXPECT_GROUP_END(curr_block);
438
439 /* Fourth block is SECCOMP_RET_KILL. */
440 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400441 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400442 EXPECT_KILL(curr_block);
443
444 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
445 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400446 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400447 EXPECT_ALLOW(curr_block);
448
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400449 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400450
451 free_block_list(block);
452}
453
Jorge Lucangeli Obesfd6f8e32016-10-12 11:19:28 -0400454TEST_F(ArgFilterTest, arg0_flag_set_inclusion) {
455 const char *fragment = "arg0 in O_RDONLY|O_CREAT";
456 int nr = 1;
457 unsigned int id = 0;
458 struct filter_block *block =
459 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
460
461 ASSERT_NE(block, nullptr);
462 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
463 EXPECT_EQ(block->total_len, exp_total_len);
464
465 /* First block is a label. */
466 struct filter_block *curr_block = block;
467 ASSERT_NE(curr_block, nullptr);
468 EXPECT_EQ(block->len, 1U);
469 EXPECT_LBL(curr_block->instrs);
470
471 /* Second block is a comparison. */
472 curr_block = block->next;
473 ASSERT_NE(curr_block, nullptr);
474 EXPECT_COMP(curr_block);
475
476 /* Third block is a jump and a label (end of AND group). */
477 curr_block = curr_block->next;
478 ASSERT_NE(curr_block, nullptr);
479 EXPECT_GROUP_END(curr_block);
480
481 /* Fourth block is SECCOMP_RET_KILL. */
482 curr_block = curr_block->next;
483 ASSERT_NE(curr_block, nullptr);
484 EXPECT_KILL(curr_block);
485
486 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
487 curr_block = curr_block->next;
488 ASSERT_NE(curr_block, nullptr);
489 EXPECT_ALLOW(curr_block);
490
491 EXPECT_EQ(curr_block->next, nullptr);
492
493 free_block_list(block);
494}
495
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400496TEST_F(ArgFilterTest, arg0_eq_mask) {
497 const char *fragment = "arg1 == O_WRONLY|O_CREAT";
498 int nr = 1;
499 unsigned int id = 0;
500
501 struct filter_block *block =
502 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
503
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400504 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400505 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
506 EXPECT_EQ(block->total_len, exp_total_len);
507
508 /* First block is a label. */
509 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400510 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400511 EXPECT_EQ(block->len, 1U);
512 EXPECT_LBL(curr_block->instrs);
513
514 /* Second block is a comparison. */
515 curr_block = block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400516 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400517 EXPECT_COMP(curr_block);
518 EXPECT_EQ(curr_block->instrs[BPF_ARG_COMP_LEN - 1].k,
519 (unsigned int)(O_WRONLY | O_CREAT));
520
521 /* Third block is a jump and a label (end of AND group). */
522 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400523 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400524 EXPECT_GROUP_END(curr_block);
525
526 /* Fourth block is SECCOMP_RET_KILL. */
527 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400528 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400529 EXPECT_KILL(curr_block);
530
531 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
532 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400533 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400534 EXPECT_ALLOW(curr_block);
535
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400536 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400537
538 free_block_list(block);
539}
540
541TEST_F(ArgFilterTest, and_or) {
542 const char *fragment = "arg0 == 0 && arg1 == 0 || arg0 == 1";
543 int nr = 1;
544 unsigned int id = 0;
545
546 struct filter_block *block =
547 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400548 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400549 size_t exp_total_len = 1 + 3 * (BPF_ARG_COMP_LEN + 1) + 2 + 2 + 1 + 2;
550 EXPECT_EQ(block->total_len, exp_total_len);
551
552 /* First block is a label. */
553 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400554 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400555 EXPECT_EQ(block->len, 1U);
556 EXPECT_LBL(curr_block->instrs);
557
558 /* Second block is a comparison ("arg0 == 0"). */
559 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400560 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400561 EXPECT_COMP(curr_block);
562
563 /* Third block is a comparison ("arg1 == 0"). */
564 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400565 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400566 EXPECT_COMP(curr_block);
567
568 /* Fourth block is a jump and a label (end of AND group). */
569 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400570 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400571 EXPECT_GROUP_END(curr_block);
572
573 /* Fifth block is a comparison ("arg0 == 1"). */
574 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400575 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400576 EXPECT_COMP(curr_block);
577
578 /* Sixth block is a jump and a label (end of AND group). */
579 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400580 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400581 EXPECT_GROUP_END(curr_block);
582
583 /* Seventh block is SECCOMP_RET_KILL. */
584 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400585 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400586 EXPECT_KILL(curr_block);
587
588 /* Eigth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
589 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400590 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400591 EXPECT_ALLOW(curr_block);
592
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400593 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400594
595 free_block_list(block);
596}
597
598TEST_F(ArgFilterTest, ret_errno) {
599 const char *fragment = "arg0 == 0 || arg0 == 1; return 1";
600 int nr = 1;
601 unsigned int id = 0;
602
603 struct filter_block *block =
604 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400605 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400606 size_t exp_total_len = 1 + 2 * (BPF_ARG_COMP_LEN + 1) + 2 + 2 + 1 + 2;
607 EXPECT_EQ(block->total_len, exp_total_len);
608
609 /* First block is a label. */
610 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400611 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400612 EXPECT_EQ(block->len, 1U);
613 EXPECT_LBL(curr_block->instrs);
614
615 /* Second block is a comparison ("arg0 == 0"). */
616 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400617 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400618 EXPECT_COMP(curr_block);
619
620 /* Third block is a jump and a label (end of AND group). */
621 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400622 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400623 EXPECT_GROUP_END(curr_block);
624
625 /* Fourth block is a comparison ("arg0 == 1"). */
626 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400627 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400628 EXPECT_COMP(curr_block);
629
630 /* Fifth block is a jump and a label (end of AND group). */
631 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400632 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400633 EXPECT_GROUP_END(curr_block);
634
635 /* Sixth block is SECCOMP_RET_ERRNO. */
636 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400637 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400638 EXPECT_EQ(curr_block->len, 1U);
639 EXPECT_EQ_STMT(curr_block->instrs,
640 BPF_RET + BPF_K,
641 SECCOMP_RET_ERRNO | (1 & SECCOMP_RET_DATA));
642
643 /* Seventh block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
644 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400645 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400646 EXPECT_ALLOW(curr_block);
647
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400648 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400649
650 free_block_list(block);
651}
652
653TEST_F(ArgFilterTest, unconditional_errno) {
654 const char *fragment = "return 1";
655 int nr = 1;
656 unsigned int id = 0;
657
658 struct filter_block *block =
659 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400660 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400661 size_t exp_total_len = 2;
662 EXPECT_EQ(block->total_len, exp_total_len);
663
664 /* First block is a label. */
665 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400666 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400667 EXPECT_EQ(block->len, 1U);
668 EXPECT_LBL(curr_block->instrs);
669
670 /* Second block is SECCOMP_RET_ERRNO. */
671 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400672 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400673 EXPECT_EQ(curr_block->len, 1U);
674 EXPECT_EQ_STMT(curr_block->instrs,
675 BPF_RET + BPF_K,
676 SECCOMP_RET_ERRNO | (1 & SECCOMP_RET_DATA));
677
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400678 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400679
680 free_block_list(block);
681}
682
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400683TEST_F(ArgFilterTest, invalid_arg_token) {
684 const char *fragment = "org0 == 0";
685 int nr = 1;
686 unsigned int id = 0;
687
688 struct filter_block *block =
689 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
690 ASSERT_EQ(block, nullptr);
691}
692
Jorge Lucangeli Obes53895402016-10-18 12:02:58 -0400693TEST_F(ArgFilterTest, invalid_arg_number) {
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400694 const char *fragment = "argnn == 0";
695 int nr = 1;
696 unsigned int id = 0;
697
698 struct filter_block *block =
699 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
Jorge Lucangeli Obes53895402016-10-18 12:02:58 -0400700 ASSERT_EQ(block, nullptr);
701}
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400702
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400703TEST_F(ArgFilterTest, extra_chars_in_arg_token) {
704 const char* fragment = "arg0n == 0";
705 int nr = 1;
706 unsigned int id = 0;
707
708 struct filter_block* block =
709 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
710 ASSERT_EQ(block, nullptr);
711}
712
713TEST_F(ArgFilterTest, invalid_operator) {
714 const char* fragment = "arg0 invalidop 0";
715 int nr = 1;
716 unsigned int id = 0;
717
718 struct filter_block* block =
719 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
720 ASSERT_EQ(block, nullptr);
721}
722
Jorge Lucangeli Obes53895402016-10-18 12:02:58 -0400723TEST_F(ArgFilterTest, invalid_constant) {
724 const char *fragment = "arg0 == INVALIDCONSTANT";
725 int nr = 1;
726 unsigned int id = 0;
727
728 struct filter_block* block =
729 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
730 ASSERT_EQ(block, nullptr);
731}
732
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400733TEST_F(ArgFilterTest, extra_tokens) {
734 const char* fragment = "arg0 == 0 EXTRATOKEN";
735 int nr = 1;
736 unsigned int id = 0;
737
738 struct filter_block* block =
739 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
740 ASSERT_EQ(block, nullptr);
741}
742
Jorge Lucangeli Obes53895402016-10-18 12:02:58 -0400743TEST_F(ArgFilterTest, invalid_errno) {
744 const char *fragment = "arg0 == 0 && arg1 == 1; return errno";
745 int nr = 1;
746 unsigned int id = 0;
747
748 struct filter_block *block =
749 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
750 ASSERT_EQ(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400751}
752
753TEST_F(ArgFilterTest, log_no_ret_error) {
754 const char *fragment = "arg0 == 0";
755 int nr = 1;
756 unsigned int id = 0;
757 struct filter_block *block =
758 compile_section(nr, fragment, id, &labels_, USE_LOGGING);
759
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400760 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400761 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
762 EXPECT_EQ(block->total_len, exp_total_len);
763
764 /* First block is a label. */
765 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400766 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400767 EXPECT_EQ(block->len, 1U);
768 EXPECT_LBL(curr_block->instrs);
769
770 /* Second block is a comparison. */
771 curr_block = block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400772 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400773 EXPECT_COMP(curr_block);
774
775 /* Third block is a jump and a label (end of AND group). */
776 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400777 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400778 EXPECT_GROUP_END(curr_block);
779
780 /* Fourth block is SECCOMP_RET_TRAP, with no errno. */
781 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400782 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400783 EXPECT_TRAP(curr_block);
784
785 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
786 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400787 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400788 EXPECT_ALLOW(curr_block);
789
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400790 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400791
792 free_block_list(block);
793}
794
795TEST_F(ArgFilterTest, log_bad_ret_error) {
796 const char *fragment = "arg0 == 0; return";
797 int nr = 1;
798 unsigned int id = 0;
799
800 struct filter_block *block =
801 compile_section(nr, fragment, id, &labels_, NO_LOGGING);
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400802 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400803 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
804 EXPECT_EQ(block->total_len, exp_total_len);
805
806 /* First block is a label. */
807 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400808 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400809 EXPECT_EQ(block->len, 1U);
810 EXPECT_LBL(curr_block->instrs);
811
812 /* Second block is a comparison ("arg0 == 0"). */
813 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400814 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400815 EXPECT_COMP(curr_block);
816
817 /* Third block is a jump and a label (end of AND group). */
818 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400819 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400820 EXPECT_GROUP_END(curr_block);
821
822 /*
823 * Sixth block is NOT SECCOMP_RET_ERRNO, it should be SECCOMP_RET_KILL.
824 */
825 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400826 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400827 EXPECT_KILL(curr_block);
828
829 /* Seventh block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
830 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400831 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400832 EXPECT_ALLOW(curr_block);
833
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400834 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400835
836 free_block_list(block);
837}
838
839TEST_F(ArgFilterTest, no_log_bad_ret_error) {
840 const char *fragment = "arg0 == 0; return";
841 int nr = 1;
842 unsigned int id = 0;
843
844 struct filter_block *block =
845 compile_section(nr, fragment, id, &labels_, USE_LOGGING);
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400846 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400847 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
848 EXPECT_EQ(block->total_len, exp_total_len);
849
850 /* First block is a label. */
851 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400852 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400853 EXPECT_EQ(block->len, 1U);
854 EXPECT_LBL(curr_block->instrs);
855
856 /* Second block is a comparison ("arg0 == 0"). */
857 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400858 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400859 EXPECT_COMP(curr_block);
860
861 /* Third block is a jump and a label (end of AND group). */
862 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400863 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400864 EXPECT_GROUP_END(curr_block);
865
866 /*
867 * Sixth block is *not* SECCOMP_RET_ERRNO, it should be
868 * SECCOMP_RET_TRAP.
869 */
870 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400871 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400872 EXPECT_TRAP(curr_block);
873
874 /* Seventh block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
875 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400876 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400877 EXPECT_ALLOW(curr_block);
878
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400879 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400880
881 free_block_list(block);
882}
883
884FILE *write_policy_to_pipe(const char *policy, size_t len) {
885 int pipefd[2];
886 if (pipe(pipefd) == -1) {
887 pwarn("pipe(pipefd) failed");
888 return NULL;
889 }
890
891 size_t i = 0;
892 unsigned int attempts = 0;
893 ssize_t ret;
894 while (i < len) {
895 ret = write(pipefd[1], &policy[i], len - i);
896 if (ret == -1) {
897 close(pipefd[0]);
898 close(pipefd[1]);
899 return NULL;
900 }
901
902 /* If we write 0 bytes three times in a row, fail. */
903 if (ret == 0) {
904 if (++attempts >= 3) {
905 close(pipefd[0]);
906 close(pipefd[1]);
907 warn("write() returned 0 three times in a row");
908 return NULL;
909 }
910 continue;
911 }
912
913 attempts = 0;
914 i += (size_t)ret;
915 }
916
917 close(pipefd[1]);
918 return fdopen(pipefd[0], "r");
919}
920
921TEST(FilterTest, seccomp_mode1) {
922 struct sock_fprog actual;
923 const char *policy =
924 "read: 1\n"
925 "write: 1\n"
926 "rt_sigreturn: 1\n"
927 "exit: 1\n";
928
929 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400930 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400931
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -0400932 int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400933 fclose(policy_file);
934
935 /*
936 * Checks return value, filter length, and that the filter
937 * validates arch, loads syscall number, and
938 * only allows expected syscalls.
939 */
940 ASSERT_EQ(res, 0);
941 EXPECT_EQ(actual.len, 13);
942 EXPECT_ARCH_VALIDATION(actual.filter);
943 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
944 BPF_LD + BPF_W + BPF_ABS,
945 syscall_nr);
946 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 1, __NR_read);
947 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 3, __NR_write);
948 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 5,
949 __NR_rt_sigreturn);
950 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 7, __NR_exit);
951 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN + 9,
952 BPF_RET + BPF_K,
953 SECCOMP_RET_KILL);
954
955 free(actual.filter);
956}
957
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -0400958TEST(FilterTest, seccomp_mode1_trap) {
959 struct sock_fprog actual;
960 const char *policy =
961 "read: 1\n"
962 "write: 1\n"
963 "rt_sigreturn: 1\n"
964 "exit: 1\n";
965
966 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400967 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -0400968
969 int res = compile_filter(policy_file, &actual, USE_RET_TRAP, NO_LOGGING);
970 fclose(policy_file);
971
972 /*
973 * Checks return value, filter length, and that the filter
974 * validates arch, loads syscall number, and
975 * only allows expected syscalls.
976 */
977 ASSERT_EQ(res, 0);
978 EXPECT_EQ(actual.len, 13);
979 EXPECT_ARCH_VALIDATION(actual.filter);
980 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
981 BPF_LD+BPF_W+BPF_ABS, syscall_nr);
982 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 1,
983 __NR_read);
984 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 3,
985 __NR_write);
986 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 5,
987 __NR_rt_sigreturn);
988 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 7,
989 __NR_exit);
990 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN + 9, BPF_RET+BPF_K,
991 SECCOMP_RET_TRAP);
992
993 free(actual.filter);
994}
995
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400996TEST(FilterTest, seccomp_read_write) {
997 struct sock_fprog actual;
998 const char *policy =
999 "read: arg0 == 0\n"
1000 "write: arg0 == 1 || arg0 == 2\n"
1001 "rt_sigreturn: 1\n"
1002 "exit: 1\n";
1003
1004 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -04001005 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001006
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -04001007 int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001008 fclose(policy_file);
1009
1010 /*
1011 * Checks return value, filter length, and that the filter
1012 * validates arch, loads syscall number, and
1013 * only allows expected syscalls, jumping to correct arg filter
1014 * offsets.
1015 */
1016 ASSERT_EQ(res, 0);
1017 size_t exp_total_len = 27 + 3 * (BPF_ARG_COMP_LEN + 1);
1018 EXPECT_EQ(actual.len, exp_total_len);
1019
1020 EXPECT_ARCH_VALIDATION(actual.filter);
1021 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
1022 BPF_LD + BPF_W + BPF_ABS,
1023 syscall_nr);
1024 EXPECT_ALLOW_SYSCALL_ARGS(
1025 actual.filter + ARCH_VALIDATION_LEN + 1, __NR_read, 7, 0, 0);
1026 EXPECT_ALLOW_SYSCALL_ARGS(actual.filter + ARCH_VALIDATION_LEN + 3,
1027 __NR_write,
1028 12 + BPF_ARG_COMP_LEN,
1029 0,
1030 0);
1031 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 5,
1032 __NR_rt_sigreturn);
1033 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 7, __NR_exit);
1034 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN + 9,
1035 BPF_RET + BPF_K,
1036 SECCOMP_RET_KILL);
1037
1038 free(actual.filter);
1039}
1040
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -04001041TEST(FilterTest, missing_atom) {
1042 struct sock_fprog actual;
1043 const char* policy = "open:\n";
1044
1045 FILE* policy_file = write_policy_to_pipe(policy, strlen(policy));
1046 ASSERT_NE(policy_file, nullptr);
1047
1048 int res = compile_filter(policy_file, &actual, 0, NO_LOGGING);
1049 fclose(policy_file);
1050 ASSERT_NE(res, 0);
1051}
1052
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001053TEST(FilterTest, invalid_name) {
1054 struct sock_fprog actual;
1055 const char *policy = "notasyscall: 1\n";
1056
1057 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -04001058 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001059
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -04001060 int res = compile_filter(policy_file, &actual, 0, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001061 fclose(policy_file);
1062 ASSERT_NE(res, 0);
1063}
1064
1065TEST(FilterTest, invalid_arg) {
1066 struct sock_fprog actual;
1067 const char *policy = "open: argnn ==\n";
1068
1069 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -04001070 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001071
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -04001072 int res = compile_filter(policy_file, &actual, 0, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001073 fclose(policy_file);
1074 ASSERT_NE(res, 0);
1075}
1076
1077TEST(FilterTest, nonexistent) {
1078 struct sock_fprog actual;
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -04001079 int res = compile_filter(NULL, &actual, 0, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001080 ASSERT_NE(res, 0);
1081}
1082
1083TEST(FilterTest, log) {
1084 struct sock_fprog actual;
1085 const char *policy =
1086 "read: 1\n"
1087 "write: 1\n"
1088 "rt_sigreturn: 1\n"
1089 "exit: 1\n";
1090
1091 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -04001092 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001093
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -04001094 int res = compile_filter(policy_file, &actual, USE_RET_TRAP, USE_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001095 fclose(policy_file);
1096
1097 size_t i;
1098 size_t index = 0;
1099 /*
1100 * Checks return value, filter length, and that the filter
1101 * validates arch, loads syscall number, only allows expected syscalls,
1102 * and returns TRAP on failure.
1103 * NOTE(jorgelo): the filter is longer since we add the syscalls needed
1104 * for logging.
1105 */
1106 ASSERT_EQ(res, 0);
1107 EXPECT_EQ(actual.len, 13 + 2 * log_syscalls_len);
1108 EXPECT_ARCH_VALIDATION(actual.filter);
1109 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
1110 BPF_LD + BPF_W + BPF_ABS,
1111 syscall_nr);
1112
1113 index = ARCH_VALIDATION_LEN + 1;
1114 for (i = 0; i < log_syscalls_len; i++)
1115 EXPECT_ALLOW_SYSCALL(actual.filter + (index + 2 * i),
1116 lookup_syscall(log_syscalls[i]));
1117
1118 index += 2 * log_syscalls_len;
1119
1120 EXPECT_ALLOW_SYSCALL(actual.filter + index, __NR_read);
1121 EXPECT_ALLOW_SYSCALL(actual.filter + index + 2, __NR_write);
1122 EXPECT_ALLOW_SYSCALL(actual.filter + index + 4, __NR_rt_sigreturn);
1123 EXPECT_ALLOW_SYSCALL(actual.filter + index + 6, __NR_exit);
1124 EXPECT_EQ_STMT(actual.filter + index + 8, BPF_RET + BPF_K, SECCOMP_RET_TRAP);
1125
1126 free(actual.filter);
1127}
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -04001128
1129TEST(FilterTest, allow_log_but_kill) {
1130 struct sock_fprog actual;
1131 const char *policy =
1132 "read: 1\n"
1133 "write: 1\n"
1134 "rt_sigreturn: 1\n"
1135 "exit: 1\n";
1136
1137 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -04001138 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -04001139
1140 int res = compile_filter(policy_file, &actual, USE_RET_KILL, USE_LOGGING);
1141 fclose(policy_file);
1142
1143 size_t i;
1144 size_t index = 0;
1145 /*
1146 * Checks return value, filter length, and that the filter
1147 * validates arch, loads syscall number, only allows expected syscalls,
1148 * and returns TRAP on failure.
1149 * NOTE(jorgelo): the filter is longer since we add the syscalls needed
1150 * for logging.
1151 */
1152 ASSERT_EQ(res, 0);
1153 EXPECT_EQ(actual.len, 13 + 2 * log_syscalls_len);
1154 EXPECT_ARCH_VALIDATION(actual.filter);
1155 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
1156 BPF_LD+BPF_W+BPF_ABS, syscall_nr);
1157
1158 index = ARCH_VALIDATION_LEN + 1;
1159 for (i = 0; i < log_syscalls_len; i++)
1160 EXPECT_ALLOW_SYSCALL(actual.filter + (index + 2 * i),
1161 lookup_syscall(log_syscalls[i]));
1162
1163 index += 2 * log_syscalls_len;
1164
1165 EXPECT_ALLOW_SYSCALL(actual.filter + index, __NR_read);
1166 EXPECT_ALLOW_SYSCALL(actual.filter + index + 2, __NR_write);
1167 EXPECT_ALLOW_SYSCALL(actual.filter + index + 4, __NR_rt_sigreturn);
1168 EXPECT_ALLOW_SYSCALL(actual.filter + index + 6, __NR_exit);
1169 EXPECT_EQ_STMT(actual.filter + index + 8, BPF_RET+BPF_K,
1170 SECCOMP_RET_KILL);
1171
1172 free(actual.filter);
1173}