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