1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2021 Facebook */
3 #include <test_progs.h>
4 #include <bpf/btf.h>
5 #include "test_btf_decl_tag.skel.h"
6 
7 /* struct btf_type_tag_test is referenced in btf_type_tag.skel.h */
8 struct btf_type_tag_test {
9         int **p;
10 };
11 #include "btf_type_tag.skel.h"
12 #include "btf_type_tag_user.skel.h"
13 #include "btf_type_tag_percpu.skel.h"
14 
15 static void test_btf_decl_tag(void)
16 {
17 	struct test_btf_decl_tag *skel;
18 
19 	skel = test_btf_decl_tag__open_and_load();
20 	if (!ASSERT_OK_PTR(skel, "btf_decl_tag"))
21 		return;
22 
23 	if (skel->rodata->skip_tests) {
24 		printf("%s:SKIP: btf_decl_tag attribute not supported", __func__);
25 		test__skip();
26 	}
27 
28 	test_btf_decl_tag__destroy(skel);
29 }
30 
31 static void test_btf_type_tag(void)
32 {
33 	struct btf_type_tag *skel;
34 
35 	skel = btf_type_tag__open_and_load();
36 	if (!ASSERT_OK_PTR(skel, "btf_type_tag"))
37 		return;
38 
39 	if (skel->rodata->skip_tests) {
40 		printf("%s:SKIP: btf_type_tag attribute not supported", __func__);
41 		test__skip();
42 	}
43 
44 	btf_type_tag__destroy(skel);
45 }
46 
47 /* loads vmlinux_btf as well as module_btf. If the caller passes NULL as
48  * module_btf, it will not load module btf.
49  *
50  * Returns 0 on success.
51  * Return -1 On error. In case of error, the loaded btf will be freed and the
52  * input parameters will be set to pointing to NULL.
53  */
54 static int load_btfs(struct btf **vmlinux_btf, struct btf **module_btf,
55 		     bool needs_vmlinux_tag)
56 {
57 	const char *module_name = "bpf_testmod";
58 	__s32 type_id;
59 
60 	if (!env.has_testmod) {
61 		test__skip();
62 		return -1;
63 	}
64 
65 	*vmlinux_btf = btf__load_vmlinux_btf();
66 	if (!ASSERT_OK_PTR(*vmlinux_btf, "could not load vmlinux BTF"))
67 		return -1;
68 
69 	if (!needs_vmlinux_tag)
70 		goto load_module_btf;
71 
72 	/* skip the test if the vmlinux does not have __user tags */
73 	type_id = btf__find_by_name_kind(*vmlinux_btf, "user", BTF_KIND_TYPE_TAG);
74 	if (type_id <= 0) {
75 		printf("%s:SKIP: btf_type_tag attribute not in vmlinux btf", __func__);
76 		test__skip();
77 		goto free_vmlinux_btf;
78 	}
79 
80 load_module_btf:
81 	/* skip loading module_btf, if not requested by caller */
82 	if (!module_btf)
83 		return 0;
84 
85 	*module_btf = btf__load_module_btf(module_name, *vmlinux_btf);
86 	if (!ASSERT_OK_PTR(*module_btf, "could not load module BTF"))
87 		goto free_vmlinux_btf;
88 
89 	/* skip the test if the module does not have __user tags */
90 	type_id = btf__find_by_name_kind(*module_btf, "user", BTF_KIND_TYPE_TAG);
91 	if (type_id <= 0) {
92 		printf("%s:SKIP: btf_type_tag attribute not in %s", __func__, module_name);
93 		test__skip();
94 		goto free_module_btf;
95 	}
96 
97 	return 0;
98 
99 free_module_btf:
100 	btf__free(*module_btf);
101 free_vmlinux_btf:
102 	btf__free(*vmlinux_btf);
103 
104 	*vmlinux_btf = NULL;
105 	if (module_btf)
106 		*module_btf = NULL;
107 	return -1;
108 }
109 
110 static void test_btf_type_tag_mod_user(bool load_test_user1)
111 {
112 	struct btf *vmlinux_btf = NULL, *module_btf = NULL;
113 	struct btf_type_tag_user *skel;
114 	int err;
115 
116 	if (load_btfs(&vmlinux_btf, &module_btf, /*needs_vmlinux_tag=*/false))
117 		return;
118 
119 	skel = btf_type_tag_user__open();
120 	if (!ASSERT_OK_PTR(skel, "btf_type_tag_user"))
121 		goto cleanup;
122 
123 	bpf_program__set_autoload(skel->progs.test_sys_getsockname, false);
124 	if (load_test_user1)
125 		bpf_program__set_autoload(skel->progs.test_user2, false);
126 	else
127 		bpf_program__set_autoload(skel->progs.test_user1, false);
128 
129 	err = btf_type_tag_user__load(skel);
130 	ASSERT_ERR(err, "btf_type_tag_user");
131 
132 	btf_type_tag_user__destroy(skel);
133 
134 cleanup:
135 	btf__free(module_btf);
136 	btf__free(vmlinux_btf);
137 }
138 
139 static void test_btf_type_tag_vmlinux_user(void)
140 {
141 	struct btf_type_tag_user *skel;
142 	struct btf *vmlinux_btf = NULL;
143 	int err;
144 
145 	if (load_btfs(&vmlinux_btf, NULL, /*needs_vmlinux_tag=*/true))
146 		return;
147 
148 	skel = btf_type_tag_user__open();
149 	if (!ASSERT_OK_PTR(skel, "btf_type_tag_user"))
150 		goto cleanup;
151 
152 	bpf_program__set_autoload(skel->progs.test_user2, false);
153 	bpf_program__set_autoload(skel->progs.test_user1, false);
154 
155 	err = btf_type_tag_user__load(skel);
156 	ASSERT_ERR(err, "btf_type_tag_user");
157 
158 	btf_type_tag_user__destroy(skel);
159 
160 cleanup:
161 	btf__free(vmlinux_btf);
162 }
163 
164 static void test_btf_type_tag_mod_percpu(bool load_test_percpu1)
165 {
166 	struct btf *vmlinux_btf, *module_btf;
167 	struct btf_type_tag_percpu *skel;
168 	int err;
169 
170 	if (load_btfs(&vmlinux_btf, &module_btf, /*needs_vmlinux_tag=*/false))
171 		return;
172 
173 	skel = btf_type_tag_percpu__open();
174 	if (!ASSERT_OK_PTR(skel, "btf_type_tag_percpu"))
175 		goto cleanup;
176 
177 	bpf_program__set_autoload(skel->progs.test_percpu_load, false);
178 	bpf_program__set_autoload(skel->progs.test_percpu_helper, false);
179 	if (load_test_percpu1)
180 		bpf_program__set_autoload(skel->progs.test_percpu2, false);
181 	else
182 		bpf_program__set_autoload(skel->progs.test_percpu1, false);
183 
184 	err = btf_type_tag_percpu__load(skel);
185 	ASSERT_ERR(err, "btf_type_tag_percpu");
186 
187 	btf_type_tag_percpu__destroy(skel);
188 
189 cleanup:
190 	btf__free(module_btf);
191 	btf__free(vmlinux_btf);
192 }
193 
194 static void test_btf_type_tag_vmlinux_percpu(bool load_test)
195 {
196 	struct btf_type_tag_percpu *skel;
197 	struct btf *vmlinux_btf = NULL;
198 	int err;
199 
200 	if (load_btfs(&vmlinux_btf, NULL, /*needs_vmlinux_tag=*/true))
201 		return;
202 
203 	skel = btf_type_tag_percpu__open();
204 	if (!ASSERT_OK_PTR(skel, "btf_type_tag_percpu"))
205 		goto cleanup;
206 
207 	bpf_program__set_autoload(skel->progs.test_percpu2, false);
208 	bpf_program__set_autoload(skel->progs.test_percpu1, false);
209 	if (load_test) {
210 		bpf_program__set_autoload(skel->progs.test_percpu_helper, false);
211 
212 		err = btf_type_tag_percpu__load(skel);
213 		ASSERT_ERR(err, "btf_type_tag_percpu_load");
214 	} else {
215 		bpf_program__set_autoload(skel->progs.test_percpu_load, false);
216 
217 		err = btf_type_tag_percpu__load(skel);
218 		ASSERT_OK(err, "btf_type_tag_percpu_helper");
219 	}
220 
221 	btf_type_tag_percpu__destroy(skel);
222 
223 cleanup:
224 	btf__free(vmlinux_btf);
225 }
226 
227 void test_btf_tag(void)
228 {
229 	if (test__start_subtest("btf_decl_tag"))
230 		test_btf_decl_tag();
231 	if (test__start_subtest("btf_type_tag"))
232 		test_btf_type_tag();
233 
234 	if (test__start_subtest("btf_type_tag_user_mod1"))
235 		test_btf_type_tag_mod_user(true);
236 	if (test__start_subtest("btf_type_tag_user_mod2"))
237 		test_btf_type_tag_mod_user(false);
238 	if (test__start_subtest("btf_type_tag_sys_user_vmlinux"))
239 		test_btf_type_tag_vmlinux_user();
240 
241 	if (test__start_subtest("btf_type_tag_percpu_mod1"))
242 		test_btf_type_tag_mod_percpu(true);
243 	if (test__start_subtest("btf_type_tag_percpu_mod2"))
244 		test_btf_type_tag_mod_percpu(false);
245 	if (test__start_subtest("btf_type_tag_percpu_vmlinux_load"))
246 		test_btf_type_tag_vmlinux_percpu(true);
247 	if (test__start_subtest("btf_type_tag_percpu_vmlinux_helper"))
248 		test_btf_type_tag_vmlinux_percpu(false);
249 }
250