1 // SPDX-License-Identifier: GPL-2.0-only 2 /* Copyright (c) 2017 Facebook 3 */ 4 #include "test_progs.h" 5 #include "cgroup_helpers.h" 6 #include "bpf_rlimit.h" 7 #include <argp.h> 8 #include <string.h> 9 #include <signal.h> 10 #include <execinfo.h> /* backtrace */ 11 12 /* defined in test_progs.h */ 13 struct test_env env = {}; 14 15 struct prog_test_def { 16 const char *test_name; 17 int test_num; 18 void (*run_test)(void); 19 bool force_log; 20 int error_cnt; 21 int skip_cnt; 22 bool tested; 23 bool need_cgroup_cleanup; 24 25 char *subtest_name; 26 int subtest_num; 27 28 /* store counts before subtest started */ 29 int old_error_cnt; 30 }; 31 32 /* Override C runtime library's usleep() implementation to ensure nanosleep() 33 * is always called. Usleep is frequently used in selftests as a way to 34 * trigger kprobe and tracepoints. 35 */ 36 int usleep(useconds_t usec) 37 { 38 struct timespec ts; 39 40 if (usec > 999999) { 41 ts.tv_sec = usec / 1000000; 42 ts.tv_nsec = usec % 1000000; 43 } else { 44 ts.tv_sec = 0; 45 ts.tv_nsec = usec; 46 } 47 return nanosleep(&ts, NULL); 48 } 49 50 static bool should_run(struct test_selector *sel, int num, const char *name) 51 { 52 int i; 53 54 for (i = 0; i < sel->blacklist.cnt; i++) { 55 if (strstr(name, sel->blacklist.strs[i])) 56 return false; 57 } 58 59 for (i = 0; i < sel->whitelist.cnt; i++) { 60 if (strstr(name, sel->whitelist.strs[i])) 61 return true; 62 } 63 64 if (!sel->whitelist.cnt && !sel->num_set) 65 return true; 66 67 return num < sel->num_set_len && sel->num_set[num]; 68 } 69 70 static void dump_test_log(const struct prog_test_def *test, bool failed) 71 { 72 if (stdout == env.stdout) 73 return; 74 75 fflush(stdout); /* exports env.log_buf & env.log_cnt */ 76 77 if (env.verbosity > VERBOSE_NONE || test->force_log || failed) { 78 if (env.log_cnt) { 79 env.log_buf[env.log_cnt] = '\0'; 80 fprintf(env.stdout, "%s", env.log_buf); 81 if (env.log_buf[env.log_cnt - 1] != '\n') 82 fprintf(env.stdout, "\n"); 83 } 84 } 85 86 fseeko(stdout, 0, SEEK_SET); /* rewind */ 87 } 88 89 static void skip_account(void) 90 { 91 if (env.test->skip_cnt) { 92 env.skip_cnt++; 93 env.test->skip_cnt = 0; 94 } 95 } 96 97 void test__end_subtest() 98 { 99 struct prog_test_def *test = env.test; 100 int sub_error_cnt = test->error_cnt - test->old_error_cnt; 101 102 if (sub_error_cnt) 103 env.fail_cnt++; 104 else 105 env.sub_succ_cnt++; 106 skip_account(); 107 108 dump_test_log(test, sub_error_cnt); 109 110 fprintf(env.stdout, "#%d/%d %s:%s\n", 111 test->test_num, test->subtest_num, 112 test->subtest_name, sub_error_cnt ? "FAIL" : "OK"); 113 114 free(test->subtest_name); 115 test->subtest_name = NULL; 116 } 117 118 bool test__start_subtest(const char *name) 119 { 120 struct prog_test_def *test = env.test; 121 122 if (test->subtest_name) 123 test__end_subtest(); 124 125 test->subtest_num++; 126 127 if (!name || !name[0]) { 128 fprintf(env.stderr, 129 "Subtest #%d didn't provide sub-test name!\n", 130 test->subtest_num); 131 return false; 132 } 133 134 if (!should_run(&env.subtest_selector, test->subtest_num, name)) 135 return false; 136 137 test->subtest_name = strdup(name); 138 if (!test->subtest_name) { 139 fprintf(env.stderr, 140 "Subtest #%d: failed to copy subtest name!\n", 141 test->subtest_num); 142 return false; 143 } 144 env.test->old_error_cnt = env.test->error_cnt; 145 146 return true; 147 } 148 149 void test__force_log() { 150 env.test->force_log = true; 151 } 152 153 void test__skip(void) 154 { 155 env.test->skip_cnt++; 156 } 157 158 void test__fail(void) 159 { 160 env.test->error_cnt++; 161 } 162 163 int test__join_cgroup(const char *path) 164 { 165 int fd; 166 167 if (!env.test->need_cgroup_cleanup) { 168 if (setup_cgroup_environment()) { 169 fprintf(stderr, 170 "#%d %s: Failed to setup cgroup environment\n", 171 env.test->test_num, env.test->test_name); 172 return -1; 173 } 174 175 env.test->need_cgroup_cleanup = true; 176 } 177 178 fd = create_and_get_cgroup(path); 179 if (fd < 0) { 180 fprintf(stderr, 181 "#%d %s: Failed to create cgroup '%s' (errno=%d)\n", 182 env.test->test_num, env.test->test_name, path, errno); 183 return fd; 184 } 185 186 if (join_cgroup(path)) { 187 fprintf(stderr, 188 "#%d %s: Failed to join cgroup '%s' (errno=%d)\n", 189 env.test->test_num, env.test->test_name, path, errno); 190 return -1; 191 } 192 193 return fd; 194 } 195 196 struct ipv4_packet pkt_v4 = { 197 .eth.h_proto = __bpf_constant_htons(ETH_P_IP), 198 .iph.ihl = 5, 199 .iph.protocol = IPPROTO_TCP, 200 .iph.tot_len = __bpf_constant_htons(MAGIC_BYTES), 201 .tcp.urg_ptr = 123, 202 .tcp.doff = 5, 203 }; 204 205 struct ipv6_packet pkt_v6 = { 206 .eth.h_proto = __bpf_constant_htons(ETH_P_IPV6), 207 .iph.nexthdr = IPPROTO_TCP, 208 .iph.payload_len = __bpf_constant_htons(MAGIC_BYTES), 209 .tcp.urg_ptr = 123, 210 .tcp.doff = 5, 211 }; 212 213 int bpf_find_map(const char *test, struct bpf_object *obj, const char *name) 214 { 215 struct bpf_map *map; 216 217 map = bpf_object__find_map_by_name(obj, name); 218 if (!map) { 219 fprintf(stdout, "%s:FAIL:map '%s' not found\n", test, name); 220 test__fail(); 221 return -1; 222 } 223 return bpf_map__fd(map); 224 } 225 226 static bool is_jit_enabled(void) 227 { 228 const char *jit_sysctl = "/proc/sys/net/core/bpf_jit_enable"; 229 bool enabled = false; 230 int sysctl_fd; 231 232 sysctl_fd = open(jit_sysctl, 0, O_RDONLY); 233 if (sysctl_fd != -1) { 234 char tmpc; 235 236 if (read(sysctl_fd, &tmpc, sizeof(tmpc)) == 1) 237 enabled = (tmpc != '0'); 238 close(sysctl_fd); 239 } 240 241 return enabled; 242 } 243 244 int compare_map_keys(int map1_fd, int map2_fd) 245 { 246 __u32 key, next_key; 247 char val_buf[PERF_MAX_STACK_DEPTH * 248 sizeof(struct bpf_stack_build_id)]; 249 int err; 250 251 err = bpf_map_get_next_key(map1_fd, NULL, &key); 252 if (err) 253 return err; 254 err = bpf_map_lookup_elem(map2_fd, &key, val_buf); 255 if (err) 256 return err; 257 258 while (bpf_map_get_next_key(map1_fd, &key, &next_key) == 0) { 259 err = bpf_map_lookup_elem(map2_fd, &next_key, val_buf); 260 if (err) 261 return err; 262 263 key = next_key; 264 } 265 if (errno != ENOENT) 266 return -1; 267 268 return 0; 269 } 270 271 int compare_stack_ips(int smap_fd, int amap_fd, int stack_trace_len) 272 { 273 __u32 key, next_key, *cur_key_p, *next_key_p; 274 char *val_buf1, *val_buf2; 275 int i, err = 0; 276 277 val_buf1 = malloc(stack_trace_len); 278 val_buf2 = malloc(stack_trace_len); 279 cur_key_p = NULL; 280 next_key_p = &key; 281 while (bpf_map_get_next_key(smap_fd, cur_key_p, next_key_p) == 0) { 282 err = bpf_map_lookup_elem(smap_fd, next_key_p, val_buf1); 283 if (err) 284 goto out; 285 err = bpf_map_lookup_elem(amap_fd, next_key_p, val_buf2); 286 if (err) 287 goto out; 288 for (i = 0; i < stack_trace_len; i++) { 289 if (val_buf1[i] != val_buf2[i]) { 290 err = -1; 291 goto out; 292 } 293 } 294 key = *next_key_p; 295 cur_key_p = &key; 296 next_key_p = &next_key; 297 } 298 if (errno != ENOENT) 299 err = -1; 300 301 out: 302 free(val_buf1); 303 free(val_buf2); 304 return err; 305 } 306 307 int extract_build_id(char *build_id, size_t size) 308 { 309 FILE *fp; 310 char *line = NULL; 311 size_t len = 0; 312 313 fp = popen("readelf -n ./urandom_read | grep 'Build ID'", "r"); 314 if (fp == NULL) 315 return -1; 316 317 if (getline(&line, &len, fp) == -1) 318 goto err; 319 fclose(fp); 320 321 if (len > size) 322 len = size; 323 memcpy(build_id, line, len); 324 build_id[len] = '\0'; 325 return 0; 326 err: 327 fclose(fp); 328 return -1; 329 } 330 331 void *spin_lock_thread(void *arg) 332 { 333 __u32 duration, retval; 334 int err, prog_fd = *(u32 *) arg; 335 336 err = bpf_prog_test_run(prog_fd, 10000, &pkt_v4, sizeof(pkt_v4), 337 NULL, NULL, &retval, &duration); 338 CHECK(err || retval, "", 339 "err %d errno %d retval %d duration %d\n", 340 err, errno, retval, duration); 341 pthread_exit(arg); 342 } 343 344 /* extern declarations for test funcs */ 345 #define DEFINE_TEST(name) extern void test_##name(void); 346 #include <prog_tests/tests.h> 347 #undef DEFINE_TEST 348 349 static struct prog_test_def prog_test_defs[] = { 350 #define DEFINE_TEST(name) { \ 351 .test_name = #name, \ 352 .run_test = &test_##name, \ 353 }, 354 #include <prog_tests/tests.h> 355 #undef DEFINE_TEST 356 }; 357 const int prog_test_cnt = ARRAY_SIZE(prog_test_defs); 358 359 const char *argp_program_version = "test_progs 0.1"; 360 const char *argp_program_bug_address = "<bpf@vger.kernel.org>"; 361 const char argp_program_doc[] = "BPF selftests test runner"; 362 363 enum ARG_KEYS { 364 ARG_TEST_NUM = 'n', 365 ARG_TEST_NAME = 't', 366 ARG_TEST_NAME_BLACKLIST = 'b', 367 ARG_VERIFIER_STATS = 's', 368 ARG_VERBOSE = 'v', 369 }; 370 371 static const struct argp_option opts[] = { 372 { "num", ARG_TEST_NUM, "NUM", 0, 373 "Run test number NUM only " }, 374 { "name", ARG_TEST_NAME, "NAMES", 0, 375 "Run tests with names containing any string from NAMES list" }, 376 { "name-blacklist", ARG_TEST_NAME_BLACKLIST, "NAMES", 0, 377 "Don't run tests with names containing any string from NAMES list" }, 378 { "verifier-stats", ARG_VERIFIER_STATS, NULL, 0, 379 "Output verifier statistics", }, 380 { "verbose", ARG_VERBOSE, "LEVEL", OPTION_ARG_OPTIONAL, 381 "Verbose output (use -vv or -vvv for progressively verbose output)" }, 382 {}, 383 }; 384 385 static int libbpf_print_fn(enum libbpf_print_level level, 386 const char *format, va_list args) 387 { 388 if (env.verbosity < VERBOSE_VERY && level == LIBBPF_DEBUG) 389 return 0; 390 vfprintf(stdout, format, args); 391 return 0; 392 } 393 394 static int parse_str_list(const char *s, struct str_set *set) 395 { 396 char *input, *state = NULL, *next, **tmp, **strs = NULL; 397 int cnt = 0; 398 399 input = strdup(s); 400 if (!input) 401 return -ENOMEM; 402 403 set->cnt = 0; 404 set->strs = NULL; 405 406 while ((next = strtok_r(state ? NULL : input, ",", &state))) { 407 tmp = realloc(strs, sizeof(*strs) * (cnt + 1)); 408 if (!tmp) 409 goto err; 410 strs = tmp; 411 412 strs[cnt] = strdup(next); 413 if (!strs[cnt]) 414 goto err; 415 416 cnt++; 417 } 418 419 set->cnt = cnt; 420 set->strs = (const char **)strs; 421 free(input); 422 return 0; 423 err: 424 free(strs); 425 free(input); 426 return -ENOMEM; 427 } 428 429 int parse_num_list(const char *s, struct test_selector *sel) 430 { 431 int i, set_len = 0, num, start = 0, end = -1; 432 bool *set = NULL, *tmp, parsing_end = false; 433 char *next; 434 435 while (s[0]) { 436 errno = 0; 437 num = strtol(s, &next, 10); 438 if (errno) 439 return -errno; 440 441 if (parsing_end) 442 end = num; 443 else 444 start = num; 445 446 if (!parsing_end && *next == '-') { 447 s = next + 1; 448 parsing_end = true; 449 continue; 450 } else if (*next == ',') { 451 parsing_end = false; 452 s = next + 1; 453 end = num; 454 } else if (*next == '\0') { 455 parsing_end = false; 456 s = next; 457 end = num; 458 } else { 459 return -EINVAL; 460 } 461 462 if (start > end) 463 return -EINVAL; 464 465 if (end + 1 > set_len) { 466 set_len = end + 1; 467 tmp = realloc(set, set_len); 468 if (!tmp) { 469 free(set); 470 return -ENOMEM; 471 } 472 set = tmp; 473 } 474 for (i = start; i <= end; i++) { 475 set[i] = true; 476 } 477 478 } 479 480 if (!set) 481 return -EINVAL; 482 483 sel->num_set = set; 484 sel->num_set_len = set_len; 485 486 return 0; 487 } 488 489 extern int extra_prog_load_log_flags; 490 491 static error_t parse_arg(int key, char *arg, struct argp_state *state) 492 { 493 struct test_env *env = state->input; 494 495 switch (key) { 496 case ARG_TEST_NUM: { 497 char *subtest_str = strchr(arg, '/'); 498 499 if (subtest_str) { 500 *subtest_str = '\0'; 501 if (parse_num_list(subtest_str + 1, 502 &env->subtest_selector)) { 503 fprintf(stderr, 504 "Failed to parse subtest numbers.\n"); 505 return -EINVAL; 506 } 507 } 508 if (parse_num_list(arg, &env->test_selector)) { 509 fprintf(stderr, "Failed to parse test numbers.\n"); 510 return -EINVAL; 511 } 512 break; 513 } 514 case ARG_TEST_NAME: { 515 char *subtest_str = strchr(arg, '/'); 516 517 if (subtest_str) { 518 *subtest_str = '\0'; 519 if (parse_str_list(subtest_str + 1, 520 &env->subtest_selector.whitelist)) 521 return -ENOMEM; 522 } 523 if (parse_str_list(arg, &env->test_selector.whitelist)) 524 return -ENOMEM; 525 break; 526 } 527 case ARG_TEST_NAME_BLACKLIST: { 528 char *subtest_str = strchr(arg, '/'); 529 530 if (subtest_str) { 531 *subtest_str = '\0'; 532 if (parse_str_list(subtest_str + 1, 533 &env->subtest_selector.blacklist)) 534 return -ENOMEM; 535 } 536 if (parse_str_list(arg, &env->test_selector.blacklist)) 537 return -ENOMEM; 538 break; 539 } 540 case ARG_VERIFIER_STATS: 541 env->verifier_stats = true; 542 break; 543 case ARG_VERBOSE: 544 env->verbosity = VERBOSE_NORMAL; 545 if (arg) { 546 if (strcmp(arg, "v") == 0) { 547 env->verbosity = VERBOSE_VERY; 548 extra_prog_load_log_flags = 1; 549 } else if (strcmp(arg, "vv") == 0) { 550 env->verbosity = VERBOSE_SUPER; 551 extra_prog_load_log_flags = 2; 552 } else { 553 fprintf(stderr, 554 "Unrecognized verbosity setting ('%s'), only -v and -vv are supported\n", 555 arg); 556 return -EINVAL; 557 } 558 } 559 break; 560 case ARGP_KEY_ARG: 561 argp_usage(state); 562 break; 563 case ARGP_KEY_END: 564 break; 565 default: 566 return ARGP_ERR_UNKNOWN; 567 } 568 return 0; 569 } 570 571 static void stdio_hijack(void) 572 { 573 #ifdef __GLIBC__ 574 env.stdout = stdout; 575 env.stderr = stderr; 576 577 if (env.verbosity > VERBOSE_NONE) { 578 /* nothing to do, output to stdout by default */ 579 return; 580 } 581 582 /* stdout and stderr -> buffer */ 583 fflush(stdout); 584 585 stdout = open_memstream(&env.log_buf, &env.log_cnt); 586 if (!stdout) { 587 stdout = env.stdout; 588 perror("open_memstream"); 589 return; 590 } 591 592 stderr = stdout; 593 #endif 594 } 595 596 static void stdio_restore(void) 597 { 598 #ifdef __GLIBC__ 599 if (stdout == env.stdout) 600 return; 601 602 fclose(stdout); 603 free(env.log_buf); 604 605 env.log_buf = NULL; 606 env.log_cnt = 0; 607 608 stdout = env.stdout; 609 stderr = env.stderr; 610 #endif 611 } 612 613 /* 614 * Determine if test_progs is running as a "flavored" test runner and switch 615 * into corresponding sub-directory to load correct BPF objects. 616 * 617 * This is done by looking at executable name. If it contains "-flavor" 618 * suffix, then we are running as a flavored test runner. 619 */ 620 int cd_flavor_subdir(const char *exec_name) 621 { 622 /* General form of argv[0] passed here is: 623 * some/path/to/test_progs[-flavor], where -flavor part is optional. 624 * First cut out "test_progs[-flavor]" part, then extract "flavor" 625 * part, if it's there. 626 */ 627 const char *flavor = strrchr(exec_name, '/'); 628 629 if (!flavor) 630 return 0; 631 flavor++; 632 flavor = strrchr(flavor, '-'); 633 if (!flavor) 634 return 0; 635 flavor++; 636 fprintf(stdout, "Switching to flavor '%s' subdirectory...\n", flavor); 637 return chdir(flavor); 638 } 639 640 #define MAX_BACKTRACE_SZ 128 641 void crash_handler(int signum) 642 { 643 void *bt[MAX_BACKTRACE_SZ]; 644 size_t sz; 645 646 sz = backtrace(bt, ARRAY_SIZE(bt)); 647 648 if (env.test) 649 dump_test_log(env.test, true); 650 if (env.stdout) 651 stdio_restore(); 652 653 fprintf(stderr, "Caught signal #%d!\nStack trace:\n", signum); 654 backtrace_symbols_fd(bt, sz, STDERR_FILENO); 655 } 656 657 int main(int argc, char **argv) 658 { 659 static const struct argp argp = { 660 .options = opts, 661 .parser = parse_arg, 662 .doc = argp_program_doc, 663 }; 664 struct sigaction sigact = { 665 .sa_handler = crash_handler, 666 .sa_flags = SA_RESETHAND, 667 }; 668 int err, i; 669 670 sigaction(SIGSEGV, &sigact, NULL); 671 672 err = argp_parse(&argp, argc, argv, 0, NULL, &env); 673 if (err) 674 return err; 675 676 err = cd_flavor_subdir(argv[0]); 677 if (err) 678 return err; 679 680 libbpf_set_print(libbpf_print_fn); 681 682 srand(time(NULL)); 683 684 env.jit_enabled = is_jit_enabled(); 685 686 stdio_hijack(); 687 for (i = 0; i < prog_test_cnt; i++) { 688 struct prog_test_def *test = &prog_test_defs[i]; 689 690 env.test = test; 691 test->test_num = i + 1; 692 693 if (!should_run(&env.test_selector, 694 test->test_num, test->test_name)) 695 continue; 696 697 test->run_test(); 698 /* ensure last sub-test is finalized properly */ 699 if (test->subtest_name) 700 test__end_subtest(); 701 702 test->tested = true; 703 if (test->error_cnt) 704 env.fail_cnt++; 705 else 706 env.succ_cnt++; 707 skip_account(); 708 709 dump_test_log(test, test->error_cnt); 710 711 fprintf(env.stdout, "#%d %s:%s\n", 712 test->test_num, test->test_name, 713 test->error_cnt ? "FAIL" : "OK"); 714 715 if (test->need_cgroup_cleanup) 716 cleanup_cgroup_environment(); 717 } 718 stdio_restore(); 719 fprintf(stdout, "Summary: %d/%d PASSED, %d SKIPPED, %d FAILED\n", 720 env.succ_cnt, env.sub_succ_cnt, env.skip_cnt, env.fail_cnt); 721 722 free(env.test_selector.blacklist.strs); 723 free(env.test_selector.whitelist.strs); 724 free(env.test_selector.num_set); 725 free(env.subtest_selector.blacklist.strs); 726 free(env.subtest_selector.whitelist.strs); 727 free(env.subtest_selector.num_set); 728 729 return env.fail_cnt ? EXIT_FAILURE : EXIT_SUCCESS; 730 } 731