1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2022 Meta Platforms, Inc. and affiliates. */ 3 #include <test_progs.h> 4 #include <bpf/btf.h> 5 6 #include "test_log_fixup.skel.h" 7 8 enum trunc_type { 9 TRUNC_NONE, 10 TRUNC_PARTIAL, 11 TRUNC_FULL, 12 }; 13 14 static void bad_core_relo(size_t log_buf_size, enum trunc_type trunc_type) 15 { 16 char log_buf[8 * 1024]; 17 struct test_log_fixup* skel; 18 int err; 19 20 skel = test_log_fixup__open(); 21 if (!ASSERT_OK_PTR(skel, "skel_open")) 22 return; 23 24 bpf_program__set_autoload(skel->progs.bad_relo, true); 25 memset(log_buf, 0, sizeof(log_buf)); 26 bpf_program__set_log_buf(skel->progs.bad_relo, log_buf, log_buf_size ?: sizeof(log_buf)); 27 bpf_program__set_log_level(skel->progs.bad_relo, 1 | 8); /* BPF_LOG_FIXED to force truncation */ 28 29 err = test_log_fixup__load(skel); 30 if (!ASSERT_ERR(err, "load_fail")) 31 goto cleanup; 32 33 ASSERT_HAS_SUBSTR(log_buf, 34 "0: <invalid CO-RE relocation>\n" 35 "failed to resolve CO-RE relocation <byte_sz> ", 36 "log_buf_part1"); 37 38 switch (trunc_type) { 39 case TRUNC_NONE: 40 ASSERT_HAS_SUBSTR(log_buf, 41 "struct task_struct___bad.fake_field (0:1 @ offset 4)\n", 42 "log_buf_part2"); 43 ASSERT_HAS_SUBSTR(log_buf, 44 "max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0\n", 45 "log_buf_end"); 46 break; 47 case TRUNC_PARTIAL: 48 /* we should get full libbpf message patch */ 49 ASSERT_HAS_SUBSTR(log_buf, 50 "struct task_struct___bad.fake_field (0:1 @ offset 4)\n", 51 "log_buf_part2"); 52 /* we shouldn't get full end of BPF verifier log */ 53 ASSERT_NULL(strstr(log_buf, "max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0\n"), 54 "log_buf_end"); 55 break; 56 case TRUNC_FULL: 57 /* we shouldn't get second part of libbpf message patch */ 58 ASSERT_NULL(strstr(log_buf, "struct task_struct___bad.fake_field (0:1 @ offset 4)\n"), 59 "log_buf_part2"); 60 /* we shouldn't get full end of BPF verifier log */ 61 ASSERT_NULL(strstr(log_buf, "max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0\n"), 62 "log_buf_end"); 63 break; 64 } 65 66 if (env.verbosity > VERBOSE_NONE) 67 printf("LOG: \n=================\n%s=================\n", log_buf); 68 cleanup: 69 test_log_fixup__destroy(skel); 70 } 71 72 static void bad_core_relo_subprog(void) 73 { 74 char log_buf[8 * 1024]; 75 struct test_log_fixup* skel; 76 int err; 77 78 skel = test_log_fixup__open(); 79 if (!ASSERT_OK_PTR(skel, "skel_open")) 80 return; 81 82 bpf_program__set_autoload(skel->progs.bad_relo_subprog, true); 83 bpf_program__set_log_buf(skel->progs.bad_relo_subprog, log_buf, sizeof(log_buf)); 84 85 err = test_log_fixup__load(skel); 86 if (!ASSERT_ERR(err, "load_fail")) 87 goto cleanup; 88 89 ASSERT_HAS_SUBSTR(log_buf, 90 ": <invalid CO-RE relocation>\n" 91 "failed to resolve CO-RE relocation <byte_off> ", 92 "log_buf"); 93 ASSERT_HAS_SUBSTR(log_buf, 94 "struct task_struct___bad.fake_field_subprog (0:2 @ offset 8)\n", 95 "log_buf"); 96 97 if (env.verbosity > VERBOSE_NONE) 98 printf("LOG: \n=================\n%s=================\n", log_buf); 99 100 cleanup: 101 test_log_fixup__destroy(skel); 102 } 103 104 static void missing_map(void) 105 { 106 char log_buf[8 * 1024]; 107 struct test_log_fixup* skel; 108 int err; 109 110 skel = test_log_fixup__open(); 111 if (!ASSERT_OK_PTR(skel, "skel_open")) 112 return; 113 114 bpf_map__set_autocreate(skel->maps.missing_map, false); 115 116 bpf_program__set_autoload(skel->progs.use_missing_map, true); 117 bpf_program__set_log_buf(skel->progs.use_missing_map, log_buf, sizeof(log_buf)); 118 119 err = test_log_fixup__load(skel); 120 if (!ASSERT_ERR(err, "load_fail")) 121 goto cleanup; 122 123 ASSERT_TRUE(bpf_map__autocreate(skel->maps.existing_map), "existing_map_autocreate"); 124 ASSERT_FALSE(bpf_map__autocreate(skel->maps.missing_map), "missing_map_autocreate"); 125 126 ASSERT_HAS_SUBSTR(log_buf, 127 ": <invalid BPF map reference>\n" 128 "BPF map 'missing_map' is referenced but wasn't created\n", 129 "log_buf"); 130 131 if (env.verbosity > VERBOSE_NONE) 132 printf("LOG: \n=================\n%s=================\n", log_buf); 133 134 cleanup: 135 test_log_fixup__destroy(skel); 136 } 137 138 static void missing_kfunc(void) 139 { 140 char log_buf[8 * 1024]; 141 struct test_log_fixup* skel; 142 int err; 143 144 skel = test_log_fixup__open(); 145 if (!ASSERT_OK_PTR(skel, "skel_open")) 146 return; 147 148 bpf_program__set_autoload(skel->progs.use_missing_kfunc, true); 149 bpf_program__set_log_buf(skel->progs.use_missing_kfunc, log_buf, sizeof(log_buf)); 150 151 err = test_log_fixup__load(skel); 152 if (!ASSERT_ERR(err, "load_fail")) 153 goto cleanup; 154 155 ASSERT_HAS_SUBSTR(log_buf, 156 "0: <invalid kfunc call>\n" 157 "kfunc 'bpf_nonexistent_kfunc' is referenced but wasn't resolved\n", 158 "log_buf"); 159 160 if (env.verbosity > VERBOSE_NONE) 161 printf("LOG: \n=================\n%s=================\n", log_buf); 162 163 cleanup: 164 test_log_fixup__destroy(skel); 165 } 166 167 void test_log_fixup(void) 168 { 169 if (test__start_subtest("bad_core_relo_trunc_none")) 170 bad_core_relo(0, TRUNC_NONE /* full buf */); 171 if (test__start_subtest("bad_core_relo_trunc_partial")) 172 bad_core_relo(280, TRUNC_PARTIAL /* truncate original log a bit */); 173 if (test__start_subtest("bad_core_relo_trunc_full")) 174 bad_core_relo(220, TRUNC_FULL /* truncate also libbpf's message patch */); 175 if (test__start_subtest("bad_core_relo_subprog")) 176 bad_core_relo_subprog(); 177 if (test__start_subtest("missing_map")) 178 missing_map(); 179 if (test__start_subtest("missing_kfunc")) 180 missing_kfunc(); 181 } 182