1ea4128ebSAndrii Nakryiko // SPDX-License-Identifier: GPL-2.0
2ea4128ebSAndrii Nakryiko /* Copyright (c) 2022 Meta Platforms, Inc. and affiliates. */
3ea4128ebSAndrii Nakryiko #include <test_progs.h>
4ea4128ebSAndrii Nakryiko #include <bpf/btf.h>
5ea4128ebSAndrii Nakryiko 
6ea4128ebSAndrii Nakryiko #include "test_log_fixup.skel.h"
7ea4128ebSAndrii Nakryiko 
8ea4128ebSAndrii Nakryiko enum trunc_type {
9ea4128ebSAndrii Nakryiko 	TRUNC_NONE,
10ea4128ebSAndrii Nakryiko 	TRUNC_PARTIAL,
11ea4128ebSAndrii Nakryiko 	TRUNC_FULL,
12ea4128ebSAndrii Nakryiko };
13ea4128ebSAndrii Nakryiko 
bad_core_relo(size_t log_buf_size,enum trunc_type trunc_type)14ea4128ebSAndrii Nakryiko static void bad_core_relo(size_t log_buf_size, enum trunc_type trunc_type)
15ea4128ebSAndrii Nakryiko {
16ea4128ebSAndrii Nakryiko 	char log_buf[8 * 1024];
17ea4128ebSAndrii Nakryiko 	struct test_log_fixup* skel;
18ea4128ebSAndrii Nakryiko 	int err;
19ea4128ebSAndrii Nakryiko 
20ea4128ebSAndrii Nakryiko 	skel = test_log_fixup__open();
21ea4128ebSAndrii Nakryiko 	if (!ASSERT_OK_PTR(skel, "skel_open"))
22ea4128ebSAndrii Nakryiko 		return;
23ea4128ebSAndrii Nakryiko 
24ea4128ebSAndrii Nakryiko 	bpf_program__set_autoload(skel->progs.bad_relo, true);
25ea4128ebSAndrii Nakryiko 	memset(log_buf, 0, sizeof(log_buf));
26ea4128ebSAndrii Nakryiko 	bpf_program__set_log_buf(skel->progs.bad_relo, log_buf, log_buf_size ?: sizeof(log_buf));
2712166409SAndrii Nakryiko 	bpf_program__set_log_level(skel->progs.bad_relo, 1 | 8); /* BPF_LOG_FIXED to force truncation */
28ea4128ebSAndrii Nakryiko 
29ea4128ebSAndrii Nakryiko 	err = test_log_fixup__load(skel);
30ea4128ebSAndrii Nakryiko 	if (!ASSERT_ERR(err, "load_fail"))
31ea4128ebSAndrii Nakryiko 		goto cleanup;
32ea4128ebSAndrii Nakryiko 
33ea4128ebSAndrii Nakryiko 	ASSERT_HAS_SUBSTR(log_buf,
34ea4128ebSAndrii Nakryiko 			  "0: <invalid CO-RE relocation>\n"
35ea4128ebSAndrii Nakryiko 			  "failed to resolve CO-RE relocation <byte_sz> ",
36ea4128ebSAndrii Nakryiko 			  "log_buf_part1");
37ea4128ebSAndrii Nakryiko 
38ea4128ebSAndrii Nakryiko 	switch (trunc_type) {
39ea4128ebSAndrii Nakryiko 	case TRUNC_NONE:
40ea4128ebSAndrii Nakryiko 		ASSERT_HAS_SUBSTR(log_buf,
41ea4128ebSAndrii Nakryiko 				  "struct task_struct___bad.fake_field (0:1 @ offset 4)\n",
42ea4128ebSAndrii Nakryiko 				  "log_buf_part2");
43ea4128ebSAndrii Nakryiko 		ASSERT_HAS_SUBSTR(log_buf,
44ea4128ebSAndrii Nakryiko 				  "max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0\n",
45ea4128ebSAndrii Nakryiko 				  "log_buf_end");
46ea4128ebSAndrii Nakryiko 		break;
47ea4128ebSAndrii Nakryiko 	case TRUNC_PARTIAL:
48ea4128ebSAndrii Nakryiko 		/* we should get full libbpf message patch */
49ea4128ebSAndrii Nakryiko 		ASSERT_HAS_SUBSTR(log_buf,
50ea4128ebSAndrii Nakryiko 				  "struct task_struct___bad.fake_field (0:1 @ offset 4)\n",
51ea4128ebSAndrii Nakryiko 				  "log_buf_part2");
52ea4128ebSAndrii Nakryiko 		/* we shouldn't get full end of BPF verifier log */
53ea4128ebSAndrii Nakryiko 		ASSERT_NULL(strstr(log_buf, "max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0\n"),
54ea4128ebSAndrii Nakryiko 			    "log_buf_end");
55ea4128ebSAndrii Nakryiko 		break;
56ea4128ebSAndrii Nakryiko 	case TRUNC_FULL:
57ea4128ebSAndrii Nakryiko 		/* we shouldn't get second part of libbpf message patch */
58ea4128ebSAndrii Nakryiko 		ASSERT_NULL(strstr(log_buf, "struct task_struct___bad.fake_field (0:1 @ offset 4)\n"),
59ea4128ebSAndrii Nakryiko 			    "log_buf_part2");
60ea4128ebSAndrii Nakryiko 		/* we shouldn't get full end of BPF verifier log */
61ea4128ebSAndrii Nakryiko 		ASSERT_NULL(strstr(log_buf, "max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0\n"),
62ea4128ebSAndrii Nakryiko 			    "log_buf_end");
63ea4128ebSAndrii Nakryiko 		break;
64ea4128ebSAndrii Nakryiko 	}
65ea4128ebSAndrii Nakryiko 
66ea4128ebSAndrii Nakryiko 	if (env.verbosity > VERBOSE_NONE)
67ea4128ebSAndrii Nakryiko 		printf("LOG:   \n=================\n%s=================\n", log_buf);
68ea4128ebSAndrii Nakryiko cleanup:
69ea4128ebSAndrii Nakryiko 	test_log_fixup__destroy(skel);
70ea4128ebSAndrii Nakryiko }
71ea4128ebSAndrii Nakryiko 
bad_core_relo_subprog(void)72ea4128ebSAndrii Nakryiko static void bad_core_relo_subprog(void)
73ea4128ebSAndrii Nakryiko {
74ea4128ebSAndrii Nakryiko 	char log_buf[8 * 1024];
75ea4128ebSAndrii Nakryiko 	struct test_log_fixup* skel;
76ea4128ebSAndrii Nakryiko 	int err;
77ea4128ebSAndrii Nakryiko 
78ea4128ebSAndrii Nakryiko 	skel = test_log_fixup__open();
79ea4128ebSAndrii Nakryiko 	if (!ASSERT_OK_PTR(skel, "skel_open"))
80ea4128ebSAndrii Nakryiko 		return;
81ea4128ebSAndrii Nakryiko 
82ea4128ebSAndrii Nakryiko 	bpf_program__set_autoload(skel->progs.bad_relo_subprog, true);
83ea4128ebSAndrii Nakryiko 	bpf_program__set_log_buf(skel->progs.bad_relo_subprog, log_buf, sizeof(log_buf));
84ea4128ebSAndrii Nakryiko 
85ea4128ebSAndrii Nakryiko 	err = test_log_fixup__load(skel);
86ea4128ebSAndrii Nakryiko 	if (!ASSERT_ERR(err, "load_fail"))
87ea4128ebSAndrii Nakryiko 		goto cleanup;
88ea4128ebSAndrii Nakryiko 
89ea4128ebSAndrii Nakryiko 	ASSERT_HAS_SUBSTR(log_buf,
90ea4128ebSAndrii Nakryiko 			  ": <invalid CO-RE relocation>\n"
91ea4128ebSAndrii Nakryiko 			  "failed to resolve CO-RE relocation <byte_off> ",
92ea4128ebSAndrii Nakryiko 			  "log_buf");
93ea4128ebSAndrii Nakryiko 	ASSERT_HAS_SUBSTR(log_buf,
94ea4128ebSAndrii Nakryiko 			  "struct task_struct___bad.fake_field_subprog (0:2 @ offset 8)\n",
95ea4128ebSAndrii Nakryiko 			  "log_buf");
96ea4128ebSAndrii Nakryiko 
97ea4128ebSAndrii Nakryiko 	if (env.verbosity > VERBOSE_NONE)
98ea4128ebSAndrii Nakryiko 		printf("LOG:   \n=================\n%s=================\n", log_buf);
99ea4128ebSAndrii Nakryiko 
100ea4128ebSAndrii Nakryiko cleanup:
101ea4128ebSAndrii Nakryiko 	test_log_fixup__destroy(skel);
102ea4128ebSAndrii Nakryiko }
103ea4128ebSAndrii Nakryiko 
missing_map(void)10468964e15SAndrii Nakryiko static void missing_map(void)
10568964e15SAndrii Nakryiko {
10668964e15SAndrii Nakryiko 	char log_buf[8 * 1024];
10768964e15SAndrii Nakryiko 	struct test_log_fixup* skel;
10868964e15SAndrii Nakryiko 	int err;
10968964e15SAndrii Nakryiko 
11068964e15SAndrii Nakryiko 	skel = test_log_fixup__open();
11168964e15SAndrii Nakryiko 	if (!ASSERT_OK_PTR(skel, "skel_open"))
11268964e15SAndrii Nakryiko 		return;
11368964e15SAndrii Nakryiko 
11468964e15SAndrii Nakryiko 	bpf_map__set_autocreate(skel->maps.missing_map, false);
11568964e15SAndrii Nakryiko 
11668964e15SAndrii Nakryiko 	bpf_program__set_autoload(skel->progs.use_missing_map, true);
11768964e15SAndrii Nakryiko 	bpf_program__set_log_buf(skel->progs.use_missing_map, log_buf, sizeof(log_buf));
11868964e15SAndrii Nakryiko 
11968964e15SAndrii Nakryiko 	err = test_log_fixup__load(skel);
12068964e15SAndrii Nakryiko 	if (!ASSERT_ERR(err, "load_fail"))
12168964e15SAndrii Nakryiko 		goto cleanup;
12268964e15SAndrii Nakryiko 
12368964e15SAndrii Nakryiko 	ASSERT_TRUE(bpf_map__autocreate(skel->maps.existing_map), "existing_map_autocreate");
12468964e15SAndrii Nakryiko 	ASSERT_FALSE(bpf_map__autocreate(skel->maps.missing_map), "missing_map_autocreate");
12568964e15SAndrii Nakryiko 
12668964e15SAndrii Nakryiko 	ASSERT_HAS_SUBSTR(log_buf,
127*898f55f5SEduard Zingerman 			  ": <invalid BPF map reference>\n"
12868964e15SAndrii Nakryiko 			  "BPF map 'missing_map' is referenced but wasn't created\n",
12968964e15SAndrii Nakryiko 			  "log_buf");
13068964e15SAndrii Nakryiko 
13168964e15SAndrii Nakryiko 	if (env.verbosity > VERBOSE_NONE)
13268964e15SAndrii Nakryiko 		printf("LOG:   \n=================\n%s=================\n", log_buf);
13368964e15SAndrii Nakryiko 
13468964e15SAndrii Nakryiko cleanup:
13568964e15SAndrii Nakryiko 	test_log_fixup__destroy(skel);
13668964e15SAndrii Nakryiko }
13768964e15SAndrii Nakryiko 
missing_kfunc(void)13830bbfe32SAndrii Nakryiko static void missing_kfunc(void)
13930bbfe32SAndrii Nakryiko {
14030bbfe32SAndrii Nakryiko 	char log_buf[8 * 1024];
14130bbfe32SAndrii Nakryiko 	struct test_log_fixup* skel;
14230bbfe32SAndrii Nakryiko 	int err;
14330bbfe32SAndrii Nakryiko 
14430bbfe32SAndrii Nakryiko 	skel = test_log_fixup__open();
14530bbfe32SAndrii Nakryiko 	if (!ASSERT_OK_PTR(skel, "skel_open"))
14630bbfe32SAndrii Nakryiko 		return;
14730bbfe32SAndrii Nakryiko 
14830bbfe32SAndrii Nakryiko 	bpf_program__set_autoload(skel->progs.use_missing_kfunc, true);
14930bbfe32SAndrii Nakryiko 	bpf_program__set_log_buf(skel->progs.use_missing_kfunc, log_buf, sizeof(log_buf));
15030bbfe32SAndrii Nakryiko 
15130bbfe32SAndrii Nakryiko 	err = test_log_fixup__load(skel);
15230bbfe32SAndrii Nakryiko 	if (!ASSERT_ERR(err, "load_fail"))
15330bbfe32SAndrii Nakryiko 		goto cleanup;
15430bbfe32SAndrii Nakryiko 
15530bbfe32SAndrii Nakryiko 	ASSERT_HAS_SUBSTR(log_buf,
15630bbfe32SAndrii Nakryiko 			  "0: <invalid kfunc call>\n"
15730bbfe32SAndrii Nakryiko 			  "kfunc 'bpf_nonexistent_kfunc' is referenced but wasn't resolved\n",
15830bbfe32SAndrii Nakryiko 			  "log_buf");
15930bbfe32SAndrii Nakryiko 
16030bbfe32SAndrii Nakryiko 	if (env.verbosity > VERBOSE_NONE)
16130bbfe32SAndrii Nakryiko 		printf("LOG:   \n=================\n%s=================\n", log_buf);
16230bbfe32SAndrii Nakryiko 
16330bbfe32SAndrii Nakryiko cleanup:
16430bbfe32SAndrii Nakryiko 	test_log_fixup__destroy(skel);
16530bbfe32SAndrii Nakryiko }
16630bbfe32SAndrii Nakryiko 
test_log_fixup(void)167ea4128ebSAndrii Nakryiko void test_log_fixup(void)
168ea4128ebSAndrii Nakryiko {
169ea4128ebSAndrii Nakryiko 	if (test__start_subtest("bad_core_relo_trunc_none"))
170ea4128ebSAndrii Nakryiko 		bad_core_relo(0, TRUNC_NONE /* full buf */);
171ea4128ebSAndrii Nakryiko 	if (test__start_subtest("bad_core_relo_trunc_partial"))
172ea4128ebSAndrii Nakryiko 		bad_core_relo(300, TRUNC_PARTIAL /* truncate original log a bit */);
173ea4128ebSAndrii Nakryiko 	if (test__start_subtest("bad_core_relo_trunc_full"))
174fffc893bSAndrii Nakryiko 		bad_core_relo(210, TRUNC_FULL  /* truncate also libbpf's message patch */);
175ea4128ebSAndrii Nakryiko 	if (test__start_subtest("bad_core_relo_subprog"))
176ea4128ebSAndrii Nakryiko 		bad_core_relo_subprog();
17768964e15SAndrii Nakryiko 	if (test__start_subtest("missing_map"))
17868964e15SAndrii Nakryiko 		missing_map();
17930bbfe32SAndrii Nakryiko 	if (test__start_subtest("missing_kfunc"))
18030bbfe32SAndrii Nakryiko 		missing_kfunc();
181ea4128ebSAndrii Nakryiko }
182