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