xref: /linux/tools/testing/selftests/bpf/test_progs.c (revision 9d106c6dd81bb26ad7fc3ee89cb1d62557c8e2c9)
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