1 /* 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 */ 7 8 #include <asm/unistd.h> 9 #include <errno.h> 10 #include <fcntl.h> /* For O_WRONLY. */ 11 12 #include <gtest/gtest.h> 13 #include <string> 14 15 #include "bpf.h" 16 #include "syscall_filter.h" 17 #include "syscall_filter_unittest_macros.h" 18 #include "util.h" 19 20 TEST(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 37 TEST(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 56 TEST(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 64 TEST(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 83 /* Test that setting one BPF instruction works. */ 84 TEST(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 96 TEST(bpf, bpf_load_arg) { 97 struct sock_filter load_arg[BPF_LOAD_ARG_LEN]; 98 const int argidx = 1; 99 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 113 TEST(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 132 TEST(bpf, bpf_comp_jset) { 133 struct sock_filter comp_jset[BPF_COMP_LEN]; 134 unsigned long mask = (1UL << (sizeof(unsigned long) * 8 - 1)) | O_WRONLY; 135 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) 145 EXPECT_EQ_BLOCK( 146 &comp_jset[0], BPF_JMP + BPF_JSET + BPF_K, 0x80000000, jt + 2, 0); 147 EXPECT_EQ_STMT(&comp_jset[1], BPF_LD + BPF_MEM, 0); 148 EXPECT_EQ_BLOCK(&comp_jset[2], BPF_JMP + BPF_JSET + BPF_K, O_WRONLY, jt, jf); 149 #endif 150 } 151 152 TEST(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); 169 #endif 170 } 171 172 TEST(bpf, bpf_arg_comp) { 173 struct sock_filter *arg_comp; 174 int op = EQ; 175 const int argidx = 1; 176 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 201 TEST(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 210 TEST(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 220 TEST(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 231 class BpfLabelTest : public ::testing::Test { 232 protected: 233 virtual void SetUp() { labels_.count = 0; } 234 virtual void TearDown() { free_label_strings(&labels_); } 235 struct bpf_labels labels_; 236 }; 237 238 TEST_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 245 TEST_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 256 TEST_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 267 TEST_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 276 TEST_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 288 TEST_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 299 TEST_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 311 TEST_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 327 class ArgFilterTest : public ::testing::Test { 328 protected: 329 virtual void SetUp() { 330 labels_.count = 0; 331 state_.filename = "policy"; 332 state_.line_number = 1; 333 } 334 virtual void TearDown() { free_label_strings(&labels_); } 335 struct bpf_labels labels_; 336 int nr_ = 1; 337 unsigned int id_ = 0; 338 struct parser_state state_; 339 }; 340 341 TEST_F(ArgFilterTest, empty_atom) { 342 const char* fragment = ""; 343 344 struct filter_block* block = 345 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING); 346 ASSERT_EQ(block, nullptr); 347 } 348 349 TEST_F(ArgFilterTest, whitespace_atom) { 350 const char* fragment = "\t "; 351 352 struct filter_block* block = 353 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING); 354 ASSERT_EQ(block, nullptr); 355 } 356 357 TEST_F(ArgFilterTest, no_comparison) { 358 const char* fragment = "arg0"; 359 360 struct filter_block* block = 361 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING); 362 ASSERT_EQ(block, nullptr); 363 } 364 365 TEST_F(ArgFilterTest, no_constant) { 366 const char* fragment = "arg0 =="; 367 368 struct filter_block* block = 369 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING); 370 ASSERT_EQ(block, nullptr); 371 } 372 373 TEST_F(ArgFilterTest, arg0_equals) { 374 const char *fragment = "arg0 == 0"; 375 376 struct filter_block* block = 377 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING); 378 379 ASSERT_NE(block, nullptr); 380 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; 385 ASSERT_NE(curr_block, nullptr); 386 EXPECT_EQ(curr_block->len, 1U); 387 EXPECT_LBL(curr_block->instrs); 388 389 /* Second block is a comparison. */ 390 curr_block = curr_block->next; 391 EXPECT_COMP(curr_block); 392 393 /* Third block is a jump and a label (end of AND group). */ 394 curr_block = curr_block->next; 395 ASSERT_NE(curr_block, nullptr); 396 EXPECT_GROUP_END(curr_block); 397 398 /* Fourth block is SECCOMP_RET_KILL. */ 399 curr_block = curr_block->next; 400 ASSERT_NE(curr_block, nullptr); 401 EXPECT_KILL(curr_block); 402 403 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */ 404 curr_block = curr_block->next; 405 ASSERT_NE(curr_block, nullptr); 406 EXPECT_ALLOW(curr_block); 407 408 EXPECT_EQ(curr_block->next, nullptr); 409 410 free_block_list(block); 411 } 412 413 TEST_F(ArgFilterTest, arg0_mask) { 414 const char *fragment = "arg1 & O_RDWR"; 415 416 struct filter_block* block = 417 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING); 418 419 ASSERT_NE(block, nullptr); 420 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; 425 ASSERT_NE(curr_block, nullptr); 426 EXPECT_EQ(curr_block->len, 1U); 427 EXPECT_LBL(curr_block->instrs); 428 429 /* Second block is a comparison. */ 430 curr_block = curr_block->next; 431 EXPECT_COMP(curr_block); 432 433 /* Third block is a jump and a label (end of AND group). */ 434 curr_block = curr_block->next; 435 ASSERT_NE(curr_block, nullptr); 436 EXPECT_GROUP_END(curr_block); 437 438 /* Fourth block is SECCOMP_RET_KILL. */ 439 curr_block = curr_block->next; 440 ASSERT_NE(curr_block, nullptr); 441 EXPECT_KILL(curr_block); 442 443 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */ 444 curr_block = curr_block->next; 445 ASSERT_NE(curr_block, nullptr); 446 EXPECT_ALLOW(curr_block); 447 448 EXPECT_EQ(curr_block->next, nullptr); 449 450 free_block_list(block); 451 } 452 453 TEST_F(ArgFilterTest, arg0_flag_set_inclusion) { 454 const char *fragment = "arg0 in O_RDONLY|O_CREAT"; 455 456 struct filter_block* block = 457 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING); 458 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); 466 EXPECT_EQ(curr_block->len, 1U); 467 EXPECT_LBL(curr_block->instrs); 468 469 /* Second block is a comparison. */ 470 curr_block = curr_block->next; 471 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 494 TEST_F(ArgFilterTest, arg0_eq_mask) { 495 const char *fragment = "arg1 == O_WRONLY|O_CREAT"; 496 497 struct filter_block* block = 498 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING); 499 500 ASSERT_NE(block, nullptr); 501 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; 506 ASSERT_NE(curr_block, nullptr); 507 EXPECT_EQ(curr_block->len, 1U); 508 EXPECT_LBL(curr_block->instrs); 509 510 /* Second block is a comparison. */ 511 curr_block = curr_block->next; 512 ASSERT_NE(curr_block, nullptr); 513 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; 519 ASSERT_NE(curr_block, nullptr); 520 EXPECT_GROUP_END(curr_block); 521 522 /* Fourth block is SECCOMP_RET_KILL. */ 523 curr_block = curr_block->next; 524 ASSERT_NE(curr_block, nullptr); 525 EXPECT_KILL(curr_block); 526 527 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */ 528 curr_block = curr_block->next; 529 ASSERT_NE(curr_block, nullptr); 530 EXPECT_ALLOW(curr_block); 531 532 EXPECT_EQ(curr_block->next, nullptr); 533 534 free_block_list(block); 535 } 536 537 TEST_F(ArgFilterTest, and_or) { 538 const char *fragment = "arg0 == 0 && arg1 == 0 || arg0 == 1"; 539 540 struct filter_block* block = 541 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING); 542 ASSERT_NE(block, nullptr); 543 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; 548 ASSERT_NE(curr_block, nullptr); 549 EXPECT_EQ(curr_block->len, 1U); 550 EXPECT_LBL(curr_block->instrs); 551 552 /* Second block is a comparison ("arg0 == 0"). */ 553 curr_block = curr_block->next; 554 ASSERT_NE(curr_block, nullptr); 555 EXPECT_COMP(curr_block); 556 557 /* Third block is a comparison ("arg1 == 0"). */ 558 curr_block = curr_block->next; 559 ASSERT_NE(curr_block, nullptr); 560 EXPECT_COMP(curr_block); 561 562 /* Fourth block is a jump and a label (end of AND group). */ 563 curr_block = curr_block->next; 564 ASSERT_NE(curr_block, nullptr); 565 EXPECT_GROUP_END(curr_block); 566 567 /* Fifth block is a comparison ("arg0 == 1"). */ 568 curr_block = curr_block->next; 569 ASSERT_NE(curr_block, nullptr); 570 EXPECT_COMP(curr_block); 571 572 /* Sixth block is a jump and a label (end of AND group). */ 573 curr_block = curr_block->next; 574 ASSERT_NE(curr_block, nullptr); 575 EXPECT_GROUP_END(curr_block); 576 577 /* Seventh block is SECCOMP_RET_KILL. */ 578 curr_block = curr_block->next; 579 ASSERT_NE(curr_block, nullptr); 580 EXPECT_KILL(curr_block); 581 582 /* Eigth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */ 583 curr_block = curr_block->next; 584 ASSERT_NE(curr_block, nullptr); 585 EXPECT_ALLOW(curr_block); 586 587 EXPECT_EQ(curr_block->next, nullptr); 588 589 free_block_list(block); 590 } 591 592 TEST_F(ArgFilterTest, ret_errno) { 593 const char *fragment = "arg0 == 0 || arg0 == 1; return 1"; 594 595 struct filter_block* block = 596 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING); 597 ASSERT_NE(block, nullptr); 598 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; 603 ASSERT_NE(curr_block, nullptr); 604 EXPECT_EQ(curr_block->len, 1U); 605 EXPECT_LBL(curr_block->instrs); 606 607 /* Second block is a comparison ("arg0 == 0"). */ 608 curr_block = curr_block->next; 609 ASSERT_NE(curr_block, nullptr); 610 EXPECT_COMP(curr_block); 611 612 /* Third block is a jump and a label (end of AND group). */ 613 curr_block = curr_block->next; 614 ASSERT_NE(curr_block, nullptr); 615 EXPECT_GROUP_END(curr_block); 616 617 /* Fourth block is a comparison ("arg0 == 1"). */ 618 curr_block = curr_block->next; 619 ASSERT_NE(curr_block, nullptr); 620 EXPECT_COMP(curr_block); 621 622 /* Fifth block is a jump and a label (end of AND group). */ 623 curr_block = curr_block->next; 624 ASSERT_NE(curr_block, nullptr); 625 EXPECT_GROUP_END(curr_block); 626 627 /* Sixth block is SECCOMP_RET_ERRNO. */ 628 curr_block = curr_block->next; 629 ASSERT_NE(curr_block, nullptr); 630 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; 637 ASSERT_NE(curr_block, nullptr); 638 EXPECT_ALLOW(curr_block); 639 640 EXPECT_EQ(curr_block->next, nullptr); 641 642 free_block_list(block); 643 } 644 645 TEST_F(ArgFilterTest, unconditional_errno) { 646 const char *fragment = "return 1"; 647 648 struct filter_block* block = 649 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING); 650 ASSERT_NE(block, nullptr); 651 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; 656 ASSERT_NE(curr_block, nullptr); 657 EXPECT_EQ(curr_block->len, 1U); 658 EXPECT_LBL(curr_block->instrs); 659 660 /* Second block is SECCOMP_RET_ERRNO. */ 661 curr_block = curr_block->next; 662 ASSERT_NE(curr_block, nullptr); 663 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 668 EXPECT_EQ(curr_block->next, nullptr); 669 670 free_block_list(block); 671 } 672 673 TEST_F(ArgFilterTest, invalid_arg_token) { 674 const char *fragment = "org0 == 0"; 675 676 struct filter_block* block = 677 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING); 678 ASSERT_EQ(block, nullptr); 679 } 680 681 TEST_F(ArgFilterTest, invalid_arg_number) { 682 const char *fragment = "argnn == 0"; 683 684 struct filter_block* block = 685 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING); 686 ASSERT_EQ(block, nullptr); 687 } 688 689 TEST_F(ArgFilterTest, extra_chars_in_arg_token) { 690 const char* fragment = "arg0n == 0"; 691 692 struct filter_block* block = 693 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING); 694 ASSERT_EQ(block, nullptr); 695 } 696 697 TEST_F(ArgFilterTest, invalid_operator) { 698 const char* fragment = "arg0 invalidop 0"; 699 700 struct filter_block* block = 701 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING); 702 ASSERT_EQ(block, nullptr); 703 } 704 705 TEST_F(ArgFilterTest, invalid_constant) { 706 const char *fragment = "arg0 == INVALIDCONSTANT"; 707 708 struct filter_block* block = 709 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING); 710 ASSERT_EQ(block, nullptr); 711 } 712 713 TEST_F(ArgFilterTest, extra_tokens) { 714 const char* fragment = "arg0 == 0 EXTRATOKEN"; 715 716 struct filter_block* block = 717 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING); 718 ASSERT_EQ(block, nullptr); 719 } 720 721 TEST_F(ArgFilterTest, invalid_errno) { 722 const char *fragment = "arg0 == 0 && arg1 == 1; return errno"; 723 724 struct filter_block* block = 725 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING); 726 ASSERT_EQ(block, nullptr); 727 } 728 729 TEST_F(ArgFilterTest, log_no_ret_error) { 730 const char *fragment = "arg0 == 0"; 731 732 struct filter_block* block = 733 compile_policy_line(&state_, nr_, fragment, id_, &labels_, USE_LOGGING); 734 735 ASSERT_NE(block, nullptr); 736 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; 741 ASSERT_NE(curr_block, nullptr); 742 EXPECT_EQ(curr_block->len, 1U); 743 EXPECT_LBL(curr_block->instrs); 744 745 /* Second block is a comparison. */ 746 curr_block = curr_block->next; 747 ASSERT_NE(curr_block, nullptr); 748 EXPECT_COMP(curr_block); 749 750 /* Third block is a jump and a label (end of AND group). */ 751 curr_block = curr_block->next; 752 ASSERT_NE(curr_block, nullptr); 753 EXPECT_GROUP_END(curr_block); 754 755 /* Fourth block is SECCOMP_RET_TRAP, with no errno. */ 756 curr_block = curr_block->next; 757 ASSERT_NE(curr_block, nullptr); 758 EXPECT_TRAP(curr_block); 759 760 /* Fifth block is "SUCCESS" label and SECCOMP_RET_ALLOW. */ 761 curr_block = curr_block->next; 762 ASSERT_NE(curr_block, nullptr); 763 EXPECT_ALLOW(curr_block); 764 765 EXPECT_EQ(curr_block->next, nullptr); 766 767 free_block_list(block); 768 } 769 770 TEST_F(ArgFilterTest, log_bad_ret_error) { 771 const char *fragment = "arg0 == 0; return"; 772 773 struct filter_block* block = 774 compile_policy_line(&state_, nr_, fragment, id_, &labels_, NO_LOGGING); 775 ASSERT_NE(block, nullptr); 776 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; 781 ASSERT_NE(curr_block, nullptr); 782 EXPECT_EQ(curr_block->len, 1U); 783 EXPECT_LBL(curr_block->instrs); 784 785 /* Second block is a comparison ("arg0 == 0"). */ 786 curr_block = curr_block->next; 787 ASSERT_NE(curr_block, nullptr); 788 EXPECT_COMP(curr_block); 789 790 /* Third block is a jump and a label (end of AND group). */ 791 curr_block = curr_block->next; 792 ASSERT_NE(curr_block, nullptr); 793 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; 799 ASSERT_NE(curr_block, nullptr); 800 EXPECT_KILL(curr_block); 801 802 /* Seventh block is "SUCCESS" label and SECCOMP_RET_ALLOW. */ 803 curr_block = curr_block->next; 804 ASSERT_NE(curr_block, nullptr); 805 EXPECT_ALLOW(curr_block); 806 807 EXPECT_EQ(curr_block->next, nullptr); 808 809 free_block_list(block); 810 } 811 812 TEST_F(ArgFilterTest, no_log_bad_ret_error) { 813 const char *fragment = "arg0 == 0; return"; 814 815 struct filter_block* block = 816 compile_policy_line(&state_, nr_, fragment, id_, &labels_, USE_LOGGING); 817 ASSERT_NE(block, nullptr); 818 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; 823 ASSERT_NE(curr_block, nullptr); 824 EXPECT_EQ(curr_block->len, 1U); 825 EXPECT_LBL(curr_block->instrs); 826 827 /* Second block is a comparison ("arg0 == 0"). */ 828 curr_block = curr_block->next; 829 ASSERT_NE(curr_block, nullptr); 830 EXPECT_COMP(curr_block); 831 832 /* Third block is a jump and a label (end of AND group). */ 833 curr_block = curr_block->next; 834 ASSERT_NE(curr_block, nullptr); 835 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; 842 ASSERT_NE(curr_block, nullptr); 843 EXPECT_TRAP(curr_block); 844 845 /* Seventh block is "SUCCESS" label and SECCOMP_RET_ALLOW. */ 846 curr_block = curr_block->next; 847 ASSERT_NE(curr_block, nullptr); 848 EXPECT_ALLOW(curr_block); 849 850 EXPECT_EQ(curr_block->next, nullptr); 851 852 free_block_list(block); 853 } 854 855 FILE *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 892 class 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 909 TEST_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); 915 int res = compile_file("policy", policy_file, head_, &arg_blocks_, &labels_, 916 USE_RET_KILL, NO_LOGGING, 0); 917 fclose(policy_file); 918 919 /* 920 * Policy is malformed, but process should not crash. 921 */ 922 ASSERT_EQ(res, -1); 923 } 924 925 TEST_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); 932 int res = compile_file("policy", policy_file, head_, &arg_blocks_, &labels_, 933 USE_RET_KILL, NO_LOGGING, 0); 934 fclose(policy_file); 935 936 /* 937 * Policy is malformed, but process should not crash. 938 */ 939 ASSERT_EQ(res, -1); 940 } 941 942 TEST_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); 948 int res = compile_file("policy", policy_file, head_, &arg_blocks_, &labels_, 949 USE_RET_KILL, NO_LOGGING, 0); 950 fclose(policy_file); 951 952 /* 953 * Policy is malformed, but process should not crash. 954 */ 955 ASSERT_EQ(res, -1); 956 } 957 958 TEST_F(FileTest, seccomp_mode1) { 959 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); 967 int res = compile_file("policy", policy_file, head_, &arg_blocks_, &labels_, 968 USE_RET_KILL, NO_LOGGING, 0); 969 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 991 TEST_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); 1002 int res = compile_file("policy", policy_file, head_, &arg_blocks_, &labels_, 1003 USE_RET_KILL, NO_LOGGING, 0); 1004 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 1060 TEST(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)); 1069 ASSERT_NE(policy_file, nullptr); 1070 1071 int res = 1072 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING); 1073 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 1098 TEST(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)); 1107 ASSERT_NE(policy_file, nullptr); 1108 1109 int res = 1110 compile_filter("policy", policy_file, &actual, USE_RET_TRAP, NO_LOGGING); 1111 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 1137 TEST(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)); 1146 ASSERT_NE(policy_file, nullptr); 1147 1148 int res = 1149 compile_filter("policy", policy_file, &actual, USE_RET_KILL, 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, 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 1183 TEST(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 1190 int res = 1191 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING); 1192 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 1202 TEST(FilterTest, missing_atom) { 1203 struct sock_fprog actual; 1204 const char* policy = "open:\n"; 1205 1206 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy)); 1207 ASSERT_NE(policy_file, nullptr); 1208 1209 int res = 1210 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING); 1211 fclose(policy_file); 1212 ASSERT_NE(res, 0); 1213 } 1214 1215 TEST(FilterTest, whitespace_atom) { 1216 struct sock_fprog actual; 1217 const char* policy = "open:\t \n"; 1218 1219 FILE *policy_file = write_policy_to_pipe(policy, strlen(policy)); 1220 ASSERT_NE(policy_file, nullptr); 1221 1222 int res = 1223 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING); 1224 fclose(policy_file); 1225 ASSERT_NE(res, 0); 1226 } 1227 1228 TEST(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)); 1233 ASSERT_NE(policy_file, nullptr); 1234 1235 int res = 1236 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING); 1237 fclose(policy_file); 1238 ASSERT_NE(res, 0); 1239 } 1240 1241 TEST(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)); 1246 ASSERT_NE(policy_file, nullptr); 1247 1248 int res = 1249 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING); 1250 fclose(policy_file); 1251 ASSERT_NE(res, 0); 1252 } 1253 1254 TEST(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 1267 TEST(FilterTest, nonexistent) { 1268 struct sock_fprog actual; 1269 int res = compile_filter("policy", NULL, &actual, USE_RET_KILL, NO_LOGGING); 1270 ASSERT_NE(res, 0); 1271 } 1272 1273 TEST(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)); 1282 ASSERT_NE(policy_file, nullptr); 1283 1284 int res = 1285 compile_filter("policy", policy_file, &actual, USE_RET_TRAP, USE_LOGGING); 1286 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 } 1319 1320 TEST(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)); 1329 ASSERT_NE(policy_file, nullptr); 1330 1331 int res = 1332 compile_filter("policy", policy_file, &actual, USE_RET_KILL, USE_LOGGING); 1333 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 } 1366 1367 TEST(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); 1374 int res = 1375 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING); 1376 fclose(policy_file); 1377 EXPECT_NE(res, 0); 1378 } 1379 1380 TEST(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); 1386 int res = 1387 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING); 1388 fclose(policy_file); 1389 EXPECT_NE(res, 0); 1390 } 1391 1392 TEST(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); 1398 int res = 1399 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING); 1400 fclose(policy_file); 1401 EXPECT_NE(res, 0); 1402 } 1403 1404 TEST(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); 1410 int res = 1411 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING); 1412 fclose(policy_file); 1413 EXPECT_NE(res, 0); 1414 } 1415 1416 TEST(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); 1423 int res = 1424 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING); 1425 fclose(policy_file); 1426 EXPECT_NE(res, 0); 1427 } 1428 1429 TEST(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); 1436 int res = 1437 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING); 1438 fclose(policy_file); 1439 EXPECT_NE(res, 0); 1440 } 1441 1442 TEST(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); 1449 int res = 1450 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING); 1451 fclose(policy_file); 1452 EXPECT_NE(res, 0); 1453 } 1454 1455 TEST(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); 1462 int res = 1463 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING); 1464 fclose(policy_file); 1465 EXPECT_NE(res, 0); 1466 } 1467 1468 TEST(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 1476 int res = 1477 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING); 1478 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 1487 TEST(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); 1501 int res_plain = compile_filter("policy", file_plain, &compiled_plain, 1502 USE_RET_KILL, NO_LOGGING); 1503 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); 1508 int res_with_include = 1509 compile_filter("policy", file_with_include, &compiled_with_include, 1510 USE_RET_KILL, NO_LOGGING); 1511 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 1545 TEST(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 1558 int res = 1559 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING); 1560 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 1569 TEST(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 1587 int res = 1588 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING); 1589 fclose(policy_file); 1590 1591 ASSERT_NE(res, 0); 1592 } 1593 1594 TEST(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 1607 int res = 1608 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING); 1609 fclose(policy_file); 1610 1611 ASSERT_NE(res, 0); 1612 } 1613 1614 TEST(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); 1622 int res = 1623 compile_filter("policy", policy_file, &actual, USE_RET_KILL, NO_LOGGING); 1624 fclose(policy_file); 1625 1626 /* 1627 * Policy is malformed, but process should not leak. 1628 */ 1629 ASSERT_EQ(res, -1); 1630 } 1631 1632 #endif // !__ANDROID__ 1633