blob: b0d4acdda76381369cc0a7ad24d5f1631e2e520d [file] [log] [blame]
Jorge Lucangeli Obesfc8ab532012-03-20 10:14:31 -07001/* syscall_filter_unittest.c
Jorge Lucangeli Obes6135db92012-07-27 13:37:30 -07002 * Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Jorge Lucangeli Obesfc8ab532012-03-20 10:14:31 -07003 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 *
6 * Test syscall filtering.
7 */
8
Jorge Lucangeli Obesd4467262012-03-23 16:19:59 -07009#include <asm/unistd.h>
Jorge Lucangeli Obesfc8ab532012-03-20 10:14:31 -070010#include <errno.h>
Jorge Lucangeli Obesffec8912012-11-30 14:46:23 -080011#include <fcntl.h> /* For O_WRONLY */
Jorge Lucangeli Obesfc8ab532012-03-20 10:14:31 -070012
13#include "test_harness.h"
14
15#include "bpf.h"
16#include "syscall_filter.h"
17
Jorge Lucangeli Obesbda833c2012-07-31 16:25:56 -070018#include "util.h"
19
Jorge Lucangeli Obesfc8ab532012-03-20 10:14:31 -070020/* BPF testing macros. */
21#define EXPECT_EQ_BLOCK(_block, _code, _k, _jt, _jf) \
22do { \
23 EXPECT_EQ((_block)->code, _code); \
24 EXPECT_EQ((_block)->k, (unsigned int)(_k)); \
25 EXPECT_EQ((_block)->jt, _jt); \
26 EXPECT_EQ((_block)->jf, _jf); \
27} while (0)
28
29#define EXPECT_EQ_STMT(_block, _code, _k) \
30 EXPECT_EQ_BLOCK(_block, _code, _k, 0, 0)
31
32#define EXPECT_COMP(_block) \
33do { \
34 EXPECT_EQ((_block)->len, BPF_ARG_COMP_LEN + 1); \
35 EXPECT_EQ((_block)->instrs->code, BPF_LD+BPF_W+BPF_ABS); \
36} while (0)
37
38#define EXPECT_LBL(_block) \
39 do { \
40 EXPECT_EQ((_block)->code, BPF_JMP+BPF_JA); \
41 EXPECT_EQ((_block)->jt, LABEL_JT); \
42 EXPECT_EQ((_block)->jf, LABEL_JF); \
43} while (0)
44
45#define EXPECT_JUMP_LBL(_block) \
46do { \
47 EXPECT_EQ((_block)->code, BPF_JMP+BPF_JA); \
48 EXPECT_EQ((_block)->jt, JUMP_JT); \
49 EXPECT_EQ((_block)->jf, JUMP_JF); \
50} while (0)
51
52#define EXPECT_GROUP_END(_block) \
53do { \
54 EXPECT_EQ((_block)->len, 2U); \
55 EXPECT_JUMP_LBL(&(_block)->instrs[0]); \
56 EXPECT_LBL(&(_block)->instrs[1]); \
57} while (0)
58
59#define EXPECT_KILL(_block) \
60do { \
61 EXPECT_EQ((_block)->len, 1U); \
62 EXPECT_EQ_STMT(_block->instrs, \
63 BPF_RET+BPF_K, SECCOMP_RET_KILL); \
64} while (0)
65
66#define EXPECT_ALLOW(_block) \
67do { \
68 EXPECT_EQ((_block)->len, 2U); \
69 EXPECT_LBL(&(_block)->instrs[0]); \
70 EXPECT_EQ_STMT(&(_block)->instrs[1], \
71 BPF_RET+BPF_K, SECCOMP_RET_ALLOW); \
72} while (0)
73
Jorge Lucangeli Obesd4467262012-03-23 16:19:59 -070074#define EXPECT_ARCH_VALIDATION(_filter) \
75do { \
76 EXPECT_EQ_STMT(&(_filter)[0], BPF_LD+BPF_W+BPF_ABS, arch_nr); \
77 EXPECT_EQ_BLOCK(&(_filter)[1], \
78 BPF_JMP+BPF_JEQ+BPF_K, ARCH_NR, SKIP, NEXT); \
79 EXPECT_EQ_STMT(&(_filter)[2], BPF_RET+BPF_K, SECCOMP_RET_KILL); \
80} while (0)
81
82#define EXPECT_ALLOW_SYSCALL(_filter, _nr) \
83do { \
84 EXPECT_EQ_BLOCK(&(_filter)[0], \
85 BPF_JMP+BPF_JEQ+BPF_K, (_nr), NEXT, SKIP); \
86 EXPECT_EQ_STMT(&(_filter)[1], \
87 BPF_RET+BPF_K, SECCOMP_RET_ALLOW); \
88} while (0)
89
90#define EXPECT_ALLOW_SYSCALL_ARGS(_filter, _nr, _id, _jt, _jf) \
91do { \
92 EXPECT_EQ_BLOCK(&(_filter)[0], \
93 BPF_JMP+BPF_JEQ+BPF_K, (_nr), NEXT, SKIP); \
94 EXPECT_EQ_BLOCK(&(_filter)[1], \
95 BPF_JMP+BPF_JA, (_id), (_jt), (_jf)); \
96} while (0)
97
98
Jorge Lucangeli Obesfc8ab532012-03-20 10:14:31 -070099FIXTURE(bpf) {};
100
101FIXTURE_SETUP(bpf) {}
102FIXTURE_TEARDOWN(bpf) {}
103
Jorge Lucangeli Obesffec8912012-11-30 14:46:23 -0800104/* Test that setting one BPF instruction works. */
Jorge Lucangeli Obesfc8ab532012-03-20 10:14:31 -0700105TEST_F(bpf, set_bpf_instr) {
106 struct sock_filter instr;
107 unsigned char code = BPF_LD+BPF_W+BPF_ABS;
108 unsigned int k = 4;
109 unsigned char jt = 1, jf = 2;
110
111 size_t len = set_bpf_instr(&instr, code, k, jt, jf);
112
113 EXPECT_EQ(len, 1U);
114 EXPECT_EQ_BLOCK(&instr, code, k, jt, jf);
115}
116
117TEST_F(bpf, bpf_load_arg) {
118 struct sock_filter load_arg[BPF_LOAD_ARG_LEN];
119 int argidx = 1;
120 size_t len = bpf_load_arg(load_arg, argidx);
121
122 EXPECT_EQ(len, BPF_LOAD_ARG_LEN);
Jorge Lucangeli Obesedb1d8e2012-04-26 10:05:09 -0700123
124#if defined(BITS32)
125 EXPECT_EQ_STMT(&load_arg[0], BPF_LD+BPF_W+BPF_ABS, LO_ARG(argidx));
126#elif defined(BITS64)
Jorge Lucangeli Obesfc8ab532012-03-20 10:14:31 -0700127 EXPECT_EQ_STMT(&load_arg[0], BPF_LD+BPF_W+BPF_ABS, LO_ARG(argidx));
128 EXPECT_EQ_STMT(&load_arg[1], BPF_ST, 0);
129 EXPECT_EQ_STMT(&load_arg[2], BPF_LD+BPF_W+BPF_ABS, HI_ARG(argidx));
130 EXPECT_EQ_STMT(&load_arg[3], BPF_ST, 1);
Jorge Lucangeli Obesedb1d8e2012-04-26 10:05:09 -0700131#endif
Jorge Lucangeli Obesfc8ab532012-03-20 10:14:31 -0700132}
133
134TEST_F(bpf, bpf_comp_jeq) {
135 struct sock_filter comp_jeq[BPF_COMP_LEN];
136 unsigned long c = 1;
137 unsigned char jt = 1;
138 unsigned char jf = 2;
139
Jorge Lucangeli Obesedb1d8e2012-04-26 10:05:09 -0700140 size_t len = bpf_comp_jeq(comp_jeq, c, jt, jf);
Jorge Lucangeli Obesfc8ab532012-03-20 10:14:31 -0700141
142 EXPECT_EQ(len, BPF_COMP_LEN);
Jorge Lucangeli Obesedb1d8e2012-04-26 10:05:09 -0700143
144#if defined(BITS32)
Jorge Lucangeli Obesffec8912012-11-30 14:46:23 -0800145 EXPECT_EQ_BLOCK(&comp_jeq[0],
Jorge Lucangeli Obesedb1d8e2012-04-26 10:05:09 -0700146 BPF_JMP+BPF_JEQ+BPF_K, c, jt, jf);
147#elif defined(BITS64)
Jorge Lucangeli Obesfc8ab532012-03-20 10:14:31 -0700148 EXPECT_EQ_BLOCK(&comp_jeq[0],
149 BPF_JMP+BPF_JEQ+BPF_K, 0, 0, jf + 2);
150 EXPECT_EQ_STMT(&comp_jeq[1], BPF_LD+BPF_MEM, 0);
151 EXPECT_EQ_BLOCK(&comp_jeq[2],
152 BPF_JMP+BPF_JEQ+BPF_K, c, jt, jf);
Jorge Lucangeli Obesedb1d8e2012-04-26 10:05:09 -0700153#endif
Jorge Lucangeli Obesfc8ab532012-03-20 10:14:31 -0700154}
155
Jorge Lucangeli Obesffec8912012-11-30 14:46:23 -0800156TEST_F(bpf, bpf_comp_jset) {
157 struct sock_filter comp_jset[BPF_COMP_LEN];
158 unsigned long mask = O_WRONLY;
159 unsigned char jt = 1;
160 unsigned char jf = 2;
161
162 size_t len = bpf_comp_jset(comp_jset, mask, jt, jf);
163
164 EXPECT_EQ(len, BPF_COMP_LEN);
165
166#if defined(BITS32)
167 EXPECT_EQ_BLOCK(&comp_jset[0],
168 BPF_JMP+BPF_JSET+BPF_K, mask, jt, jf);
169#elif defined(BITS64)
170 EXPECT_EQ_BLOCK(&comp_jset[0],
171 BPF_JMP+BPF_JSET+BPF_K, 0, jt + 2, 0);
172 EXPECT_EQ_STMT(&comp_jset[1], BPF_LD+BPF_MEM, 0);
173 EXPECT_EQ_BLOCK(&comp_jset[2],
174 BPF_JMP+BPF_JSET+BPF_K, mask, jt, jf);
175#endif
176}
177
Jorge Lucangeli Obesfc8ab532012-03-20 10:14:31 -0700178TEST_F(bpf, bpf_arg_comp) {
179 struct sock_filter *arg_comp;
180 int op = EQ;
181 int argidx = 1;
182 unsigned long c = 3;
183 unsigned int label_id = 0;
184
185 size_t len = bpf_arg_comp(&arg_comp, op, argidx, c, label_id);
186
187 EXPECT_EQ(len, BPF_ARG_COMP_LEN + 1);
Jorge Lucangeli Obesedb1d8e2012-04-26 10:05:09 -0700188
189#if defined(BITS32)
190 EXPECT_EQ_STMT(&arg_comp[0],
191 BPF_LD+BPF_W+BPF_ABS, LO_ARG(argidx));
192 EXPECT_EQ_BLOCK(&arg_comp[1],
193 BPF_JMP+BPF_JEQ+BPF_K, c, 1, 0);
194 EXPECT_JUMP_LBL(&arg_comp[2]);
195#elif defined(BITS64)
Jorge Lucangeli Obesfc8ab532012-03-20 10:14:31 -0700196 EXPECT_EQ_STMT(&arg_comp[0],
197 BPF_LD+BPF_W+BPF_ABS, LO_ARG(argidx));
198 EXPECT_EQ_STMT(&arg_comp[1], BPF_ST, 0);
199 EXPECT_EQ_STMT(&arg_comp[2],
200 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],
204 BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 2);
205 EXPECT_EQ_STMT(&arg_comp[5], BPF_LD+BPF_MEM, 0);
206 EXPECT_EQ_BLOCK(&arg_comp[6],
207 BPF_JMP+BPF_JEQ+BPF_K, c, 1, 0);
208 EXPECT_JUMP_LBL(&arg_comp[7]);
Jorge Lucangeli Obesedb1d8e2012-04-26 10:05:09 -0700209#endif
Jorge Lucangeli Obesfc8ab532012-03-20 10:14:31 -0700210 free(arg_comp);
211}
212
Jorge Lucangeli Obesd4467262012-03-23 16:19:59 -0700213TEST_F(bpf, bpf_validate_arch) {
214 struct sock_filter validate_arch[ARCH_VALIDATION_LEN];
215
216 size_t len = bpf_validate_arch(validate_arch);
217
218 EXPECT_EQ(len, ARCH_VALIDATION_LEN);
219 EXPECT_ARCH_VALIDATION(validate_arch);
220}
221
222TEST_F(bpf, bpf_allow_syscall) {
223 struct sock_filter allow_syscall[ALLOW_SYSCALL_LEN];
224 int nr = 1;
225
226 size_t len = bpf_allow_syscall(allow_syscall, nr);
227
228 EXPECT_EQ(len, ALLOW_SYSCALL_LEN);
229 EXPECT_ALLOW_SYSCALL(allow_syscall, nr);
230}
231
232TEST_F(bpf, bpf_allow_syscall_args) {
233 struct sock_filter allow_syscall[ALLOW_SYSCALL_LEN];
234 int nr = 1;
235 unsigned int id = 1024;
236
237 size_t len = bpf_allow_syscall_args(allow_syscall, nr, id);
238
239 EXPECT_EQ(len, ALLOW_SYSCALL_LEN);
240 EXPECT_ALLOW_SYSCALL_ARGS(allow_syscall, nr, id, JUMP_JT, JUMP_JF);
241}
242
Jorge Lucangeli Obesfc8ab532012-03-20 10:14:31 -0700243FIXTURE(arg_filter) {
244 struct bpf_labels labels;
245};
246
247FIXTURE_SETUP(arg_filter) {}
248FIXTURE_TEARDOWN(arg_filter) {}
249
250TEST_F(arg_filter, arg0_equals) {
251 const char *fragment = "arg0 == 0";
252 int nr = 1;
253 unsigned int id = 0;
254 struct filter_block *block =
255 compile_section(nr, fragment, id, &self->labels);
256
257 ASSERT_NE(block, NULL);
Jorge Lucangeli Obesedb1d8e2012-04-26 10:05:09 -0700258 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
259 EXPECT_EQ(block->total_len, exp_total_len);
Jorge Lucangeli Obesfc8ab532012-03-20 10:14:31 -0700260
261 /* First block is a label. */
262 struct filter_block *curr_block = block;
263 ASSERT_NE(curr_block, NULL);
264 EXPECT_EQ(block->len, 1U);
265 EXPECT_LBL(curr_block->instrs);
266
267 /* Second block is a comparison. */
268 curr_block = block->next;
269 EXPECT_COMP(curr_block);
270
271 /* Third block is a jump and a label (end of AND group). */
272 curr_block = curr_block->next;
273 EXPECT_NE(curr_block, NULL);
274 EXPECT_GROUP_END(curr_block);
275
276 /* Fourth block is SECCOMP_RET_KILL */
277 curr_block = curr_block->next;
278 EXPECT_NE(curr_block, NULL);
279 EXPECT_KILL(curr_block);
280
281 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW */
282 curr_block = curr_block->next;
283 EXPECT_NE(curr_block, NULL);
284 EXPECT_ALLOW(curr_block);
285
286 EXPECT_EQ(curr_block->next, NULL);
287
288 free_block_list(block);
289 free_label_strings(&self->labels);
290}
291
Jorge Lucangeli Obes66cfc142012-11-30 15:42:52 -0800292TEST_F(arg_filter, arg0_mask) {
Luis Hector Chavez40b25742013-09-22 19:44:06 -0700293 const char *fragment = "arg1 & O_RDWR";
Jorge Lucangeli Obes66cfc142012-11-30 15:42:52 -0800294 int nr = 1;
295 unsigned int id = 0;
296 struct filter_block *block =
297 compile_section(nr, fragment, id, &self->labels);
298
299 ASSERT_NE(block, NULL);
300 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
301 EXPECT_EQ(block->total_len, exp_total_len);
302
303 /* First block is a label. */
304 struct filter_block *curr_block = block;
305 ASSERT_NE(curr_block, NULL);
306 EXPECT_EQ(block->len, 1U);
307 EXPECT_LBL(curr_block->instrs);
308
309 /* Second block is a comparison. */
310 curr_block = block->next;
311 EXPECT_COMP(curr_block);
312
313 /* Third block is a jump and a label (end of AND group). */
314 curr_block = curr_block->next;
315 EXPECT_NE(curr_block, NULL);
316 EXPECT_GROUP_END(curr_block);
317
318 /* Fourth block is SECCOMP_RET_KILL */
319 curr_block = curr_block->next;
320 EXPECT_NE(curr_block, NULL);
321 EXPECT_KILL(curr_block);
322
323 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW */
324 curr_block = curr_block->next;
325 EXPECT_NE(curr_block, NULL);
326 EXPECT_ALLOW(curr_block);
327
328 EXPECT_EQ(curr_block->next, NULL);
329
330 free_block_list(block);
331 free_label_strings(&self->labels);
332}
333
Luis Hector Chavez21224552015-06-27 18:10:39 +0000334TEST_F(arg_filter, arg0_eq_mask) {
335 const char *fragment = "arg1 == O_WRONLY|O_CREAT";
336 int nr = 1;
337 unsigned int id = 0;
338 struct filter_block *block =
339 compile_section(nr, fragment, id, &self->labels);
340
341 ASSERT_NE(block, NULL);
342 size_t exp_total_len = 1 + (BPF_ARG_COMP_LEN + 1) + 2 + 1 + 2;
343 EXPECT_EQ(block->total_len, exp_total_len);
344
345 /* First block is a label. */
346 struct filter_block *curr_block = block;
347 ASSERT_NE(curr_block, NULL);
348 EXPECT_EQ(block->len, 1U);
349 EXPECT_LBL(curr_block->instrs);
350
351 /* Second block is a comparison. */
352 curr_block = block->next;
353 EXPECT_COMP(curr_block);
354 EXPECT_EQ(curr_block->instrs[BPF_ARG_COMP_LEN - 1].k,
355 (unsigned int)(O_WRONLY | O_CREAT));
356
357 /* Third block is a jump and a label (end of AND group). */
358 curr_block = curr_block->next;
359 EXPECT_NE(curr_block, NULL);
360 EXPECT_GROUP_END(curr_block);
361
362 /* Fourth block is SECCOMP_RET_KILL */
363 curr_block = curr_block->next;
364 EXPECT_NE(curr_block, NULL);
365 EXPECT_KILL(curr_block);
366
367 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW */
368 curr_block = curr_block->next;
369 EXPECT_NE(curr_block, NULL);
370 EXPECT_ALLOW(curr_block);
371
372 EXPECT_EQ(curr_block->next, NULL);
373
374 free_block_list(block);
375 free_label_strings(&self->labels);
376}
377
Jorge Lucangeli Obesfc8ab532012-03-20 10:14:31 -0700378TEST_F(arg_filter, and_or) {
379 const char *fragment = "arg0 == 0 && arg1 == 0 || arg0 == 1";
380 int nr = 1;
381 unsigned int id = 0;
382
383 struct filter_block *block =
384 compile_section(nr, fragment, id, &self->labels);
385 ASSERT_NE(block, NULL);
Jorge Lucangeli Obesedb1d8e2012-04-26 10:05:09 -0700386 size_t exp_total_len = 1 + 3 * (BPF_ARG_COMP_LEN + 1) + 2 + 2 + 1 + 2;
387 EXPECT_EQ(block->total_len, exp_total_len);
Jorge Lucangeli Obesfc8ab532012-03-20 10:14:31 -0700388
389 /* First block is a label. */
390 struct filter_block *curr_block = block;
391 ASSERT_NE(curr_block, NULL);
392 EXPECT_EQ(block->len, 1U);
393 EXPECT_LBL(curr_block->instrs);
394
395 /* Second block is a comparison ("arg0 == 0"). */
396 curr_block = curr_block->next;
397 EXPECT_NE(curr_block, NULL);
398 EXPECT_COMP(curr_block);
399
400 /* Third block is a comparison ("arg1 == 0"). */
401 curr_block = curr_block->next;
402 EXPECT_NE(curr_block, NULL);
403 EXPECT_COMP(curr_block);
404
405 /* Fourth block is a jump and a label (end of AND group). */
406 curr_block = curr_block->next;
407 EXPECT_NE(curr_block, NULL);
408 EXPECT_GROUP_END(curr_block);
409
410 /* Fifth block is a comparison ("arg0 == 1"). */
411 curr_block = curr_block->next;
412 EXPECT_NE(curr_block, NULL);
413 EXPECT_COMP(curr_block);
414
415 /* Sixth block is a jump and a label (end of AND group). */
416 curr_block = curr_block->next;
417 EXPECT_NE(curr_block, NULL);
418 EXPECT_GROUP_END(curr_block);
419
420 /* Seventh block is SECCOMP_RET_KILL */
421 curr_block = curr_block->next;
422 EXPECT_NE(curr_block, NULL);
423 EXPECT_KILL(curr_block);
424
425 /* Eigth block is "SUCCESS" label and SECCOMP_RET_ALLOW */
426 curr_block = curr_block->next;
427 EXPECT_NE(curr_block, NULL);
428 EXPECT_ALLOW(curr_block);
429
430 EXPECT_EQ(curr_block->next, NULL);
431
432 free_block_list(block);
433 free_label_strings(&self->labels);
434}
435
436TEST_F(arg_filter, ret_errno) {
437 const char *fragment = "arg0 == 0 || arg0 == 1; return 1";
438 int nr = 1;
439 unsigned int id = 0;
440
441 struct filter_block *block =
442 compile_section(nr, fragment, id, &self->labels);
443 ASSERT_NE(block, NULL);
Jorge Lucangeli Obesedb1d8e2012-04-26 10:05:09 -0700444 size_t exp_total_len = 1 + 2 * (BPF_ARG_COMP_LEN + 1) + 2 + 2 + 1 + 2;
445 EXPECT_EQ(block->total_len, exp_total_len);
Jorge Lucangeli Obesfc8ab532012-03-20 10:14:31 -0700446
447 /* First block is a label. */
448 struct filter_block *curr_block = block;
449 ASSERT_NE(curr_block, NULL);
450 EXPECT_EQ(block->len, 1U);
451 EXPECT_LBL(curr_block->instrs);
452
453 /* Second block is a comparison ("arg0 == 0"). */
454 curr_block = curr_block->next;
455 EXPECT_NE(curr_block, NULL);
456 EXPECT_COMP(curr_block);
457
458 /* Third block is a jump and a label (end of AND group). */
459 curr_block = curr_block->next;
460 EXPECT_NE(curr_block, NULL);
461 EXPECT_GROUP_END(curr_block);
462
463 /* Fourth block is a comparison ("arg0 == 1"). */
464 curr_block = curr_block->next;
465 EXPECT_NE(curr_block, NULL);
466 EXPECT_COMP(curr_block);
467
468 /* Fifth block is a jump and a label (end of AND group). */
469 curr_block = curr_block->next;
470 EXPECT_NE(curr_block, NULL);
471 EXPECT_GROUP_END(curr_block);
472
473 /* Sixth block is SECCOMP_RET_ERRNO */
474 curr_block = curr_block->next;
475 EXPECT_NE(curr_block, NULL);
476 EXPECT_EQ(curr_block->len, 1U);
477 EXPECT_EQ_STMT(curr_block->instrs,
478 BPF_RET+BPF_K,
479 SECCOMP_RET_ERRNO | (1 & SECCOMP_RET_DATA));
480
481 /* Seventh block is "SUCCESS" label and SECCOMP_RET_ALLOW */
482 curr_block = curr_block->next;
483 EXPECT_NE(curr_block, NULL);
484 EXPECT_ALLOW(curr_block);
485
486 EXPECT_EQ(curr_block->next, NULL);
487
488 free_block_list(block);
489 free_label_strings(&self->labels);
490}
491
Jorge Lucangeli Obesd96baf42013-03-26 15:11:30 -0700492TEST_F(arg_filter, unconditional_errno) {
493 const char *fragment = "return 1";
494 int nr = 1;
495 unsigned int id = 0;
496
497 struct filter_block *block =
498 compile_section(nr, fragment, id, &self->labels);
499 ASSERT_NE(block, NULL);
500 size_t exp_total_len = 2;
501 EXPECT_EQ(block->total_len, exp_total_len);
502
503 /* First block is a label. */
504 struct filter_block *curr_block = block;
505 ASSERT_NE(curr_block, NULL);
506 EXPECT_EQ(block->len, 1U);
507 EXPECT_LBL(curr_block->instrs);
508
509 /* Second block is SECCOMP_RET_ERRNO */
510 curr_block = curr_block->next;
511 EXPECT_NE(curr_block, NULL);
512 EXPECT_EQ(curr_block->len, 1U);
513 EXPECT_EQ_STMT(curr_block->instrs,
514 BPF_RET+BPF_K,
515 SECCOMP_RET_ERRNO | (1 & SECCOMP_RET_DATA));
516
517 EXPECT_EQ(curr_block->next, NULL);
518
519 free_block_list(block);
520 free_label_strings(&self->labels);
521}
522
Jorge Lucangeli Obesfc8ab532012-03-20 10:14:31 -0700523TEST_F(arg_filter, invalid) {
524 const char *fragment = "argnn == 0";
525 int nr = 1;
526 unsigned int id = 0;
527
528 struct filter_block *block =
529 compile_section(nr, fragment, id, &self->labels);
530 ASSERT_EQ(block, NULL);
531
532 fragment = "arg0 == 0 && arg1 == 1; return errno";
533 block = compile_section(nr, fragment, id, &self->labels);
534 ASSERT_EQ(block, NULL);
535}
536
Jorge Lucangeli Obesd4467262012-03-23 16:19:59 -0700537FIXTURE(filter) {};
538
Jorge Lucangeli Obes53495fe2015-12-01 11:56:04 -0800539/*
540 * When compiling for Android, disable tests that require data files.
541 * TODO(b/259497279): Re-enable this.
542 */
543#if !defined(__ANDROID__)
Jorge Lucangeli Obesd4467262012-03-23 16:19:59 -0700544FIXTURE_SETUP(filter) {}
545FIXTURE_TEARDOWN(filter) {}
546
547TEST_F(filter, seccomp_mode1) {
548 struct sock_fprog actual;
549 FILE *policy = fopen("test/seccomp.policy", "r");
Jorge Lucangeli Obesbda833c2012-07-31 16:25:56 -0700550 int res = compile_filter(policy, &actual, NO_LOGGING);
Jorge Lucangeli Obesd4467262012-03-23 16:19:59 -0700551
552 /*
553 * Checks return value, filter length, and that the filter
554 * validates arch, loads syscall number, and
555 * only allows expected syscalls.
556 */
557 ASSERT_EQ(res, 0);
558 EXPECT_EQ(actual.len, 13);
559 EXPECT_ARCH_VALIDATION(actual.filter);
560 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
561 BPF_LD+BPF_W+BPF_ABS, syscall_nr);
562 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 1,
563 __NR_read);
564 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 3,
565 __NR_write);
566 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 5,
567 __NR_rt_sigreturn);
568 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 7,
569 __NR_exit);
Jorge Lucangeli Obes18d1eba2014-04-18 13:58:20 -0700570 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN + 9, BPF_RET+BPF_K,
571 SECCOMP_RET_KILL);
Jorge Lucangeli Obesd4467262012-03-23 16:19:59 -0700572
573 free(actual.filter);
574 fclose(policy);
575}
576
577TEST_F(filter, seccomp_read_write) {
578 struct sock_fprog actual;
579 FILE *policy = fopen("test/stdin_stdout.policy", "r");
Jorge Lucangeli Obesbda833c2012-07-31 16:25:56 -0700580 int res = compile_filter(policy, &actual, NO_LOGGING);
Jorge Lucangeli Obesd4467262012-03-23 16:19:59 -0700581
582 /*
583 * Checks return value, filter length, and that the filter
584 * validates arch, loads syscall number, and
585 * only allows expected syscalls, jumping to correct arg filter
586 * offsets.
587 */
588 ASSERT_EQ(res, 0);
589 size_t exp_total_len = 27 + 3 * (BPF_ARG_COMP_LEN + 1);
590 EXPECT_EQ(actual.len, exp_total_len);
591
592 EXPECT_ARCH_VALIDATION(actual.filter);
593 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
594 BPF_LD+BPF_W+BPF_ABS, syscall_nr);
595 EXPECT_ALLOW_SYSCALL_ARGS(actual.filter + ARCH_VALIDATION_LEN + 1,
596 __NR_read, 7, 0, 0);
597 EXPECT_ALLOW_SYSCALL_ARGS(actual.filter + ARCH_VALIDATION_LEN + 3,
598 __NR_write, 12 + BPF_ARG_COMP_LEN, 0, 0);
599 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 5,
600 __NR_rt_sigreturn);
601 EXPECT_ALLOW_SYSCALL(actual.filter + ARCH_VALIDATION_LEN + 7,
602 __NR_exit);
Jorge Lucangeli Obes18d1eba2014-04-18 13:58:20 -0700603 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN + 9, BPF_RET+BPF_K,
604 SECCOMP_RET_KILL);
Jorge Lucangeli Obesd4467262012-03-23 16:19:59 -0700605
606 free(actual.filter);
607 fclose(policy);
608}
609
610TEST_F(filter, invalid) {
611 struct sock_fprog actual;
612
613 FILE *policy = fopen("test/invalid_syscall_name.policy", "r");
Jorge Lucangeli Obesbda833c2012-07-31 16:25:56 -0700614 int res = compile_filter(policy, &actual, NO_LOGGING);
Jorge Lucangeli Obesd4467262012-03-23 16:19:59 -0700615 ASSERT_NE(res, 0);
616 fclose(policy);
617
618 policy = fopen("test/invalid_arg_filter.policy", "r");
Jorge Lucangeli Obesbda833c2012-07-31 16:25:56 -0700619 res = compile_filter(policy, &actual, NO_LOGGING);
Jorge Lucangeli Obesd4467262012-03-23 16:19:59 -0700620 ASSERT_NE(res, 0);
621 fclose(policy);
622}
623
Jorge Lucangeli Obes6135db92012-07-27 13:37:30 -0700624TEST_F(filter, nonexistent) {
625 struct sock_fprog actual;
626
627 FILE *policy = fopen("test/nonexistent-file.policy", "r");
Jorge Lucangeli Obesbda833c2012-07-31 16:25:56 -0700628 int res = compile_filter(policy, &actual, NO_LOGGING);
Jorge Lucangeli Obes6135db92012-07-27 13:37:30 -0700629 ASSERT_NE(res, 0);
630}
631
Jorge Lucangeli Obesbda833c2012-07-31 16:25:56 -0700632TEST_F(filter, log) {
633 struct sock_fprog actual;
634
635 FILE *policy = fopen("test/seccomp.policy", "r");
636 int res = compile_filter(policy, &actual, USE_LOGGING);
637
638 size_t i;
639 size_t index = 0;
640 /*
641 * Checks return value, filter length, and that the filter
642 * validates arch, loads syscall number, only allows expected syscalls,
643 * and returns TRAP on failure.
644 * NOTE(jorgelo): the filter is longer since we add the syscalls needed
645 * for logging.
646 */
647 ASSERT_EQ(res, 0);
648 EXPECT_EQ(actual.len, 13 + 2 * log_syscalls_len);
649 EXPECT_ARCH_VALIDATION(actual.filter);
650 EXPECT_EQ_STMT(actual.filter + ARCH_VALIDATION_LEN,
651 BPF_LD+BPF_W+BPF_ABS, syscall_nr);
652
653 index = ARCH_VALIDATION_LEN + 1;
654 for (i = 0; i < log_syscalls_len; i++)
655 EXPECT_ALLOW_SYSCALL(actual.filter + (index + 2 * i),
656 lookup_syscall(log_syscalls[i]));
657
658 index += 2 * log_syscalls_len;
659
660 EXPECT_ALLOW_SYSCALL(actual.filter + index, __NR_read);
661 EXPECT_ALLOW_SYSCALL(actual.filter + index + 2, __NR_write);
662 EXPECT_ALLOW_SYSCALL(actual.filter + index + 4, __NR_rt_sigreturn);
663 EXPECT_ALLOW_SYSCALL(actual.filter + index + 6, __NR_exit);
Jorge Lucangeli Obes66cfc142012-11-30 15:42:52 -0800664 EXPECT_EQ_STMT(actual.filter + index + 8, BPF_RET+BPF_K,
665 SECCOMP_RET_TRAP);
Jorge Lucangeli Obesbda833c2012-07-31 16:25:56 -0700666
667 free(actual.filter);
668 fclose(policy);
669}
Jorge Lucangeli Obes53495fe2015-12-01 11:56:04 -0800670#endif /* __ANDROID__ */
Jorge Lucangeli Obesffec8912012-11-30 14:46:23 -0800671
672TEST_HARNESS_MAIN