blob: 9beac6529d95dca17034cdea8d9dbc56ea50261d [file] [log] [blame]
Mike Frysinger50e31fa2018-01-19 18:59:49 -05001/* Copyright 2016 The Chromium OS Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 *
5 * Test syscall filtering using gtest.
6 */
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04007
8#include <asm/unistd.h>
9#include <errno.h>
10#include <fcntl.h> /* For O_WRONLY. */
11
12#include <gtest/gtest.h>
Jorge Lucangeli Obes07459372016-10-19 15:33:31 -040013#include <string>
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -040014
15#include "bpf.h"
16#include "syscall_filter.h"
17#include "syscall_filter_unittest_macros.h"
18#include "util.h"
19
Jorge Lucangeli Obes07459372016-10-19 15:33:31 -040020TEST(util, parse_constant_unsigned) {
21 char *end;
22 long int c = 0;
23 std::string constant;
24
25#if defined(BITS32)
26 constant = "0x80000000";
27 c = parse_constant(const_cast<char*>(constant.c_str()), &end);
28 EXPECT_EQ(0x80000000U, static_cast<unsigned long int>(c));
29
30#elif defined(BITS64)
31 constant = "0x8000000000000000";
32 c = parse_constant(const_cast<char*>(constant.c_str()), &end);
33 EXPECT_EQ(0x8000000000000000UL, static_cast<unsigned long int>(c));
34#endif
35}
36
37TEST(util, parse_constant_unsigned_toobig) {
38 char *end;
39 long int c = 0;
40 std::string constant;
41
42#if defined(BITS32)
43 constant = "0x100000000"; // Too big for 32-bit unsigned long int.
44 c = parse_constant(const_cast<char*>(constant.c_str()), &end);
45 // Error case should return 0.
46 EXPECT_EQ(0, c);
47
48#elif defined(BITS64)
49 constant = "0x10000000000000000";
50 c = parse_constant(const_cast<char*>(constant.c_str()), &end);
51 // Error case should return 0.
52 EXPECT_EQ(0, c);
53#endif
54}
55
56TEST(util, parse_constant_signed) {
57 char *end;
58 long int c = 0;
59 std::string constant = "-1";
60 c = parse_constant(const_cast<char*>(constant.c_str()), &end);
61 EXPECT_EQ(-1, c);
62}
63
64TEST(util, parse_constant_signed_toonegative) {
65 char *end;
66 long int c = 0;
67 std::string constant;
68
69#if defined(BITS32)
70 constant = "-0x80000001";
71 c = parse_constant(const_cast<char*>(constant.c_str()), &end);
72 // Error case should return 0.
73 EXPECT_EQ(0, c);
74
75#elif defined(BITS64)
76 constant = "-0x8000000000000001";
77 c = parse_constant(const_cast<char*>(constant.c_str()), &end);
78 // Error case should return 0.
79 EXPECT_EQ(0, c);
80#endif
81}
82
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -040083/* Test that setting one BPF instruction works. */
84TEST(bpf, set_bpf_instr) {
85 struct sock_filter instr;
86 unsigned char code = BPF_LD + BPF_W + BPF_ABS;
87 unsigned int k = 4;
88 unsigned char jt = 1, jf = 2;
89
90 size_t len = set_bpf_instr(&instr, code, k, jt, jf);
91
92 EXPECT_EQ(len, 1U);
93 EXPECT_EQ_BLOCK(&instr, code, k, jt, jf);
94}
95
96TEST(bpf, bpf_load_arg) {
97 struct sock_filter load_arg[BPF_LOAD_ARG_LEN];
Jorge Lucangeli Obes9bd316b2017-01-26 17:21:16 -050098 const int argidx = 1;
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -040099 size_t len = bpf_load_arg(load_arg, argidx);
100
101 EXPECT_EQ(len, BPF_LOAD_ARG_LEN);
102
103#if defined(BITS32)
104 EXPECT_EQ_STMT(&load_arg[0], BPF_LD + BPF_W + BPF_ABS, LO_ARG(argidx));
105#elif defined(BITS64)
106 EXPECT_EQ_STMT(&load_arg[0], BPF_LD + BPF_W + BPF_ABS, LO_ARG(argidx));
107 EXPECT_EQ_STMT(&load_arg[1], BPF_ST, 0);
108 EXPECT_EQ_STMT(&load_arg[2], BPF_LD + BPF_W + BPF_ABS, HI_ARG(argidx));
109 EXPECT_EQ_STMT(&load_arg[3], BPF_ST, 1);
110#endif
111}
112
113TEST(bpf, bpf_comp_jeq) {
114 struct sock_filter comp_jeq[BPF_COMP_LEN];
115 unsigned long c = 1;
116 unsigned char jt = 1;
117 unsigned char jf = 2;
118
119 size_t len = bpf_comp_jeq(comp_jeq, c, jt, jf);
120
121 EXPECT_EQ(len, BPF_COMP_LEN);
122
123#if defined(BITS32)
124 EXPECT_EQ_BLOCK(&comp_jeq[0], BPF_JMP + BPF_JEQ + BPF_K, c, jt, jf);
125#elif defined(BITS64)
126 EXPECT_EQ_BLOCK(&comp_jeq[0], BPF_JMP + BPF_JEQ + BPF_K, 0, 0, jf + 2);
127 EXPECT_EQ_STMT(&comp_jeq[1], BPF_LD + BPF_MEM, 0);
128 EXPECT_EQ_BLOCK(&comp_jeq[2], BPF_JMP + BPF_JEQ + BPF_K, c, jt, jf);
129#endif
130}
131
132TEST(bpf, bpf_comp_jset) {
133 struct sock_filter comp_jset[BPF_COMP_LEN];
Jorge Lucangeli Obesfd6f8e32016-10-12 11:19:28 -0400134 unsigned long mask = (1UL << (sizeof(unsigned long) * 8 - 1)) | O_WRONLY;
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400135 unsigned char jt = 1;
136 unsigned char jf = 2;
137
138 size_t len = bpf_comp_jset(comp_jset, mask, jt, jf);
139
140 EXPECT_EQ(len, BPF_COMP_LEN);
141
142#if defined(BITS32)
143 EXPECT_EQ_BLOCK(&comp_jset[0], BPF_JMP + BPF_JSET + BPF_K, mask, jt, jf);
144#elif defined(BITS64)
Jorge Lucangeli Obesfd6f8e32016-10-12 11:19:28 -0400145 EXPECT_EQ_BLOCK(
146 &comp_jset[0], BPF_JMP + BPF_JSET + BPF_K, 0x80000000, jt + 2, 0);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400147 EXPECT_EQ_STMT(&comp_jset[1], BPF_LD + BPF_MEM, 0);
Jorge Lucangeli Obesfd6f8e32016-10-12 11:19:28 -0400148 EXPECT_EQ_BLOCK(&comp_jset[2], BPF_JMP + BPF_JSET + BPF_K, O_WRONLY, jt, jf);
149#endif
150}
151
152TEST(bpf, bpf_comp_jin) {
153 struct sock_filter comp_jin[BPF_COMP_LEN];
154 unsigned long mask = (1UL << (sizeof(unsigned long) * 8 - 1)) | O_WRONLY;
155 unsigned char jt = 10;
156 unsigned char jf = 20;
157
158 size_t len = bpf_comp_jin(comp_jin, mask, jt, jf);
159
160 EXPECT_EQ(len, BPF_COMP_LEN);
161
162#if defined(BITS32)
163 EXPECT_EQ_BLOCK(&comp_jin[0], BPF_JMP + BPF_JSET + BPF_K, ~mask, jf, jt);
164#elif defined(BITS64)
165 EXPECT_EQ_BLOCK(
166 &comp_jin[0], BPF_JMP + BPF_JSET + BPF_K, 0x7FFFFFFF, jf + 2, 0);
167 EXPECT_EQ_STMT(&comp_jin[1], BPF_LD + BPF_MEM, 0);
168 EXPECT_EQ_BLOCK(&comp_jin[2], BPF_JMP + BPF_JSET + BPF_K, ~O_WRONLY, jf, jt);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400169#endif
170}
171
172TEST(bpf, bpf_arg_comp) {
173 struct sock_filter *arg_comp;
174 int op = EQ;
Jorge Lucangeli Obes9bd316b2017-01-26 17:21:16 -0500175 const int argidx = 1;
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400176 unsigned long c = 3;
177 unsigned int label_id = 0;
178
179 size_t len = bpf_arg_comp(&arg_comp, op, argidx, c, label_id);
180
181 EXPECT_EQ(len, BPF_ARG_COMP_LEN + 1);
182
183#if defined(BITS32)
184 EXPECT_EQ_STMT(&arg_comp[0], BPF_LD + BPF_W + BPF_ABS, LO_ARG(argidx));
185 EXPECT_EQ_BLOCK(&arg_comp[1], BPF_JMP + BPF_JEQ + BPF_K, c, 1, 0);
186 EXPECT_JUMP_LBL(&arg_comp[2]);
187#elif defined(BITS64)
188 EXPECT_EQ_STMT(&arg_comp[0], BPF_LD + BPF_W + BPF_ABS, LO_ARG(argidx));
189 EXPECT_EQ_STMT(&arg_comp[1], BPF_ST, 0);
190 EXPECT_EQ_STMT(&arg_comp[2], BPF_LD + BPF_W + BPF_ABS, HI_ARG(argidx));
191 EXPECT_EQ_STMT(&arg_comp[3], BPF_ST, 1);
192
193 EXPECT_EQ_BLOCK(&arg_comp[4], BPF_JMP + BPF_JEQ + BPF_K, 0, 0, 2);
194 EXPECT_EQ_STMT(&arg_comp[5], BPF_LD + BPF_MEM, 0);
195 EXPECT_EQ_BLOCK(&arg_comp[6], BPF_JMP + BPF_JEQ + BPF_K, c, 1, 0);
196 EXPECT_JUMP_LBL(&arg_comp[7]);
197#endif
198 free(arg_comp);
199}
200
201TEST(bpf, bpf_validate_arch) {
202 struct sock_filter validate_arch[ARCH_VALIDATION_LEN];
203
204 size_t len = bpf_validate_arch(validate_arch);
205
206 EXPECT_EQ(len, ARCH_VALIDATION_LEN);
207 EXPECT_ARCH_VALIDATION(validate_arch);
208}
209
210TEST(bpf, bpf_allow_syscall) {
211 struct sock_filter allow_syscall[ALLOW_SYSCALL_LEN];
212 int nr = 1;
213
214 size_t len = bpf_allow_syscall(allow_syscall, nr);
215
216 EXPECT_EQ(len, ALLOW_SYSCALL_LEN);
217 EXPECT_ALLOW_SYSCALL(allow_syscall, nr);
218}
219
220TEST(bpf, bpf_allow_syscall_args) {
221 struct sock_filter allow_syscall[ALLOW_SYSCALL_LEN];
222 int nr = 1;
223 unsigned int id = 1024;
224
225 size_t len = bpf_allow_syscall_args(allow_syscall, nr, id);
226
227 EXPECT_EQ(len, ALLOW_SYSCALL_LEN);
228 EXPECT_ALLOW_SYSCALL_ARGS(allow_syscall, nr, id, JUMP_JT, JUMP_JF);
229}
230
Jorge Lucangeli Obes8cc9d4a2016-10-03 10:00:57 -0400231class BpfLabelTest : public ::testing::Test {
232 protected:
Jorge Lucangeli Obes9bd316b2017-01-26 17:21:16 -0500233 virtual void SetUp() { labels_.count = 0; }
Jorge Lucangeli Obes8cc9d4a2016-10-03 10:00:57 -0400234 virtual void TearDown() { free_label_strings(&labels_); }
235 struct bpf_labels labels_;
236};
237
238TEST_F(BpfLabelTest, zero_length_filter) {
239 int res = bpf_resolve_jumps(&labels_, NULL, 0);
240
241 EXPECT_EQ(res, 0);
242 EXPECT_EQ(labels_.count, 0U);
243}
244
245TEST_F(BpfLabelTest, single_label) {
246 struct sock_filter test_label[1];
247
248 int id = bpf_label_id(&labels_, "test");
249 set_bpf_lbl(test_label, id);
250 int res = bpf_resolve_jumps(&labels_, test_label, 1);
251
252 EXPECT_EQ(res, 0);
253 EXPECT_EQ(labels_.count, 1U);
254}
255
256TEST_F(BpfLabelTest, repeated_label) {
257 struct sock_filter test_label[2];
258
259 int id = bpf_label_id(&labels_, "test");
260 set_bpf_lbl(&test_label[0], id);
261 set_bpf_lbl(&test_label[1], id);
262 int res = bpf_resolve_jumps(&labels_, test_label, 2);
263
264 EXPECT_EQ(res, -1);
265}
266
267TEST_F(BpfLabelTest, jump_with_no_label) {
268 struct sock_filter test_jump[1];
269
270 set_bpf_jump_lbl(test_jump, 14831);
271 int res = bpf_resolve_jumps(&labels_, test_jump, 1);
272
273 EXPECT_EQ(res, -1);
274}
275
276TEST_F(BpfLabelTest, jump_to_valid_label) {
277 struct sock_filter test_jump[2];
278
279 int id = bpf_label_id(&labels_, "test");
280 set_bpf_jump_lbl(&test_jump[0], id);
281 set_bpf_lbl(&test_jump[1], id);
282
283 int res = bpf_resolve_jumps(&labels_, test_jump, 2);
284 EXPECT_EQ(res, 0);
285 EXPECT_EQ(labels_.count, 1U);
286}
287
288TEST_F(BpfLabelTest, jump_to_invalid_label) {
289 struct sock_filter test_jump[2];
290
291 int id = bpf_label_id(&labels_, "test");
292 set_bpf_jump_lbl(&test_jump[0], id + 1);
293 set_bpf_lbl(&test_jump[1], id);
294
295 int res = bpf_resolve_jumps(&labels_, test_jump, 2);
296 EXPECT_EQ(res, -1);
297}
298
299TEST_F(BpfLabelTest, jump_to_unresolved_label) {
300 struct sock_filter test_jump[2];
301
302 int id = bpf_label_id(&labels_, "test");
303 /* Notice the order of the instructions is reversed. */
304 set_bpf_lbl(&test_jump[0], id);
305 set_bpf_jump_lbl(&test_jump[1], id);
306
307 int res = bpf_resolve_jumps(&labels_, test_jump, 2);
308 EXPECT_EQ(res, -1);
309}
310
311TEST_F(BpfLabelTest, too_many_labels) {
312 unsigned int i;
313 char label[20];
314
315 for (i = 0; i < BPF_LABELS_MAX; i++) {
316 snprintf(label, 20, "test%u", i);
317 (void) bpf_label_id(&labels_, label);
318 }
319 int id = bpf_label_id(&labels_, "test");
320
321 /* Insertion failed... */
322 EXPECT_EQ(id, -1);
323 /* ... because the label lookup table is full. */
324 EXPECT_EQ(labels_.count, BPF_LABELS_MAX);
325}
326
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400327class ArgFilterTest : public ::testing::Test {
328 protected:
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700329 virtual void SetUp() {
330 labels_.count = 0;
331 state_.filename = "policy";
332 state_.line_number = 1;
333 }
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400334 virtual void TearDown() { free_label_strings(&labels_); }
335 struct bpf_labels labels_;
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700336 int nr_ = 1;
337 unsigned int id_ = 0;
338 struct parser_state state_;
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400339};
340
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400341TEST_F(ArgFilterTest, empty_atom) {
342 const char* fragment = "";
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400343
344 struct filter_block* block =
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700345 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400346 ASSERT_EQ(block, nullptr);
347}
348
349TEST_F(ArgFilterTest, whitespace_atom) {
350 const char* fragment = "\t ";
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400351
352 struct filter_block* block =
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700353 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400354 ASSERT_EQ(block, nullptr);
355}
356
357TEST_F(ArgFilterTest, no_comparison) {
358 const char* fragment = "arg0";
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400359
360 struct filter_block* block =
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700361 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400362 ASSERT_EQ(block, nullptr);
363}
364
365TEST_F(ArgFilterTest, no_constant) {
366 const char* fragment = "arg0 ==";
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400367
368 struct filter_block* block =
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700369 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400370 ASSERT_EQ(block, nullptr);
371}
372
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400373TEST_F(ArgFilterTest, arg0_equals) {
374 const char *fragment = "arg0 == 0";
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700375
376 struct filter_block* block =
377 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400378
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 Obes45932a52017-03-15 17:02:58 -0400386 EXPECT_EQ(curr_block->len, 1U);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400387 EXPECT_LBL(curr_block->instrs);
388
389 /* Second block is a comparison. */
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400390 curr_block = curr_block->next;
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400391 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";
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700415
416 struct filter_block* block =
417 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400418
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400419 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400420 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
421 EXPECT_EQ(block->total_len, exp_total_len);
422
423 /* First block is a label. */
424 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400425 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400426 EXPECT_EQ(curr_block->len, 1U);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400427 EXPECT_LBL(curr_block->instrs);
428
429 /* Second block is a comparison. */
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400430 curr_block = curr_block->next;
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400431 EXPECT_COMP(curr_block);
432
433 /* Third block is a jump and a label (end of AND group). */
434 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400435 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400436 EXPECT_GROUP_END(curr_block);
437
438 /* Fourth block is SECCOMP_RET_KILL. */
439 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400440 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400441 EXPECT_KILL(curr_block);
442
443 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
444 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400445 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400446 EXPECT_ALLOW(curr_block);
447
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400448 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400449
450 free_block_list(block);
451}
452
Jorge Lucangeli Obesfd6f8e32016-10-12 11:19:28 -0400453TEST_F(ArgFilterTest, arg0_flag_set_inclusion) {
454 const char *fragment = "arg0 in O_RDONLY|O_CREAT";
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700455
456 struct filter_block* block =
457 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obesfd6f8e32016-10-12 11:19:28 -0400458
459 ASSERT_NE(block, nullptr);
460 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
461 EXPECT_EQ(block->total_len, exp_total_len);
462
463 /* First block is a label. */
464 struct filter_block *curr_block = block;
465 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400466 EXPECT_EQ(curr_block->len, 1U);
Jorge Lucangeli Obesfd6f8e32016-10-12 11:19:28 -0400467 EXPECT_LBL(curr_block->instrs);
468
469 /* Second block is a comparison. */
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400470 curr_block = curr_block->next;
Jorge Lucangeli Obesfd6f8e32016-10-12 11:19:28 -0400471 ASSERT_NE(curr_block, nullptr);
472 EXPECT_COMP(curr_block);
473
474 /* Third block is a jump and a label (end of AND group). */
475 curr_block = curr_block->next;
476 ASSERT_NE(curr_block, nullptr);
477 EXPECT_GROUP_END(curr_block);
478
479 /* Fourth block is SECCOMP_RET_KILL. */
480 curr_block = curr_block->next;
481 ASSERT_NE(curr_block, nullptr);
482 EXPECT_KILL(curr_block);
483
484 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
485 curr_block = curr_block->next;
486 ASSERT_NE(curr_block, nullptr);
487 EXPECT_ALLOW(curr_block);
488
489 EXPECT_EQ(curr_block->next, nullptr);
490
491 free_block_list(block);
492}
493
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400494TEST_F(ArgFilterTest, arg0_eq_mask) {
495 const char *fragment = "arg1 == O_WRONLY|O_CREAT";
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400496
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700497 struct filter_block* block =
498 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400499
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400500 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400501 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
502 EXPECT_EQ(block->total_len, exp_total_len);
503
504 /* First block is a label. */
505 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400506 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400507 EXPECT_EQ(curr_block->len, 1U);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400508 EXPECT_LBL(curr_block->instrs);
509
510 /* Second block is a comparison. */
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400511 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400512 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400513 EXPECT_COMP(curr_block);
514 EXPECT_EQ(curr_block->instrs[BPF_ARG_COMP_LEN - 1].k,
515 (unsigned int)(O_WRONLY | O_CREAT));
516
517 /* Third block is a jump and a label (end of AND group). */
518 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400519 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400520 EXPECT_GROUP_END(curr_block);
521
522 /* Fourth block is SECCOMP_RET_KILL. */
523 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400524 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400525 EXPECT_KILL(curr_block);
526
527 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
528 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400529 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400530 EXPECT_ALLOW(curr_block);
531
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400532 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400533
534 free_block_list(block);
535}
536
537TEST_F(ArgFilterTest, and_or) {
538 const char *fragment = "arg0 == 0 && arg1 == 0 || arg0 == 1";
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400539
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700540 struct filter_block* block =
541 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400542 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400543 size_t exp_total_len = 1 + 3 * (BPF_ARG_COMP_LEN + 1) + 2 + 2 + 1 + 2;
544 EXPECT_EQ(block->total_len, exp_total_len);
545
546 /* First block is a label. */
547 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400548 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400549 EXPECT_EQ(curr_block->len, 1U);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400550 EXPECT_LBL(curr_block->instrs);
551
552 /* Second block is a comparison ("arg0 == 0"). */
553 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400554 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400555 EXPECT_COMP(curr_block);
556
557 /* Third block is a comparison ("arg1 == 0"). */
558 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400559 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400560 EXPECT_COMP(curr_block);
561
562 /* Fourth block is a jump and a label (end of AND group). */
563 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400564 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400565 EXPECT_GROUP_END(curr_block);
566
567 /* Fifth block is a comparison ("arg0 == 1"). */
568 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400569 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400570 EXPECT_COMP(curr_block);
571
572 /* Sixth block is a jump and a label (end of AND group). */
573 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400574 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400575 EXPECT_GROUP_END(curr_block);
576
577 /* Seventh block is SECCOMP_RET_KILL. */
578 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400579 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400580 EXPECT_KILL(curr_block);
581
582 /* Eigth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
583 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400584 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400585 EXPECT_ALLOW(curr_block);
586
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400587 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400588
589 free_block_list(block);
590}
591
592TEST_F(ArgFilterTest, ret_errno) {
593 const char *fragment = "arg0 == 0 || arg0 == 1; return 1";
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400594
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700595 struct filter_block* block =
596 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400597 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400598 size_t exp_total_len = 1 + 2 * (BPF_ARG_COMP_LEN + 1) + 2 + 2 + 1 + 2;
599 EXPECT_EQ(block->total_len, exp_total_len);
600
601 /* First block is a label. */
602 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400603 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400604 EXPECT_EQ(curr_block->len, 1U);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400605 EXPECT_LBL(curr_block->instrs);
606
607 /* Second block is a comparison ("arg0 == 0"). */
608 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400609 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400610 EXPECT_COMP(curr_block);
611
612 /* Third block is a jump and a label (end of AND group). */
613 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400614 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400615 EXPECT_GROUP_END(curr_block);
616
617 /* Fourth block is a comparison ("arg0 == 1"). */
618 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400619 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400620 EXPECT_COMP(curr_block);
621
622 /* Fifth block is a jump and a label (end of AND group). */
623 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400624 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400625 EXPECT_GROUP_END(curr_block);
626
627 /* Sixth block is SECCOMP_RET_ERRNO. */
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_EQ(curr_block->len, 1U);
631 EXPECT_EQ_STMT(curr_block->instrs,
632 BPF_RET + BPF_K,
633 SECCOMP_RET_ERRNO | (1 & SECCOMP_RET_DATA));
634
635 /* Seventh block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
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_ALLOW(curr_block);
639
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400640 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400641
642 free_block_list(block);
643}
644
645TEST_F(ArgFilterTest, unconditional_errno) {
646 const char *fragment = "return 1";
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400647
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700648 struct filter_block* block =
649 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400650 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400651 size_t exp_total_len = 2;
652 EXPECT_EQ(block->total_len, exp_total_len);
653
654 /* First block is a label. */
655 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400656 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400657 EXPECT_EQ(curr_block->len, 1U);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400658 EXPECT_LBL(curr_block->instrs);
659
660 /* Second block is SECCOMP_RET_ERRNO. */
661 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400662 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400663 EXPECT_EQ(curr_block->len, 1U);
664 EXPECT_EQ_STMT(curr_block->instrs,
665 BPF_RET + BPF_K,
666 SECCOMP_RET_ERRNO | (1 & SECCOMP_RET_DATA));
667
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400668 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400669
670 free_block_list(block);
671}
672
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400673TEST_F(ArgFilterTest, invalid_arg_token) {
674 const char *fragment = "org0 == 0";
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400675
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700676 struct filter_block* block =
677 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400678 ASSERT_EQ(block, nullptr);
679}
680
Jorge Lucangeli Obes53895402016-10-18 12:02:58 -0400681TEST_F(ArgFilterTest, invalid_arg_number) {
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400682 const char *fragment = "argnn == 0";
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400683
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700684 struct filter_block* block =
685 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obes53895402016-10-18 12:02:58 -0400686 ASSERT_EQ(block, nullptr);
687}
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400688
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400689TEST_F(ArgFilterTest, extra_chars_in_arg_token) {
690 const char* fragment = "arg0n == 0";
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400691
692 struct filter_block* block =
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700693 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400694 ASSERT_EQ(block, nullptr);
695}
696
697TEST_F(ArgFilterTest, invalid_operator) {
698 const char* fragment = "arg0 invalidop 0";
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400699
700 struct filter_block* block =
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700701 compile_policy_line(&state_, 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_constant) {
706 const char *fragment = "arg0 == INVALIDCONSTANT";
Jorge Lucangeli Obes53895402016-10-18 12:02:58 -0400707
708 struct filter_block* block =
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700709 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obes53895402016-10-18 12:02:58 -0400710 ASSERT_EQ(block, nullptr);
711}
712
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400713TEST_F(ArgFilterTest, extra_tokens) {
714 const char* fragment = "arg0 == 0 EXTRATOKEN";
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400715
716 struct filter_block* block =
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700717 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -0400718 ASSERT_EQ(block, nullptr);
719}
720
Jorge Lucangeli Obes53895402016-10-18 12:02:58 -0400721TEST_F(ArgFilterTest, invalid_errno) {
722 const char *fragment = "arg0 == 0 && arg1 == 1; return errno";
Jorge Lucangeli Obes53895402016-10-18 12:02:58 -0400723
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700724 struct filter_block* block =
725 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obes53895402016-10-18 12:02:58 -0400726 ASSERT_EQ(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400727}
728
729TEST_F(ArgFilterTest, log_no_ret_error) {
730 const char *fragment = "arg0 == 0";
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700731
732 struct filter_block* block =
733 compile_policy_line(&state_, nr_, fragment, id_, &labels_, USE_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400734
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400735 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400736 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
737 EXPECT_EQ(block->total_len, exp_total_len);
738
739 /* First block is a label. */
740 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400741 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400742 EXPECT_EQ(curr_block->len, 1U);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400743 EXPECT_LBL(curr_block->instrs);
744
745 /* Second block is a comparison. */
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400746 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400747 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400748 EXPECT_COMP(curr_block);
749
750 /* Third block is a jump and a label (end of AND group). */
751 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400752 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400753 EXPECT_GROUP_END(curr_block);
754
755 /* Fourth block is SECCOMP_RET_TRAP, with no errno. */
756 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400757 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400758 EXPECT_TRAP(curr_block);
759
760 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
761 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400762 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400763 EXPECT_ALLOW(curr_block);
764
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400765 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400766
767 free_block_list(block);
768}
769
770TEST_F(ArgFilterTest, log_bad_ret_error) {
771 const char *fragment = "arg0 == 0; return";
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400772
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700773 struct filter_block* block =
774 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING);
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400775 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400776 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
777 EXPECT_EQ(block->total_len, exp_total_len);
778
779 /* First block is a label. */
780 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400781 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400782 EXPECT_EQ(curr_block->len, 1U);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400783 EXPECT_LBL(curr_block->instrs);
784
785 /* Second block is a comparison ("arg0 == 0"). */
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_COMP(curr_block);
789
790 /* Third block is a jump and a label (end of AND group). */
791 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400792 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400793 EXPECT_GROUP_END(curr_block);
794
795 /*
796 * Sixth block is NOT SECCOMP_RET_ERRNO, it should be SECCOMP_RET_KILL.
797 */
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_KILL(curr_block);
801
802 /* Seventh block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
803 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400804 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400805 EXPECT_ALLOW(curr_block);
806
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400807 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400808
809 free_block_list(block);
810}
811
812TEST_F(ArgFilterTest, no_log_bad_ret_error) {
813 const char *fragment = "arg0 == 0; return";
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400814
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700815 struct filter_block* block =
816 compile_policy_line(&state_, nr_, fragment, id_, &labels_, USE_LOGGING);
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400817 ASSERT_NE(block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400818 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
819 EXPECT_EQ(block->total_len, exp_total_len);
820
821 /* First block is a label. */
822 struct filter_block *curr_block = block;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400823 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400824 EXPECT_EQ(curr_block->len, 1U);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400825 EXPECT_LBL(curr_block->instrs);
826
827 /* Second block is a comparison ("arg0 == 0"). */
828 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400829 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400830 EXPECT_COMP(curr_block);
831
832 /* Third block is a jump and a label (end of AND group). */
833 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400834 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400835 EXPECT_GROUP_END(curr_block);
836
837 /*
838 * Sixth block is *not* SECCOMP_RET_ERRNO, it should be
839 * SECCOMP_RET_TRAP.
840 */
841 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400842 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400843 EXPECT_TRAP(curr_block);
844
845 /* Seventh block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
846 curr_block = curr_block->next;
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400847 ASSERT_NE(curr_block, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400848 EXPECT_ALLOW(curr_block);
849
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -0400850 EXPECT_EQ(curr_block->next, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -0400851
852 free_block_list(block);
853}
854
855FILE *write_policy_to_pipe(const char *policy, size_t len) {
856 int pipefd[2];
857 if (pipe(pipefd) == -1) {
858 pwarn("pipe(pipefd) failed");
859 return NULL;
860 }
861
862 size_t i = 0;
863 unsigned int attempts = 0;
864 ssize_t ret;
865 while (i < len) {
866 ret = write(pipefd[1], &policy[i], len - i);
867 if (ret == -1) {
868 close(pipefd[0]);
869 close(pipefd[1]);
870 return NULL;
871 }
872
873 /* If we write 0 bytes three times in a row, fail. */
874 if (ret == 0) {
875 if (++attempts >= 3) {
876 close(pipefd[0]);
877 close(pipefd[1]);
878 warn("write() returned 0 three times in a row");
879 return NULL;
880 }
881 continue;
882 }
883
884 attempts = 0;
885 i += (size_t)ret;
886 }
887
888 close(pipefd[1]);
889 return fdopen(pipefd[0], "r");
890}
891
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400892class FileTest : public ::testing::Test {
893 protected:
894 virtual void SetUp() {
895 labels_.count = 0;
896 head_ = new_filter_block();
897 arg_blocks_ = NULL;
898 }
899 virtual void TearDown() {
900 free_label_strings(&labels_);
901 free_block_list(head_);
902 free_block_list(arg_blocks_);
903 }
904 struct bpf_labels labels_;
905 struct filter_block *head_;
906 struct filter_block *arg_blocks_;
907};
908
lhchavezd0b40702017-09-01 04:17:41 +0000909TEST_F(FileTest, malformed_policy) {
910 const char *policy =
911 "malformed";
912
913 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
914 ASSERT_NE(policy_file, nullptr);
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700915 int res = compile_file("policy", policy_file, head_, &arg_blocks_, &labels_,
916 USE_RET_KILL, NO_LOGGING, 0);
lhchavezd0b40702017-09-01 04:17:41 +0000917 fclose(policy_file);
918
919 /*
920 * Policy is malformed, but process should not crash.
921 */
922 ASSERT_EQ(res, -1);
923}
924
lhchavezd38280c2017-09-01 14:00:05 +0000925TEST_F(FileTest, double_free_on_compile_error) {
926 const char *policy =
927 "read:arg0 == 0\n"
928 "write:0";
929
930 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
931 ASSERT_NE(policy_file, nullptr);
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700932 int res = compile_file("policy", policy_file, head_, &arg_blocks_, &labels_,
933 USE_RET_KILL, NO_LOGGING, 0);
lhchavezd38280c2017-09-01 14:00:05 +0000934 fclose(policy_file);
935
936 /*
937 * Policy is malformed, but process should not crash.
938 */
939 ASSERT_EQ(res, -1);
940}
941
Luis Hector Chavez52f3dd72017-09-01 19:14:22 -0700942TEST_F(FileTest, invalid_return) {
943 const char *policy =
944 "read:arg0 == 0; ;";
945
946 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
947 ASSERT_NE(policy_file, nullptr);
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700948 int res = compile_file("policy", policy_file, head_, &arg_blocks_, &labels_,
949 USE_RET_KILL, NO_LOGGING, 0);
Luis Hector Chavez52f3dd72017-09-01 19:14:22 -0700950 fclose(policy_file);
951
952 /*
953 * Policy is malformed, but process should not crash.
954 */
955 ASSERT_EQ(res, -1);
956}
957
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400958TEST_F(FileTest, seccomp_mode1) {
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400959 const char *policy =
960 "read: 1\n"
961 "write: 1\n"
962 "rt_sigreturn: 1\n"
963 "exit: 1\n";
964
965 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
966 ASSERT_NE(policy_file, nullptr);
Luis Hector Chavez7624e712017-08-28 19:30:59 -0700967 int res = compile_file("policy", policy_file, head_, &arg_blocks_, &labels_,
968 USE_RET_KILL, NO_LOGGING, 0);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -0400969 fclose(policy_file);
970
971 /*
972 * Checks return value and that the blocks only allow expected syscalls.
973 */
974 ASSERT_EQ(res, 0);
975 struct filter_block *curr_block = head_;
976 ASSERT_NE(curr_block, nullptr);
977 EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_read);
978 curr_block = curr_block->next;
979 ASSERT_NE(curr_block, nullptr);
980 EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_write);
981 curr_block = curr_block->next;
982 ASSERT_NE(curr_block, nullptr);
983 EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_rt_sigreturn);
984 curr_block = curr_block->next;
985 ASSERT_NE(curr_block, nullptr);
986 EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_exit);
987
988 EXPECT_EQ(curr_block->next, nullptr);
989}
990
991TEST_F(FileTest, seccomp_read) {
992 const char *policy =
993 "read: arg0 == 0\n"
994 "write: 1\n"
995 "rt_sigreturn: 1\n"
996 "exit: 1\n";
997
998 const int LABEL_ID = 0;
999
1000 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
1001 ASSERT_NE(policy_file, nullptr);
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001002 int res = compile_file("policy", policy_file, head_, &arg_blocks_, &labels_,
1003 USE_RET_KILL, NO_LOGGING, 0);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -04001004 fclose(policy_file);
1005
1006 /*
1007 * Checks return value, that the blocks only allow expected syscalls, and that
1008 * labels between |head_| and |arg_blocks_| match.
1009 */
1010 ASSERT_EQ(res, 0);
1011 struct filter_block *curr_block = head_;
1012 ASSERT_NE(curr_block, nullptr);
1013 EXPECT_ALLOW_SYSCALL_ARGS(curr_block->instrs,
1014 __NR_read,
1015 LABEL_ID,
1016 JUMP_JT,
1017 JUMP_JF);
1018 curr_block = curr_block->next;
1019 ASSERT_NE(curr_block, nullptr);
1020 EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_write);
1021 curr_block = curr_block->next;
1022 ASSERT_NE(curr_block, nullptr);
1023 EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_rt_sigreturn);
1024 curr_block = curr_block->next;
1025 ASSERT_NE(curr_block, nullptr);
1026 EXPECT_ALLOW_SYSCALL(curr_block->instrs, __NR_exit);
1027
1028 ASSERT_NE(arg_blocks_, nullptr);
1029 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
1030 EXPECT_EQ(arg_blocks_->total_len, exp_total_len);
1031
1032 /* First block is a label. */
1033 curr_block = arg_blocks_;
1034 ASSERT_NE(curr_block, nullptr);
1035 EXPECT_EQ(curr_block->len, 1U);
1036 EXPECT_ACTUAL_LBL(curr_block->instrs, LABEL_ID);
1037
1038 /* Second block is a comparison. */
1039 curr_block = curr_block->next;
1040 EXPECT_COMP(curr_block);
1041
1042 /* Third block is a jump and a label (end of AND group). */
1043 curr_block = curr_block->next;
1044 ASSERT_NE(curr_block, nullptr);
1045 EXPECT_GROUP_END(curr_block);
1046
1047 /* Fourth block is SECCOMP_RET_KILL. */
1048 curr_block = curr_block->next;
1049 ASSERT_NE(curr_block, nullptr);
1050 EXPECT_KILL(curr_block);
1051
1052 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */
1053 curr_block = curr_block->next;
1054 ASSERT_NE(curr_block, nullptr);
1055 EXPECT_ALLOW(curr_block);
1056
1057 EXPECT_EQ(curr_block->next, nullptr);
1058}
1059
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001060TEST(FilterTest, seccomp_mode1) {
1061 struct sock_fprog actual;
1062 const char *policy =
1063 "read: 1\n"
1064 "write: 1\n"
1065 "rt_sigreturn: 1\n"
1066 "exit: 1\n";
1067
1068 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -04001069 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001070
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001071 int res =
1072 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001073 fclose(policy_file);
1074
1075 /*
1076 * Checks return value, filter length, and that the filter
1077 * validates arch, loads syscall number, and
1078 * only allows expected syscalls.
1079 */
1080 ASSERT_EQ(res, 0);
1081 EXPECT_EQ(actual.len, 13);
1082 EXPECT_ARCH_VALIDATION(actual.filter);
1083 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
1084 BPF_LD + BPF_W + BPF_ABS,
1085 syscall_nr);
1086 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 1, __NR_read);
1087 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 3, __NR_write);
1088 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 5,
1089 __NR_rt_sigreturn);
1090 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 7, __NR_exit);
1091 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN + 9,
1092 BPF_RET + BPF_K,
1093 SECCOMP_RET_KILL);
1094
1095 free(actual.filter);
1096}
1097
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -04001098TEST(FilterTest, seccomp_mode1_trap) {
1099 struct sock_fprog actual;
1100 const char *policy =
1101 "read: 1\n"
1102 "write: 1\n"
1103 "rt_sigreturn: 1\n"
1104 "exit: 1\n";
1105
1106 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -04001107 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -04001108
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001109 int res =
1110 compile_filter("policy", policy_file, &actual, USE_RET_TRAP, NO_LOGGING);
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -04001111 fclose(policy_file);
1112
1113 /*
1114 * Checks return value, filter length, and that the filter
1115 * validates arch, loads syscall number, and
1116 * only allows expected syscalls.
1117 */
1118 ASSERT_EQ(res, 0);
1119 EXPECT_EQ(actual.len, 13);
1120 EXPECT_ARCH_VALIDATION(actual.filter);
1121 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
1122 BPF_LD+BPF_W+BPF_ABS, syscall_nr);
1123 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 1,
1124 __NR_read);
1125 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 3,
1126 __NR_write);
1127 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 5,
1128 __NR_rt_sigreturn);
1129 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 7,
1130 __NR_exit);
1131 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN + 9, BPF_RET+BPF_K,
1132 SECCOMP_RET_TRAP);
1133
1134 free(actual.filter);
1135}
1136
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001137TEST(FilterTest, seccomp_read_write) {
1138 struct sock_fprog actual;
1139 const char *policy =
1140 "read: arg0 == 0\n"
1141 "write: arg0 == 1 || arg0 == 2\n"
1142 "rt_sigreturn: 1\n"
1143 "exit: 1\n";
1144
1145 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -04001146 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001147
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001148 int res =
1149 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001150 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, jumping to correct arg filter
1156 * offsets.
1157 */
1158 ASSERT_EQ(res, 0);
1159 size_t exp_total_len = 27 + 3 * (BPF_ARG_COMP_LEN + 1);
1160 EXPECT_EQ(actual.len, exp_total_len);
1161
1162 EXPECT_ARCH_VALIDATION(actual.filter);
1163 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
1164 BPF_LD + BPF_W + BPF_ABS,
1165 syscall_nr);
1166 EXPECT_ALLOW_SYSCALL_ARGS(
1167 actual.filter + ARCH_VALIDATION_LEN + 1, __NR_read, 7, 0, 0);
1168 EXPECT_ALLOW_SYSCALL_ARGS(actual.filter + ARCH_VALIDATION_LEN + 3,
1169 __NR_write,
1170 12 + BPF_ARG_COMP_LEN,
1171 0,
1172 0);
1173 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 5,
1174 __NR_rt_sigreturn);
1175 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 7, __NR_exit);
1176 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN + 9,
1177 BPF_RET + BPF_K,
1178 SECCOMP_RET_KILL);
1179
1180 free(actual.filter);
1181}
1182
Jorge Lucangeli Obesc4992572017-04-28 10:49:01 -04001183TEST(FilterTest, misplaced_whitespace) {
1184 struct sock_fprog actual;
1185 const char *policy = "open :1\n";
1186
1187 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
1188 ASSERT_NE(policy_file, nullptr);
1189
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001190 int res =
1191 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obesc4992572017-04-28 10:49:01 -04001192 fclose(policy_file);
1193
1194 /* Checks return value and filter length. */
1195 ASSERT_EQ(res, 0);
1196 EXPECT_EQ(actual.len,
1197 ARCH_VALIDATION_LEN + 1 /* load syscall nr */ + ALLOW_SYSCALL_LEN +
1198 1 /* ret kill */);
1199 free(actual.filter);
1200}
1201
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -04001202TEST(FilterTest, missing_atom) {
1203 struct sock_fprog actual;
1204 const char* policy = "open:\n";
1205
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001206 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -04001207 ASSERT_NE(policy_file, nullptr);
1208
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001209 int res =
1210 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -04001211 fclose(policy_file);
1212 ASSERT_NE(res, 0);
1213}
1214
1215TEST(FilterTest, whitespace_atom) {
1216 struct sock_fprog actual;
1217 const char* policy = "open:\t \n";
1218
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001219 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obes45932a52017-03-15 17:02:58 -04001220 ASSERT_NE(policy_file, nullptr);
1221
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001222 int res =
1223 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obes1a122b82016-11-01 11:59:33 -04001224 fclose(policy_file);
1225 ASSERT_NE(res, 0);
1226}
1227
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001228TEST(FilterTest, invalid_name) {
1229 struct sock_fprog actual;
1230 const char *policy = "notasyscall: 1\n";
1231
1232 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -04001233 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001234
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001235 int res =
1236 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001237 fclose(policy_file);
1238 ASSERT_NE(res, 0);
1239}
1240
1241TEST(FilterTest, invalid_arg) {
1242 struct sock_fprog actual;
1243 const char *policy = "open: argnn ==\n";
1244
1245 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -04001246 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001247
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001248 int res =
1249 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001250 fclose(policy_file);
1251 ASSERT_NE(res, 0);
1252}
1253
Mike Frysingerb4c7e772018-01-17 17:40:15 -05001254TEST(FilterTest, invalid_tokens) {
1255 struct sock_fprog actual;
1256 const char *policy = "read: arg0 == 1 |||| arg0 == 2\n";
1257
1258 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
1259 ASSERT_NE(policy_file, nullptr);
1260
1261 int res =
1262 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
1263 fclose(policy_file);
1264 ASSERT_NE(res, 0);
1265}
1266
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001267TEST(FilterTest, nonexistent) {
1268 struct sock_fprog actual;
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001269 int res = compile_filter("policy", NULL, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001270 ASSERT_NE(res, 0);
1271}
1272
1273TEST(FilterTest, log) {
1274 struct sock_fprog actual;
1275 const char *policy =
1276 "read: 1\n"
1277 "write: 1\n"
1278 "rt_sigreturn: 1\n"
1279 "exit: 1\n";
1280
1281 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -04001282 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001283
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001284 int res =
1285 compile_filter("policy", policy_file, &actual, USE_RET_TRAP, USE_LOGGING);
Jorge Lucangeli Obes106d97f2016-08-19 12:34:02 -04001286 fclose(policy_file);
1287
1288 size_t i;
1289 size_t index = 0;
1290 /*
1291 * Checks return value, filter length, and that the filter
1292 * validates arch, loads syscall number, only allows expected syscalls,
1293 * and returns TRAP on failure.
1294 * NOTE(jorgelo): the filter is longer since we add the syscalls needed
1295 * for logging.
1296 */
1297 ASSERT_EQ(res, 0);
1298 EXPECT_EQ(actual.len, 13 + 2 * log_syscalls_len);
1299 EXPECT_ARCH_VALIDATION(actual.filter);
1300 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
1301 BPF_LD + BPF_W + BPF_ABS,
1302 syscall_nr);
1303
1304 index = ARCH_VALIDATION_LEN + 1;
1305 for (i = 0; i < log_syscalls_len; i++)
1306 EXPECT_ALLOW_SYSCALL(actual.filter + (index + 2 * i),
1307 lookup_syscall(log_syscalls[i]));
1308
1309 index += 2 * log_syscalls_len;
1310
1311 EXPECT_ALLOW_SYSCALL(actual.filter + index, __NR_read);
1312 EXPECT_ALLOW_SYSCALL(actual.filter + index + 2, __NR_write);
1313 EXPECT_ALLOW_SYSCALL(actual.filter + index + 4, __NR_rt_sigreturn);
1314 EXPECT_ALLOW_SYSCALL(actual.filter + index + 6, __NR_exit);
1315 EXPECT_EQ_STMT(actual.filter + index + 8, BPF_RET + BPF_K, SECCOMP_RET_TRAP);
1316
1317 free(actual.filter);
1318}
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -04001319
1320TEST(FilterTest, allow_log_but_kill) {
1321 struct sock_fprog actual;
1322 const char *policy =
1323 "read: 1\n"
1324 "write: 1\n"
1325 "rt_sigreturn: 1\n"
1326 "exit: 1\n";
1327
1328 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
Jorge Lucangeli Obese9740af2016-11-02 13:39:24 -04001329 ASSERT_NE(policy_file, nullptr);
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -04001330
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001331 int res =
1332 compile_filter("policy", policy_file, &actual, USE_RET_KILL, USE_LOGGING);
Jorge Lucangeli Obes713f6fb2016-10-03 13:03:25 -04001333 fclose(policy_file);
1334
1335 size_t i;
1336 size_t index = 0;
1337 /*
1338 * Checks return value, filter length, and that the filter
1339 * validates arch, loads syscall number, only allows expected syscalls,
1340 * and returns TRAP on failure.
1341 * NOTE(jorgelo): the filter is longer since we add the syscalls needed
1342 * for logging.
1343 */
1344 ASSERT_EQ(res, 0);
1345 EXPECT_EQ(actual.len, 13 + 2 * log_syscalls_len);
1346 EXPECT_ARCH_VALIDATION(actual.filter);
1347 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
1348 BPF_LD+BPF_W+BPF_ABS, syscall_nr);
1349
1350 index = ARCH_VALIDATION_LEN + 1;
1351 for (i = 0; i < log_syscalls_len; i++)
1352 EXPECT_ALLOW_SYSCALL(actual.filter + (index + 2 * i),
1353 lookup_syscall(log_syscalls[i]));
1354
1355 index += 2 * log_syscalls_len;
1356
1357 EXPECT_ALLOW_SYSCALL(actual.filter + index, __NR_read);
1358 EXPECT_ALLOW_SYSCALL(actual.filter + index + 2, __NR_write);
1359 EXPECT_ALLOW_SYSCALL(actual.filter + index + 4, __NR_rt_sigreturn);
1360 EXPECT_ALLOW_SYSCALL(actual.filter + index + 6, __NR_exit);
1361 EXPECT_EQ_STMT(actual.filter + index + 8, BPF_RET+BPF_K,
1362 SECCOMP_RET_KILL);
1363
1364 free(actual.filter);
1365}
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001366
1367TEST(FilterTest, include_invalid_token) {
1368 struct sock_fprog actual;
1369 const char *invalid_token = "@unclude ./test/seccomp.policy\n";
1370
1371 FILE *policy_file =
1372 write_policy_to_pipe(invalid_token, strlen(invalid_token));
1373 ASSERT_NE(policy_file, nullptr);
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001374 int res =
1375 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001376 fclose(policy_file);
1377 EXPECT_NE(res, 0);
1378}
1379
1380TEST(FilterTest, include_no_space) {
1381 struct sock_fprog actual;
1382 const char *no_space = "@includetest/seccomp.policy\n";
1383
1384 FILE *policy_file = write_policy_to_pipe(no_space, strlen(no_space));
1385 ASSERT_NE(policy_file, nullptr);
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001386 int res =
1387 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001388 fclose(policy_file);
1389 EXPECT_NE(res, 0);
1390}
1391
1392TEST(FilterTest, include_double_token) {
1393 struct sock_fprog actual;
1394 const char *double_token = "@includeinclude ./test/seccomp.policy\n";
1395
1396 FILE *policy_file = write_policy_to_pipe(double_token, strlen(double_token));
1397 ASSERT_NE(policy_file, nullptr);
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001398 int res =
1399 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001400 fclose(policy_file);
1401 EXPECT_NE(res, 0);
1402}
1403
1404TEST(FilterTest, include_no_file) {
1405 struct sock_fprog actual;
1406 const char *no_file = "@include\n";
1407
1408 FILE *policy_file = write_policy_to_pipe(no_file, strlen(no_file));
1409 ASSERT_NE(policy_file, nullptr);
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001410 int res =
1411 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001412 fclose(policy_file);
1413 EXPECT_NE(res, 0);
1414}
1415
1416TEST(FilterTest, include_space_no_file) {
1417 struct sock_fprog actual;
1418 const char *space_no_file = "@include \n";
1419
1420 FILE *policy_file =
1421 write_policy_to_pipe(space_no_file, strlen(space_no_file));
1422 ASSERT_NE(policy_file, nullptr);
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001423 int res =
1424 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001425 fclose(policy_file);
1426 EXPECT_NE(res, 0);
1427}
1428
1429TEST(FilterTest, include_implicit_relative_path) {
1430 struct sock_fprog actual;
1431 const char *implicit_relative_path = "@include test/seccomp.policy\n";
1432
1433 FILE *policy_file = write_policy_to_pipe(implicit_relative_path,
1434 strlen(implicit_relative_path));
1435 ASSERT_NE(policy_file, nullptr);
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001436 int res =
1437 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001438 fclose(policy_file);
1439 EXPECT_NE(res, 0);
1440}
1441
1442TEST(FilterTest, include_extra_text) {
1443 struct sock_fprog actual;
1444 const char *extra_text = "@include /some/file: sneaky comment\n";
1445
1446 FILE *policy_file =
1447 write_policy_to_pipe(extra_text, strlen(extra_text));
1448 ASSERT_NE(policy_file, nullptr);
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001449 int res =
1450 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001451 fclose(policy_file);
1452 EXPECT_NE(res, 0);
1453}
1454
1455TEST(FilterTest, include_split_filename) {
1456 struct sock_fprog actual;
1457 const char *split_filename = "@include /some/file:colon.policy\n";
1458
1459 FILE *policy_file =
1460 write_policy_to_pipe(split_filename, strlen(split_filename));
1461 ASSERT_NE(policy_file, nullptr);
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001462 int res =
1463 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001464 fclose(policy_file);
1465 EXPECT_NE(res, 0);
1466}
1467
1468TEST(FilterTest, include_nonexistent_file) {
1469 struct sock_fprog actual;
1470 const char *include_policy = "@include ./nonexistent.policy\n";
1471
1472 FILE *policy_file =
1473 write_policy_to_pipe(include_policy, strlen(include_policy));
1474 ASSERT_NE(policy_file, nullptr);
1475
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001476 int res =
1477 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001478 fclose(policy_file);
1479
1480 ASSERT_NE(res, 0);
1481}
1482
1483// TODO(jorgelo): Android unit tests don't currently support data files.
1484// Re-enable by creating a temporary policy file at runtime.
1485#if !defined(__ANDROID__)
1486
1487TEST(FilterTest, include) {
1488 struct sock_fprog compiled_plain;
1489 struct sock_fprog compiled_with_include;
1490
1491 const char *policy_plain =
1492 "read: 1\n"
1493 "write: 1\n"
1494 "rt_sigreturn: 1\n"
1495 "exit: 1\n";
1496
1497 const char *policy_with_include = "@include ./test/seccomp.policy\n";
1498
1499 FILE *file_plain = write_policy_to_pipe(policy_plain, strlen(policy_plain));
1500 ASSERT_NE(file_plain, nullptr);
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001501 int res_plain = compile_filter("policy", file_plain, &compiled_plain,
1502 USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001503 fclose(file_plain);
1504
1505 FILE *file_with_include =
1506 write_policy_to_pipe(policy_with_include, strlen(policy_with_include));
1507 ASSERT_NE(file_with_include, nullptr);
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001508 int res_with_include =
1509 compile_filter("policy", file_with_include, &compiled_with_include,
1510 USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001511 fclose(file_with_include);
1512
1513 /*
1514 * Checks that filter length is the same for a plain policy and an equivalent
1515 * policy with an @include statement. Also checks that the filter generated
1516 * from the policy with an @include statement is exactly the same as one
1517 * generated from a plain policy.
1518 */
1519 ASSERT_EQ(res_plain, 0);
1520 ASSERT_EQ(res_with_include, 0);
1521
1522 EXPECT_EQ(compiled_plain.len, 13);
1523 EXPECT_EQ(compiled_with_include.len, 13);
1524
1525 EXPECT_ARCH_VALIDATION(compiled_with_include.filter);
1526 EXPECT_EQ_STMT(compiled_with_include.filter + ARCH_VALIDATION_LEN,
1527 BPF_LD + BPF_W + BPF_ABS,
1528 syscall_nr);
1529 EXPECT_ALLOW_SYSCALL(compiled_with_include.filter + ARCH_VALIDATION_LEN + 1,
1530 __NR_read);
1531 EXPECT_ALLOW_SYSCALL(compiled_with_include.filter + ARCH_VALIDATION_LEN + 3,
1532 __NR_write);
1533 EXPECT_ALLOW_SYSCALL(compiled_with_include.filter + ARCH_VALIDATION_LEN + 5,
1534 __NR_rt_sigreturn);
1535 EXPECT_ALLOW_SYSCALL(compiled_with_include.filter + ARCH_VALIDATION_LEN + 7,
1536 __NR_exit);
1537 EXPECT_EQ_STMT(compiled_with_include.filter + ARCH_VALIDATION_LEN + 9,
1538 BPF_RET + BPF_K,
1539 SECCOMP_RET_KILL);
1540
1541 free(compiled_plain.filter);
1542 free(compiled_with_include.filter);
1543}
1544
1545TEST(FilterTest, include_same_syscalls) {
1546 struct sock_fprog actual;
1547 const char *policy =
1548 "read: 1\n"
1549 "write: 1\n"
1550 "rt_sigreturn: 1\n"
1551 "exit: 1\n"
1552 "@include ./test/seccomp.policy\n";
1553
1554 FILE *policy_file =
1555 write_policy_to_pipe(policy, strlen(policy));
1556 ASSERT_NE(policy_file, nullptr);
1557
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001558 int res =
1559 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001560 fclose(policy_file);
1561
1562 ASSERT_EQ(res, 0);
1563 EXPECT_EQ(actual.len,
1564 ARCH_VALIDATION_LEN + 1 /* load syscall nr */ +
1565 2 * 8 /* check syscalls twice */ + 1 /* filter return */);
1566 free(actual.filter);
1567}
1568
1569TEST(FilterTest, include_invalid_policy) {
1570 struct sock_fprog actual;
1571 const char *policy =
1572 "read: 1\n"
1573 "write: 1\n"
1574 "rt_sigreturn: 1\n"
1575 "exit: 1\n"
1576 "@include ./test/invalid_syscall_name.policy\n";
1577
1578 FILE *policy_file =
1579 write_policy_to_pipe(policy, strlen(policy));
1580 ASSERT_NE(policy_file, nullptr);
1581
1582 /* Ensure the included (invalid) policy file exists. */
1583 FILE *included_file = fopen("./test/invalid_syscall_name.policy", "r");
1584 ASSERT_NE(included_file, nullptr);
1585 fclose(included_file);
1586
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001587 int res =
1588 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001589 fclose(policy_file);
1590
1591 ASSERT_NE(res, 0);
1592}
1593
1594TEST(FilterTest, include_nested) {
1595 struct sock_fprog actual;
1596 const char *policy = "@include ./test/nested.policy\n";
1597
1598 FILE *policy_file =
1599 write_policy_to_pipe(policy, strlen(policy));
1600 ASSERT_NE(policy_file, nullptr);
1601
1602 /* Ensure the policy file exists. */
1603 FILE *included_file = fopen("./test/nested.policy", "r");
1604 ASSERT_NE(included_file, nullptr);
1605 fclose(included_file);
1606
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001607 int res =
1608 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001609 fclose(policy_file);
1610
1611 ASSERT_NE(res, 0);
1612}
1613
Luis Hector Chavez1a87c8a2017-09-02 13:18:31 -07001614TEST(FilterTest, error_cleanup_leak) {
1615 struct sock_fprog actual;
1616 const char *policy =
1617 "read:&&\n"
1618 "read:&&";
1619
1620 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy));
1621 ASSERT_NE(policy_file, nullptr);
Luis Hector Chavez7624e712017-08-28 19:30:59 -07001622 int res =
1623 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING);
Luis Hector Chavez1a87c8a2017-09-02 13:18:31 -07001624 fclose(policy_file);
1625
1626 /*
1627 * Policy is malformed, but process should not leak.
1628 */
1629 ASSERT_EQ(res, -1);
1630}
1631
Jorge Lucangeli Obesbce4ccb2017-03-20 13:38:43 -04001632#endif // !__ANDROID__