blob: 98a28c35dd6b777fc453ecc2908c6089ae261092 [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 =
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400350 compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
351 ASSERT_EQ(block, nullptr);
352}
353
354TEST_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);
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400361 ASSERT_EQ(block, nullptr);
362}
363
364TEST_F(ArgFilterTest, no_comparison) {
365 const char* fragment = "arg0";
366 int nr = 1;
367 unsigned int id = 0;
368
369 struct filter_block* block =
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400370 compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400371 ASSERT_EQ(block, nullptr);
372}
373
374TEST_F(ArgFilterTest, no_constant) {
375 const char* fragment = "arg0 ==";
376 int nr = 1;
377 unsigned int id = 0;
378
379 struct filter_block* block =
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400380 compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400381 ASSERT_EQ(block, nullptr);
382}
383
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400384TEST_F(ArgFilterTest, arg0_equals) {
385 const char *fragment = "arg0 == 0";
386 int nr = 1;
387 unsigned int id = 0;
388 struct filter_block *block =
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400389 compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400390
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400391 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400392 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;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400397 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400398 EXPECT_EQ(curr_block->len, 1U);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400399 EXPECT_LBL(curr_block->instrs);
400
401 /* Second block is a comparison. */
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400402 curr_block = curr_block->next;
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400403 EXPECT_COMP(curr_block);
404
405 /* Third block is a jump and a label (end of AND group). */
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_GROUP_END(curr_block);
409
410 /* Fourth block is SECCOMP_RET_KILL. */
411 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400412 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400413 EXPECT_KILL(curr_block);
414
415 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
416 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400417 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400418 EXPECT_ALLOW(curr_block);
419
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400420 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400421
422 free_block_list(block);
423}
424
425TEST_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 =
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400430 compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400431
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400432 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400433 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;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400438 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400439 EXPECT_EQ(curr_block->len, 1U);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400440 EXPECT_LBL(curr_block->instrs);
441
442 /* Second block is a comparison. */
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400443 curr_block = curr_block->next;
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400444 EXPECT_COMP(curr_block);
445
446 /* Third block is a jump and a label (end of AND group). */
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_GROUP_END(curr_block);
450
451 /* Fourth block is SECCOMP_RET_KILL. */
452 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400453 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400454 EXPECT_KILL(curr_block);
455
456 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
457 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400458 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400459 EXPECT_ALLOW(curr_block);
460
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400461 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400462
463 free_block_list(block);
464}
465
Jorge Lucangeli Obesfd6f8e32016-10-12 11:19:28 -0400466TEST_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 =
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400471 compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
Jorge Lucangeli Obesfd6f8e32016-10-12 11:19:28 -0400472
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);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400480 EXPECT_EQ(curr_block->len, 1U);
Jorge Lucangeli Obesfd6f8e32016-10-12 11:19:28 -0400481 EXPECT_LBL(curr_block->instrs);
482
483 /* Second block is a comparison. */
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400484 curr_block = curr_block->next;
Jorge Lucangeli Obesfd6f8e32016-10-12 11:19:28 -0400485 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
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400508TEST_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 =
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400514 compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400515
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400516 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400517 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;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400522 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400523 EXPECT_EQ(curr_block->len, 1U);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400524 EXPECT_LBL(curr_block->instrs);
525
526 /* Second block is a comparison. */
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400527 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_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;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400535 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400536 EXPECT_GROUP_END(curr_block);
537
538 /* Fourth block is SECCOMP_RET_KILL. */
539 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400540 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400541 EXPECT_KILL(curr_block);
542
543 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
544 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400545 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400546 EXPECT_ALLOW(curr_block);
547
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400548 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400549
550 free_block_list(block);
551}
552
553TEST_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 =
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400559 compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400560 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400561 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;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400566 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400567 EXPECT_EQ(curr_block->len, 1U);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400568 EXPECT_LBL(curr_block->instrs);
569
570 /* Second block is a comparison ("arg0 == 0"). */
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_COMP(curr_block);
574
575 /* Third block is a comparison ("arg1 == 0"). */
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 /* Fourth 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 /* Fifth block is a comparison ("arg0 == 1"). */
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_COMP(curr_block);
589
590 /* Sixth block is a jump and a label (end of AND group). */
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_GROUP_END(curr_block);
594
595 /* Seventh block is SECCOMP_RET_KILL. */
596 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400597 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400598 EXPECT_KILL(curr_block);
599
600 /* Eigth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
601 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400602 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400603 EXPECT_ALLOW(curr_block);
604
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400605 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400606
607 free_block_list(block);
608}
609
610TEST_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 =
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400616 compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400617 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400618 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;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400623 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400624 EXPECT_EQ(curr_block->len, 1U);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400625 EXPECT_LBL(curr_block->instrs);
626
627 /* Second block is a comparison ("arg0 == 0"). */
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 /* Third 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 /* Fourth block is a comparison ("arg0 == 1"). */
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_COMP(curr_block);
641
642 /* Fifth block is a jump and a label (end of AND group). */
643 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400644 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400645 EXPECT_GROUP_END(curr_block);
646
647 /* Sixth block is SECCOMP_RET_ERRNO. */
648 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400649 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400650 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;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400657 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400658 EXPECT_ALLOW(curr_block);
659
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400660 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400661
662 free_block_list(block);
663}
664
665TEST_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 =
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400671 compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400672 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400673 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;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400678 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400679 EXPECT_EQ(curr_block->len, 1U);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400680 EXPECT_LBL(curr_block->instrs);
681
682 /* Second block is SECCOMP_RET_ERRNO. */
683 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400684 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400685 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
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400690 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400691
692 free_block_list(block);
693}
694
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400695TEST_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 =
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400701 compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400702 ASSERT_EQ(block, nullptr);
703}
704
Jorge Lucangeli Obes53895402016-10-18 12:02:58 -0400705TEST_F(ArgFilterTest, invalid_arg_number) {
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400706 const char *fragment = "argnn == 0";
707 int nr = 1;
708 unsigned int id = 0;
709
710 struct filter_block *block =
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400711 compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
Jorge Lucangeli Obes53895402016-10-18 12:02:58 -0400712 ASSERT_EQ(block, nullptr);
713}
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400714
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400715TEST_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 =
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400721 compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400722 ASSERT_EQ(block, nullptr);
723}
724
725TEST_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 =
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400731 compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400732 ASSERT_EQ(block, nullptr);
733}
734
Jorge Lucangeli Obes53895402016-10-18 12:02:58 -0400735TEST_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 =
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400741 compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
Jorge Lucangeli Obes53895402016-10-18 12:02:58 -0400742 ASSERT_EQ(block, nullptr);
743}
744
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400745TEST_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 =
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400751 compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400752 ASSERT_EQ(block, nullptr);
753}
754
Jorge Lucangeli Obes53895402016-10-18 12:02:58 -0400755TEST_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 =
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400761 compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
Jorge Lucangeli Obes53895402016-10-18 12:02:58 -0400762 ASSERT_EQ(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400763}
764
765TEST_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 =
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400770 compile_policy_line(nr, fragment, id, &labels_, USE_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400771
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400772 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400773 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;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400778 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400779 EXPECT_EQ(curr_block->len, 1U);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400780 EXPECT_LBL(curr_block->instrs);
781
782 /* Second block is a comparison. */
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400783 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_COMP(curr_block);
786
787 /* Third block is a jump and a label (end of AND group). */
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_GROUP_END(curr_block);
791
792 /* Fourth block is SECCOMP_RET_TRAP, with no errno. */
793 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400794 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400795 EXPECT_TRAP(curr_block);
796
797 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
798 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400799 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400800 EXPECT_ALLOW(curr_block);
801
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400802 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400803
804 free_block_list(block);
805}
806
807TEST_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 =
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400813 compile_policy_line(nr, fragment, id, &labels_, NO_LOGGING);
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400814 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400815 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;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400820 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400821 EXPECT_EQ(curr_block->len, 1U);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400822 EXPECT_LBL(curr_block->instrs);
823
824 /* Second block is a comparison ("arg0 == 0"). */
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_COMP(curr_block);
828
829 /* Third block is a jump and a label (end of AND group). */
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_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;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400838 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400839 EXPECT_KILL(curr_block);
840
841 /* Seventh block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
842 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400843 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400844 EXPECT_ALLOW(curr_block);
845
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400846 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400847
848 free_block_list(block);
849}
850
851TEST_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 =
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400857 compile_policy_line(nr, fragment, id, &labels_, USE_LOGGING);
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400858 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400859 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;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400864 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400865 EXPECT_EQ(curr_block->len, 1U);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400866 EXPECT_LBL(curr_block->instrs);
867
868 /* Second block is a comparison ("arg0 == 0"). */
869 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400870 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400871 EXPECT_COMP(curr_block);
872
873 /* Third block is a jump and a label (end of AND group). */
874 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400875 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400876 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;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400883 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400884 EXPECT_TRAP(curr_block);
885
886 /* Seventh block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
887 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400888 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400889 EXPECT_ALLOW(curr_block);
890
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400891 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400892
893 free_block_list(block);
894}
895
896FILE *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
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400933class FileTest : public ::testing::Test {
934 protected:
935 virtual void SetUp() {
936 labels_.count = 0;
937 head_ = new_filter_block();
938 arg_blocks_ = NULL;
939 }
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
lhchavezd0b40702017-09-01 04:17:41 +0000950TEST_F(FileTest, malformed_policy) {
951 const char *policy =
952 "malformed";
953
954 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
955 ASSERT_NE(policy_file, nullptr);
956 int res = compile_file(
957 policy_file, head_, &arg_blocks_, &labels_, USE_RET_KILL, NO_LOGGING, 0);
958 fclose(policy_file);
959
960 /*
961 * Policy is malformed, but process should not crash.
962 */
963 ASSERT_EQ(res, -1);
964}
965
lhchavezd38280c2017-09-01 14:00:05 +0000966TEST_F(FileTest, double_free_on_compile_error) {
967 const char *policy =
968 "read:arg0 == 0\n"
969 "write:0";
970
971 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
972 ASSERT_NE(policy_file, nullptr);
973 int res = compile_file(
974 policy_file, head_, &arg_blocks_, &labels_, USE_RET_KILL, NO_LOGGING, 0);
975 fclose(policy_file);
976
977 /*
978 * Policy is malformed, but process should not crash.
979 */
980 ASSERT_EQ(res, -1);
981}
982
Luis Hector Chavez52f3dd72017-09-01 19:14:22 -0700983TEST_F(FileTest, invalid_return) {
984 const char *policy =
985 "read:arg0 == 0; ;";
986
987 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
988 ASSERT_NE(policy_file, nullptr);
989 int res = compile_file(
990 policy_file, head_, &arg_blocks_, &labels_, USE_RET_KILL, NO_LOGGING, 0);
991 fclose(policy_file);
992
993 /*
994 * Policy is malformed, but process should not crash.
995 */
996 ASSERT_EQ(res, -1);
997}
998
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400999TEST_F(FileTest, seccomp_mode1) {
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -04001000 const char *policy =
1001 "read: 1\n"
1002 "write: 1\n"
1003 "rt_sigreturn: 1\n"
1004 "exit: 1\n";
1005
1006 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
1007 ASSERT_NE(policy_file, nullptr);
1008 int res = compile_file(
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001009 policy_file, head_, &arg_blocks_, &labels_, USE_RET_KILL, NO_LOGGING, 0);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -04001010 fclose(policy_file);
1011
1012 /*
1013 * Checks return value and that the blocks only allow expected syscalls.
1014 */
1015 ASSERT_EQ(res, 0);
1016 struct filter_block *curr_block = head_;
1017 ASSERT_NE(curr_block, nullptr);
1018 EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_read);
1019 curr_block = curr_block->next;
1020 ASSERT_NE(curr_block, nullptr);
1021 EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_write);
1022 curr_block = curr_block->next;
1023 ASSERT_NE(curr_block, nullptr);
1024 EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_rt_sigreturn);
1025 curr_block = curr_block->next;
1026 ASSERT_NE(curr_block, nullptr);
1027 EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_exit);
1028
1029 EXPECT_EQ(curr_block->next, nullptr);
1030}
1031
1032TEST_F(FileTest, seccomp_read) {
1033 const char *policy =
1034 "read: arg0 == 0\n"
1035 "write: 1\n"
1036 "rt_sigreturn: 1\n"
1037 "exit: 1\n";
1038
1039 const int LABEL_ID = 0;
1040
1041 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
1042 ASSERT_NE(policy_file, nullptr);
1043 int res = compile_file(
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001044 policy_file, head_, &arg_blocks_, &labels_, USE_RET_KILL, NO_LOGGING, 0);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -04001045 fclose(policy_file);
1046
1047 /*
1048 * Checks return value, that the blocks only allow expected syscalls, and that
1049 * labels between |head_| and |arg_blocks_| match.
1050 */
1051 ASSERT_EQ(res, 0);
1052 struct filter_block *curr_block = head_;
1053 ASSERT_NE(curr_block, nullptr);
1054 EXPECT_ALLOW_SYSCALL_ARGS(curr_block->instrs,
1055 __NR_read,
1056 LABEL_ID,
1057 JUMP_JT,
1058 JUMP_JF);
1059 curr_block = curr_block->next;
1060 ASSERT_NE(curr_block, nullptr);
1061 EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_write);
1062 curr_block = curr_block->next;
1063 ASSERT_NE(curr_block, nullptr);
1064 EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_rt_sigreturn);
1065 curr_block = curr_block->next;
1066 ASSERT_NE(curr_block, nullptr);
1067 EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_exit);
1068
1069 ASSERT_NE(arg_blocks_, nullptr);
1070 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
1071 EXPECT_EQ(arg_blocks_->total_len, exp_total_len);
1072
1073 /* First block is a label. */
1074 curr_block = arg_blocks_;
1075 ASSERT_NE(curr_block, nullptr);
1076 EXPECT_EQ(curr_block->len, 1U);
1077 EXPECT_ACTUAL_LBL(curr_block->instrs, LABEL_ID);
1078
1079 /* Second block is a comparison. */
1080 curr_block = curr_block->next;
1081 EXPECT_COMP(curr_block);
1082
1083 /* Third block is a jump and a label (end of AND group). */
1084 curr_block = curr_block->next;
1085 ASSERT_NE(curr_block, nullptr);
1086 EXPECT_GROUP_END(curr_block);
1087
1088 /* Fourth block is SECCOMP_RET_KILL. */
1089 curr_block = curr_block->next;
1090 ASSERT_NE(curr_block, nullptr);
1091 EXPECT_KILL(curr_block);
1092
1093 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
1094 curr_block = curr_block->next;
1095 ASSERT_NE(curr_block, nullptr);
1096 EXPECT_ALLOW(curr_block);
1097
1098 EXPECT_EQ(curr_block->next, nullptr);
1099}
1100
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001101TEST(FilterTest, seccomp_mode1) {
1102 struct sock_fprog actual;
1103 const char *policy =
1104 "read: 1\n"
1105 "write: 1\n"
1106 "rt_sigreturn: 1\n"
1107 "exit: 1\n";
1108
1109 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -04001110 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001111
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -04001112 int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001113 fclose(policy_file);
1114
1115 /*
1116 * Checks return value, filter length, and that the filter
1117 * validates arch, loads syscall number, and
1118 * only allows expected syscalls.
1119 */
1120 ASSERT_EQ(res, 0);
1121 EXPECT_EQ(actual.len, 13);
1122 EXPECT_ARCH_VALIDATION(actual.filter);
1123 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
1124 BPF_LD + BPF_W + BPF_ABS,
1125 syscall_nr);
1126 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 1, __NR_read);
1127 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 3, __NR_write);
1128 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 5,
1129 __NR_rt_sigreturn);
1130 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 7, __NR_exit);
1131 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN + 9,
1132 BPF_RET + BPF_K,
1133 SECCOMP_RET_KILL);
1134
1135 free(actual.filter);
1136}
1137
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -04001138TEST(FilterTest, seccomp_mode1_trap) {
1139 struct sock_fprog actual;
1140 const char *policy =
1141 "read: 1\n"
1142 "write: 1\n"
1143 "rt_sigreturn: 1\n"
1144 "exit: 1\n";
1145
1146 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -04001147 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -04001148
1149 int res = compile_filter(policy_file, &actual, USE_RET_TRAP, NO_LOGGING);
1150 fclose(policy_file);
1151
1152 /*
1153 * Checks return value, filter length, and that the filter
1154 * validates arch, loads syscall number, and
1155 * only allows expected syscalls.
1156 */
1157 ASSERT_EQ(res, 0);
1158 EXPECT_EQ(actual.len, 13);
1159 EXPECT_ARCH_VALIDATION(actual.filter);
1160 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
1161 BPF_LD+BPF_W+BPF_ABS, syscall_nr);
1162 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 1,
1163 __NR_read);
1164 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 3,
1165 __NR_write);
1166 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 5,
1167 __NR_rt_sigreturn);
1168 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 7,
1169 __NR_exit);
1170 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN + 9, BPF_RET+BPF_K,
1171 SECCOMP_RET_TRAP);
1172
1173 free(actual.filter);
1174}
1175
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001176TEST(FilterTest, seccomp_read_write) {
1177 struct sock_fprog actual;
1178 const char *policy =
1179 "read: arg0 == 0\n"
1180 "write: arg0 == 1 || arg0 == 2\n"
1181 "rt_sigreturn: 1\n"
1182 "exit: 1\n";
1183
1184 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -04001185 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001186
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -04001187 int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001188 fclose(policy_file);
1189
1190 /*
1191 * Checks return value, filter length, and that the filter
1192 * validates arch, loads syscall number, and
1193 * only allows expected syscalls, jumping to correct arg filter
1194 * offsets.
1195 */
1196 ASSERT_EQ(res, 0);
1197 size_t exp_total_len = 27 + 3 * (BPF_ARG_COMP_LEN + 1);
1198 EXPECT_EQ(actual.len, exp_total_len);
1199
1200 EXPECT_ARCH_VALIDATION(actual.filter);
1201 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
1202 BPF_LD + BPF_W + BPF_ABS,
1203 syscall_nr);
1204 EXPECT_ALLOW_SYSCALL_ARGS(
1205 actual.filter + ARCH_VALIDATION_LEN + 1, __NR_read, 7, 0, 0);
1206 EXPECT_ALLOW_SYSCALL_ARGS(actual.filter + ARCH_VALIDATION_LEN + 3,
1207 __NR_write,
1208 12 + BPF_ARG_COMP_LEN,
1209 0,
1210 0);
1211 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 5,
1212 __NR_rt_sigreturn);
1213 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 7, __NR_exit);
1214 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN + 9,
1215 BPF_RET + BPF_K,
1216 SECCOMP_RET_KILL);
1217
1218 free(actual.filter);
1219}
1220
Jorge Lucangeli Obesc4992572017-04-28 10:49:01 -04001221TEST(FilterTest, misplaced_whitespace) {
1222 struct sock_fprog actual;
1223 const char *policy = "open :1\n";
1224
1225 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
1226 ASSERT_NE(policy_file, nullptr);
1227
1228 int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
1229 fclose(policy_file);
1230
1231 /* Checks return value and filter length. */
1232 ASSERT_EQ(res, 0);
1233 EXPECT_EQ(actual.len,
1234 ARCH_VALIDATION_LEN + 1 /* load syscall nr */ + ALLOW_SYSCALL_LEN +
1235 1 /* ret kill */);
1236 free(actual.filter);
1237}
1238
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -04001239TEST(FilterTest, missing_atom) {
1240 struct sock_fprog actual;
1241 const char* policy = "open:\n";
1242
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001243 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -04001244 ASSERT_NE(policy_file, nullptr);
1245
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -04001246 int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
1247 fclose(policy_file);
1248 ASSERT_NE(res, 0);
1249}
1250
1251TEST(FilterTest, whitespace_atom) {
1252 struct sock_fprog actual;
1253 const char* policy = "open:\t \n";
1254
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001255 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -04001256 ASSERT_NE(policy_file, nullptr);
1257
1258 int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -04001259 fclose(policy_file);
1260 ASSERT_NE(res, 0);
1261}
1262
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001263TEST(FilterTest, invalid_name) {
1264 struct sock_fprog actual;
1265 const char *policy = "notasyscall: 1\n";
1266
1267 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -04001268 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001269
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -04001270 int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001271 fclose(policy_file);
1272 ASSERT_NE(res, 0);
1273}
1274
1275TEST(FilterTest, invalid_arg) {
1276 struct sock_fprog actual;
1277 const char *policy = "open: argnn ==\n";
1278
1279 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -04001280 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001281
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -04001282 int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001283 fclose(policy_file);
1284 ASSERT_NE(res, 0);
1285}
1286
1287TEST(FilterTest, nonexistent) {
1288 struct sock_fprog actual;
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -04001289 int res = compile_filter(NULL, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001290 ASSERT_NE(res, 0);
1291}
1292
1293TEST(FilterTest, log) {
1294 struct sock_fprog actual;
1295 const char *policy =
1296 "read: 1\n"
1297 "write: 1\n"
1298 "rt_sigreturn: 1\n"
1299 "exit: 1\n";
1300
1301 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -04001302 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001303
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -04001304 int res = compile_filter(policy_file, &actual, USE_RET_TRAP, USE_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001305 fclose(policy_file);
1306
1307 size_t i;
1308 size_t index = 0;
1309 /*
1310 * Checks return value, filter length, and that the filter
1311 * validates arch, loads syscall number, only allows expected syscalls,
1312 * and returns TRAP on failure.
1313 * NOTE(jorgelo): the filter is longer since we add the syscalls needed
1314 * for logging.
1315 */
1316 ASSERT_EQ(res, 0);
1317 EXPECT_EQ(actual.len, 13 + 2 * log_syscalls_len);
1318 EXPECT_ARCH_VALIDATION(actual.filter);
1319 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
1320 BPF_LD + BPF_W + BPF_ABS,
1321 syscall_nr);
1322
1323 index = ARCH_VALIDATION_LEN + 1;
1324 for (i = 0; i < log_syscalls_len; i++)
1325 EXPECT_ALLOW_SYSCALL(actual.filter + (index + 2 * i),
1326 lookup_syscall(log_syscalls[i]));
1327
1328 index += 2 * log_syscalls_len;
1329
1330 EXPECT_ALLOW_SYSCALL(actual.filter + index, __NR_read);
1331 EXPECT_ALLOW_SYSCALL(actual.filter + index + 2, __NR_write);
1332 EXPECT_ALLOW_SYSCALL(actual.filter + index + 4, __NR_rt_sigreturn);
1333 EXPECT_ALLOW_SYSCALL(actual.filter + index + 6, __NR_exit);
1334 EXPECT_EQ_STMT(actual.filter + index + 8, BPF_RET + BPF_K, SECCOMP_RET_TRAP);
1335
1336 free(actual.filter);
1337}
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -04001338
1339TEST(FilterTest, allow_log_but_kill) {
1340 struct sock_fprog actual;
1341 const char *policy =
1342 "read: 1\n"
1343 "write: 1\n"
1344 "rt_sigreturn: 1\n"
1345 "exit: 1\n";
1346
1347 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -04001348 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -04001349
1350 int res = compile_filter(policy_file, &actual, USE_RET_KILL, USE_LOGGING);
1351 fclose(policy_file);
1352
1353 size_t i;
1354 size_t index = 0;
1355 /*
1356 * Checks return value, filter length, and that the filter
1357 * validates arch, loads syscall number, only allows expected syscalls,
1358 * and returns TRAP on failure.
1359 * NOTE(jorgelo): the filter is longer since we add the syscalls needed
1360 * for logging.
1361 */
1362 ASSERT_EQ(res, 0);
1363 EXPECT_EQ(actual.len, 13 + 2 * log_syscalls_len);
1364 EXPECT_ARCH_VALIDATION(actual.filter);
1365 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
1366 BPF_LD+BPF_W+BPF_ABS, syscall_nr);
1367
1368 index = ARCH_VALIDATION_LEN + 1;
1369 for (i = 0; i < log_syscalls_len; i++)
1370 EXPECT_ALLOW_SYSCALL(actual.filter + (index + 2 * i),
1371 lookup_syscall(log_syscalls[i]));
1372
1373 index += 2 * log_syscalls_len;
1374
1375 EXPECT_ALLOW_SYSCALL(actual.filter + index, __NR_read);
1376 EXPECT_ALLOW_SYSCALL(actual.filter + index + 2, __NR_write);
1377 EXPECT_ALLOW_SYSCALL(actual.filter + index + 4, __NR_rt_sigreturn);
1378 EXPECT_ALLOW_SYSCALL(actual.filter + index + 6, __NR_exit);
1379 EXPECT_EQ_STMT(actual.filter + index + 8, BPF_RET+BPF_K,
1380 SECCOMP_RET_KILL);
1381
1382 free(actual.filter);
1383}
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001384
1385TEST(FilterTest, include_invalid_token) {
1386 struct sock_fprog actual;
1387 const char *invalid_token = "@unclude ./test/seccomp.policy\n";
1388
1389 FILE *policy_file =
1390 write_policy_to_pipe(invalid_token, strlen(invalid_token));
1391 ASSERT_NE(policy_file, nullptr);
1392 int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
1393 fclose(policy_file);
1394 EXPECT_NE(res, 0);
1395}
1396
1397TEST(FilterTest, include_no_space) {
1398 struct sock_fprog actual;
1399 const char *no_space = "@includetest/seccomp.policy\n";
1400
1401 FILE *policy_file = write_policy_to_pipe(no_space, strlen(no_space));
1402 ASSERT_NE(policy_file, nullptr);
1403 int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
1404 fclose(policy_file);
1405 EXPECT_NE(res, 0);
1406}
1407
1408TEST(FilterTest, include_double_token) {
1409 struct sock_fprog actual;
1410 const char *double_token = "@includeinclude ./test/seccomp.policy\n";
1411
1412 FILE *policy_file = write_policy_to_pipe(double_token, strlen(double_token));
1413 ASSERT_NE(policy_file, nullptr);
1414 int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
1415 fclose(policy_file);
1416 EXPECT_NE(res, 0);
1417}
1418
1419TEST(FilterTest, include_no_file) {
1420 struct sock_fprog actual;
1421 const char *no_file = "@include\n";
1422
1423 FILE *policy_file = write_policy_to_pipe(no_file, strlen(no_file));
1424 ASSERT_NE(policy_file, nullptr);
1425 int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
1426 fclose(policy_file);
1427 EXPECT_NE(res, 0);
1428}
1429
1430TEST(FilterTest, include_space_no_file) {
1431 struct sock_fprog actual;
1432 const char *space_no_file = "@include \n";
1433
1434 FILE *policy_file =
1435 write_policy_to_pipe(space_no_file, strlen(space_no_file));
1436 ASSERT_NE(policy_file, nullptr);
1437 int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
1438 fclose(policy_file);
1439 EXPECT_NE(res, 0);
1440}
1441
1442TEST(FilterTest, include_implicit_relative_path) {
1443 struct sock_fprog actual;
1444 const char *implicit_relative_path = "@include test/seccomp.policy\n";
1445
1446 FILE *policy_file = write_policy_to_pipe(implicit_relative_path,
1447 strlen(implicit_relative_path));
1448 ASSERT_NE(policy_file, nullptr);
1449 int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
1450 fclose(policy_file);
1451 EXPECT_NE(res, 0);
1452}
1453
1454TEST(FilterTest, include_extra_text) {
1455 struct sock_fprog actual;
1456 const char *extra_text = "@include /some/file: sneaky comment\n";
1457
1458 FILE *policy_file =
1459 write_policy_to_pipe(extra_text, strlen(extra_text));
1460 ASSERT_NE(policy_file, nullptr);
1461 int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
1462 fclose(policy_file);
1463 EXPECT_NE(res, 0);
1464}
1465
1466TEST(FilterTest, include_split_filename) {
1467 struct sock_fprog actual;
1468 const char *split_filename = "@include /some/file:colon.policy\n";
1469
1470 FILE *policy_file =
1471 write_policy_to_pipe(split_filename, strlen(split_filename));
1472 ASSERT_NE(policy_file, nullptr);
1473 int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
1474 fclose(policy_file);
1475 EXPECT_NE(res, 0);
1476}
1477
1478TEST(FilterTest, include_nonexistent_file) {
1479 struct sock_fprog actual;
1480 const char *include_policy = "@include ./nonexistent.policy\n";
1481
1482 FILE *policy_file =
1483 write_policy_to_pipe(include_policy, strlen(include_policy));
1484 ASSERT_NE(policy_file, nullptr);
1485
1486 int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
1487 fclose(policy_file);
1488
1489 ASSERT_NE(res, 0);
1490}
1491
1492// TODO(jorgelo): Android unit tests don't currently support data files.
1493// Re-enable by creating a temporary policy file at runtime.
1494#if !defined(__ANDROID__)
1495
1496TEST(FilterTest, include) {
1497 struct sock_fprog compiled_plain;
1498 struct sock_fprog compiled_with_include;
1499
1500 const char *policy_plain =
1501 "read: 1\n"
1502 "write: 1\n"
1503 "rt_sigreturn: 1\n"
1504 "exit: 1\n";
1505
1506 const char *policy_with_include = "@include ./test/seccomp.policy\n";
1507
1508 FILE *file_plain = write_policy_to_pipe(policy_plain, strlen(policy_plain));
1509 ASSERT_NE(file_plain, nullptr);
1510 int res_plain =
1511 compile_filter(file_plain, &compiled_plain, USE_RET_KILL, NO_LOGGING);
1512 fclose(file_plain);
1513
1514 FILE *file_with_include =
1515 write_policy_to_pipe(policy_with_include, strlen(policy_with_include));
1516 ASSERT_NE(file_with_include, nullptr);
1517 int res_with_include = compile_filter(
1518 file_with_include, &compiled_with_include, USE_RET_KILL, NO_LOGGING);
1519 fclose(file_with_include);
1520
1521 /*
1522 * Checks that filter length is the same for a plain policy and an equivalent
1523 * policy with an @include statement. Also checks that the filter generated
1524 * from the policy with an @include statement is exactly the same as one
1525 * generated from a plain policy.
1526 */
1527 ASSERT_EQ(res_plain, 0);
1528 ASSERT_EQ(res_with_include, 0);
1529
1530 EXPECT_EQ(compiled_plain.len, 13);
1531 EXPECT_EQ(compiled_with_include.len, 13);
1532
1533 EXPECT_ARCH_VALIDATION(compiled_with_include.filter);
1534 EXPECT_EQ_STMT(compiled_with_include.filter + ARCH_VALIDATION_LEN,
1535 BPF_LD + BPF_W + BPF_ABS,
1536 syscall_nr);
1537 EXPECT_ALLOW_SYSCALL(compiled_with_include.filter + ARCH_VALIDATION_LEN + 1,
1538 __NR_read);
1539 EXPECT_ALLOW_SYSCALL(compiled_with_include.filter + ARCH_VALIDATION_LEN + 3,
1540 __NR_write);
1541 EXPECT_ALLOW_SYSCALL(compiled_with_include.filter + ARCH_VALIDATION_LEN + 5,
1542 __NR_rt_sigreturn);
1543 EXPECT_ALLOW_SYSCALL(compiled_with_include.filter + ARCH_VALIDATION_LEN + 7,
1544 __NR_exit);
1545 EXPECT_EQ_STMT(compiled_with_include.filter + ARCH_VALIDATION_LEN + 9,
1546 BPF_RET + BPF_K,
1547 SECCOMP_RET_KILL);
1548
1549 free(compiled_plain.filter);
1550 free(compiled_with_include.filter);
1551}
1552
1553TEST(FilterTest, include_same_syscalls) {
1554 struct sock_fprog actual;
1555 const char *policy =
1556 "read: 1\n"
1557 "write: 1\n"
1558 "rt_sigreturn: 1\n"
1559 "exit: 1\n"
1560 "@include ./test/seccomp.policy\n";
1561
1562 FILE *policy_file =
1563 write_policy_to_pipe(policy, strlen(policy));
1564 ASSERT_NE(policy_file, nullptr);
1565
1566 int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
1567 fclose(policy_file);
1568
1569 ASSERT_EQ(res, 0);
1570 EXPECT_EQ(actual.len,
1571 ARCH_VALIDATION_LEN + 1 /* load syscall nr */ +
1572 2 * 8 /* check syscalls twice */ + 1 /* filter return */);
1573 free(actual.filter);
1574}
1575
1576TEST(FilterTest, include_invalid_policy) {
1577 struct sock_fprog actual;
1578 const char *policy =
1579 "read: 1\n"
1580 "write: 1\n"
1581 "rt_sigreturn: 1\n"
1582 "exit: 1\n"
1583 "@include ./test/invalid_syscall_name.policy\n";
1584
1585 FILE *policy_file =
1586 write_policy_to_pipe(policy, strlen(policy));
1587 ASSERT_NE(policy_file, nullptr);
1588
1589 /* Ensure the included (invalid) policy file exists. */
1590 FILE *included_file = fopen("./test/invalid_syscall_name.policy", "r");
1591 ASSERT_NE(included_file, nullptr);
1592 fclose(included_file);
1593
1594 int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
1595 fclose(policy_file);
1596
1597 ASSERT_NE(res, 0);
1598}
1599
1600TEST(FilterTest, include_nested) {
1601 struct sock_fprog actual;
1602 const char *policy = "@include ./test/nested.policy\n";
1603
1604 FILE *policy_file =
1605 write_policy_to_pipe(policy, strlen(policy));
1606 ASSERT_NE(policy_file, nullptr);
1607
1608 /* Ensure the policy file exists. */
1609 FILE *included_file = fopen("./test/nested.policy", "r");
1610 ASSERT_NE(included_file, nullptr);
1611 fclose(included_file);
1612
1613 int res = compile_filter(policy_file, &actual, USE_RET_KILL, NO_LOGGING);
1614 fclose(policy_file);
1615
1616 ASSERT_NE(res, 0);
1617}
1618
1619#endif // !__ANDROID__