xref: /linux/tools/testing/selftests/bpf/prog_tests/linked_list.c (revision 5a8cd539ac19f7a68e68e1d25ef9ca2ff55b8500)
1 // SPDX-License-Identifier: GPL-2.0
2 #include <bpf/btf.h>
3 #include <test_btf.h>
4 #include <linux/btf.h>
5 #include <test_progs.h>
6 #include <network_helpers.h>
7 
8 #include "linked_list.skel.h"
9 #include "linked_list_fail.skel.h"
10 #include "linked_list_peek.skel.h"
11 
12 static char log_buf[1024 * 1024];
13 
14 static struct {
15 	const char *prog_name;
16 	const char *err_msg;
17 } linked_list_fail_tests[] = {
18 #define TEST(test, off) \
19 	{ #test "_missing_lock_push_front", \
20 	  "bpf_spin_lock at off=" #off " must be held for bpf_list_head" }, \
21 	{ #test "_missing_lock_push_back", \
22 	  "bpf_spin_lock at off=" #off " must be held for bpf_list_head" }, \
23 	{ #test "_missing_lock_pop_front", \
24 	  "bpf_spin_lock at off=" #off " must be held for bpf_list_head" }, \
25 	{ #test "_missing_lock_pop_back", \
26 	  "bpf_spin_lock at off=" #off " must be held for bpf_list_head" },
27 	TEST(kptr, 40)
28 	TEST(global, 16)
29 	TEST(map, 0)
30 	TEST(inner_map, 0)
31 #undef TEST
32 #define TEST(test, op) \
33 	{ #test "_kptr_incorrect_lock_" #op, \
34 	  "held lock and object are not in the same allocation\n" \
35 	  "bpf_spin_lock at off=40 must be held for bpf_list_head" }, \
36 	{ #test "_global_incorrect_lock_" #op, \
37 	  "held lock and object are not in the same allocation\n" \
38 	  "bpf_spin_lock at off=16 must be held for bpf_list_head" }, \
39 	{ #test "_map_incorrect_lock_" #op, \
40 	  "held lock and object are not in the same allocation\n" \
41 	  "bpf_spin_lock at off=0 must be held for bpf_list_head" }, \
42 	{ #test "_inner_map_incorrect_lock_" #op, \
43 	  "held lock and object are not in the same allocation\n" \
44 	  "bpf_spin_lock at off=0 must be held for bpf_list_head" },
45 	TEST(kptr, push_front)
46 	TEST(kptr, push_back)
47 	TEST(kptr, pop_front)
48 	TEST(kptr, pop_back)
49 	TEST(global, push_front)
50 	TEST(global, push_back)
51 	TEST(global, pop_front)
52 	TEST(global, pop_back)
53 	TEST(map, push_front)
54 	TEST(map, push_back)
55 	TEST(map, pop_front)
56 	TEST(map, pop_back)
57 	TEST(inner_map, push_front)
58 	TEST(inner_map, push_back)
59 	TEST(inner_map, pop_front)
60 	TEST(inner_map, pop_back)
61 #undef TEST
62 	{ "map_compat_kprobe", "tracing progs cannot use bpf_{list_head,rb_root} yet" },
63 	{ "map_compat_kretprobe", "tracing progs cannot use bpf_{list_head,rb_root} yet" },
64 	{ "map_compat_tp", "tracing progs cannot use bpf_{list_head,rb_root} yet" },
65 	{ "map_compat_perf", "tracing progs cannot use bpf_{list_head,rb_root} yet" },
66 	{ "map_compat_raw_tp", "tracing progs cannot use bpf_{list_head,rb_root} yet" },
67 	{ "map_compat_raw_tp_w", "tracing progs cannot use bpf_{list_head,rb_root} yet" },
68 	{ "obj_type_id_oor", "local type ID argument must be in range [0, U32_MAX]" },
69 	{ "obj_new_no_composite", "bpf_obj_new/bpf_percpu_obj_new type ID argument must be of a struct" },
70 	{ "obj_new_no_struct", "bpf_obj_new/bpf_percpu_obj_new type ID argument must be of a struct" },
71 	{ "obj_new_flex_array", "access beyond struct obj_new_flex" },
72 	{ "obj_drop_non_zero_off", "R1 must have zero offset when passed to release func" },
73 	{ "new_null_ret", "R0 invalid mem access 'ptr_or_null_'" },
74 	{ "obj_new_acq", "Unreleased reference id=" },
75 	{ "use_after_drop", "invalid mem access 'scalar'" },
76 	{ "ptr_walk_scalar", "type=rdonly_untrusted_mem expected=percpu_ptr_" },
77 	{ "direct_read_lock", "direct access to bpf_spin_lock is disallowed" },
78 	{ "direct_write_lock", "direct access to bpf_spin_lock is disallowed" },
79 	{ "direct_read_head", "direct access to bpf_list_head is disallowed" },
80 	{ "direct_write_head", "direct access to bpf_list_head is disallowed" },
81 	{ "direct_read_node", "direct access to bpf_list_node is disallowed" },
82 	{ "direct_write_node", "direct access to bpf_list_node is disallowed" },
83 	{ "use_after_unlock_push_front", "invalid mem access 'scalar'" },
84 	{ "use_after_unlock_push_back", "invalid mem access 'scalar'" },
85 	{ "double_push_front", "R2 expected pointer to allocated object" },
86 	{ "double_push_back", "R2 expected pointer to allocated object" },
87 	{ "no_node_value_type", "bpf_list_node not found at offset=0" },
88 	{ "incorrect_value_type",
89 	  "operation on bpf_list_head expects arg#1 bpf_list_node at offset=48 in struct foo, "
90 	  "but arg is at offset=0 in struct bar" },
91 	{ "incorrect_node_var_off", "variable ptr_ access var_off=(0x0; 0x1ffffffff) disallowed" },
92 	{ "incorrect_node_off1", "bpf_list_node not found at offset=49" },
93 	{ "incorrect_node_off2", "arg#1 offset=0, but expected bpf_list_node at offset=48 in struct foo" },
94 	{ "no_head_type", "bpf_list_head not found at offset=0" },
95 	{ "incorrect_head_var_off1", "R1 doesn't have constant offset" },
96 	{ "incorrect_head_var_off2", "variable ptr_ access var_off=(0x0; 0x1ffffffff) disallowed" },
97 	{ "incorrect_head_off1", "bpf_list_head not found at offset=25" },
98 	{ "incorrect_head_off2", "bpf_list_head not found at offset=1" },
99 	{ "pop_front_off", "off 48 doesn't point to 'struct bpf_spin_lock' that is at 40" },
100 	{ "pop_back_off", "off 48 doesn't point to 'struct bpf_spin_lock' that is at 40" },
101 };
102 
test_linked_list_fail_prog(const char * prog_name,const char * err_msg)103 static void test_linked_list_fail_prog(const char *prog_name, const char *err_msg)
104 {
105 	LIBBPF_OPTS(bpf_object_open_opts, opts, .kernel_log_buf = log_buf,
106 						.kernel_log_size = sizeof(log_buf),
107 						.kernel_log_level = 1);
108 	struct linked_list_fail *skel;
109 	struct bpf_program *prog;
110 	int ret;
111 
112 	skel = linked_list_fail__open_opts(&opts);
113 	if (!ASSERT_OK_PTR(skel, "linked_list_fail__open_opts"))
114 		return;
115 
116 	prog = bpf_object__find_program_by_name(skel->obj, prog_name);
117 	if (!ASSERT_OK_PTR(prog, "bpf_object__find_program_by_name"))
118 		goto end;
119 
120 	bpf_program__set_autoload(prog, true);
121 
122 	ret = linked_list_fail__load(skel);
123 	if (!ASSERT_ERR(ret, "linked_list_fail__load must fail"))
124 		goto end;
125 
126 	if (!ASSERT_OK_PTR(strstr(log_buf, err_msg), "expected error message")) {
127 		fprintf(stderr, "Expected: %s\n", err_msg);
128 		fprintf(stderr, "Verifier: %s\n", log_buf);
129 	}
130 
131 end:
132 	linked_list_fail__destroy(skel);
133 }
134 
clear_fields(struct bpf_program * prog)135 static void clear_fields(struct bpf_program *prog)
136 {
137 	LIBBPF_OPTS(bpf_test_run_opts, opts);
138 	int ret;
139 
140 	ret = bpf_prog_test_run_opts(bpf_program__fd(prog), &opts);
141 	ASSERT_OK(ret, "clear_fields");
142 	ASSERT_OK(opts.retval, "clear_fields retval");
143 }
144 
145 enum {
146 	TEST_ALL,
147 	PUSH_POP,
148 	PUSH_POP_MULT,
149 	LIST_IN_LIST,
150 };
151 
test_linked_list_success(int mode,bool leave_in_map)152 static void test_linked_list_success(int mode, bool leave_in_map)
153 {
154 	LIBBPF_OPTS(bpf_test_run_opts, opts,
155 		.data_in = &pkt_v4,
156 		.data_size_in = sizeof(pkt_v4),
157 		.repeat = 1,
158 	);
159 	struct linked_list *skel;
160 	int ret;
161 
162 	skel = linked_list__open_and_load();
163 	if (!ASSERT_OK_PTR(skel, "linked_list__open_and_load"))
164 		return;
165 
166 	if (mode == LIST_IN_LIST)
167 		goto lil;
168 	if (mode == PUSH_POP_MULT)
169 		goto ppm;
170 
171 	ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.map_list_push_pop), &opts);
172 	ASSERT_OK(ret, "map_list_push_pop");
173 	ASSERT_OK(opts.retval, "map_list_push_pop retval");
174 	if (!leave_in_map)
175 		clear_fields(skel->progs.clear_map_list);
176 
177 	ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.inner_map_list_push_pop), &opts);
178 	ASSERT_OK(ret, "inner_map_list_push_pop");
179 	ASSERT_OK(opts.retval, "inner_map_list_push_pop retval");
180 	if (!leave_in_map)
181 		clear_fields(skel->progs.clear_inner_map_list);
182 
183 	ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.global_list_push_pop), &opts);
184 	ASSERT_OK(ret, "global_list_push_pop");
185 	ASSERT_OK(opts.retval, "global_list_push_pop retval");
186 	if (!leave_in_map)
187 		clear_fields(skel->progs.clear_global_list);
188 
189 	ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.global_list_push_pop_nested), &opts);
190 	ASSERT_OK(ret, "global_list_push_pop_nested");
191 	ASSERT_OK(opts.retval, "global_list_push_pop_nested retval");
192 	if (!leave_in_map)
193 		clear_fields(skel->progs.clear_global_nested_list);
194 
195 	ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.global_list_array_push_pop), &opts);
196 	ASSERT_OK(ret, "global_list_array_push_pop");
197 	ASSERT_OK(opts.retval, "global_list_array_push_pop retval");
198 	if (!leave_in_map)
199 		clear_fields(skel->progs.clear_global_array_list);
200 
201 	if (mode == PUSH_POP)
202 		goto end;
203 
204 ppm:
205 	ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.map_list_push_pop_multiple), &opts);
206 	ASSERT_OK(ret, "map_list_push_pop_multiple");
207 	ASSERT_OK(opts.retval, "map_list_push_pop_multiple retval");
208 	if (!leave_in_map)
209 		clear_fields(skel->progs.clear_map_list);
210 
211 	ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.inner_map_list_push_pop_multiple), &opts);
212 	ASSERT_OK(ret, "inner_map_list_push_pop_multiple");
213 	ASSERT_OK(opts.retval, "inner_map_list_push_pop_multiple retval");
214 	if (!leave_in_map)
215 		clear_fields(skel->progs.clear_inner_map_list);
216 
217 	ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.global_list_push_pop_multiple), &opts);
218 	ASSERT_OK(ret, "global_list_push_pop_multiple");
219 	ASSERT_OK(opts.retval, "global_list_push_pop_multiple retval");
220 	if (!leave_in_map)
221 		clear_fields(skel->progs.clear_global_list);
222 
223 	if (mode == PUSH_POP_MULT)
224 		goto end;
225 
226 lil:
227 	ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.map_list_in_list), &opts);
228 	ASSERT_OK(ret, "map_list_in_list");
229 	ASSERT_OK(opts.retval, "map_list_in_list retval");
230 	if (!leave_in_map)
231 		clear_fields(skel->progs.clear_map_list);
232 
233 	ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.inner_map_list_in_list), &opts);
234 	ASSERT_OK(ret, "inner_map_list_in_list");
235 	ASSERT_OK(opts.retval, "inner_map_list_in_list retval");
236 	if (!leave_in_map)
237 		clear_fields(skel->progs.clear_inner_map_list);
238 
239 	ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.global_list_in_list), &opts);
240 	ASSERT_OK(ret, "global_list_in_list");
241 	ASSERT_OK(opts.retval, "global_list_in_list retval");
242 	if (!leave_in_map)
243 		clear_fields(skel->progs.clear_global_list);
244 end:
245 	linked_list__destroy(skel);
246 }
247 
248 #define SPIN_LOCK 2
249 #define LIST_HEAD 3
250 #define LIST_NODE 4
251 
init_btf(void)252 static struct btf *init_btf(void)
253 {
254 	int id, lid, hid, nid;
255 	struct btf *btf;
256 
257 	btf = btf__new_empty();
258 	if (!ASSERT_OK_PTR(btf, "btf__new_empty"))
259 		return NULL;
260 	id = btf__add_int(btf, "int", 4, BTF_INT_SIGNED);
261 	if (!ASSERT_EQ(id, 1, "btf__add_int"))
262 		goto end;
263 	lid = btf__add_struct(btf, "bpf_spin_lock", 4);
264 	if (!ASSERT_EQ(lid, SPIN_LOCK, "btf__add_struct bpf_spin_lock"))
265 		goto end;
266 	hid = btf__add_struct(btf, "bpf_list_head", 16);
267 	if (!ASSERT_EQ(hid, LIST_HEAD, "btf__add_struct bpf_list_head"))
268 		goto end;
269 	nid = btf__add_struct(btf, "bpf_list_node", 24);
270 	if (!ASSERT_EQ(nid, LIST_NODE, "btf__add_struct bpf_list_node"))
271 		goto end;
272 	return btf;
273 end:
274 	btf__free(btf);
275 	return NULL;
276 }
277 
list_and_rb_node_same_struct(bool refcount_field)278 static void list_and_rb_node_same_struct(bool refcount_field)
279 {
280 	int bpf_rb_node_btf_id, bpf_refcount_btf_id = 0, foo_btf_id;
281 	struct btf *btf;
282 	int id, err;
283 
284 	btf = init_btf();
285 	if (!ASSERT_OK_PTR(btf, "init_btf"))
286 		return;
287 
288 	bpf_rb_node_btf_id = btf__add_struct(btf, "bpf_rb_node", 32);
289 	if (!ASSERT_GT(bpf_rb_node_btf_id, 0, "btf__add_struct bpf_rb_node"))
290 		return;
291 
292 	if (refcount_field) {
293 		bpf_refcount_btf_id = btf__add_struct(btf, "bpf_refcount", 4);
294 		if (!ASSERT_GT(bpf_refcount_btf_id, 0, "btf__add_struct bpf_refcount"))
295 			return;
296 	}
297 
298 	id = btf__add_struct(btf, "bar", refcount_field ? 60 : 56);
299 	if (!ASSERT_GT(id, 0, "btf__add_struct bar"))
300 		return;
301 	err = btf__add_field(btf, "a", LIST_NODE, 0, 0);
302 	if (!ASSERT_OK(err, "btf__add_field bar::a"))
303 		return;
304 	err = btf__add_field(btf, "c", bpf_rb_node_btf_id, 192, 0);
305 	if (!ASSERT_OK(err, "btf__add_field bar::c"))
306 		return;
307 	if (refcount_field) {
308 		err = btf__add_field(btf, "ref", bpf_refcount_btf_id, 448, 0);
309 		if (!ASSERT_OK(err, "btf__add_field bar::ref"))
310 			return;
311 	}
312 
313 	foo_btf_id = btf__add_struct(btf, "foo", 20);
314 	if (!ASSERT_GT(foo_btf_id, 0, "btf__add_struct foo"))
315 		return;
316 	err = btf__add_field(btf, "a", LIST_HEAD, 0, 0);
317 	if (!ASSERT_OK(err, "btf__add_field foo::a"))
318 		return;
319 	err = btf__add_field(btf, "b", SPIN_LOCK, 128, 0);
320 	if (!ASSERT_OK(err, "btf__add_field foo::b"))
321 		return;
322 	id = btf__add_decl_tag(btf, "contains:bar:a", foo_btf_id, 0);
323 	if (!ASSERT_GT(id, 0, "btf__add_decl_tag contains:bar:a"))
324 		return;
325 
326 	err = btf__load_into_kernel(btf);
327 	ASSERT_EQ(err, refcount_field ? 0 : -EINVAL, "check btf");
328 	btf__free(btf);
329 }
330 
test_btf(void)331 static void test_btf(void)
332 {
333 	struct btf *btf = NULL;
334 	int id, err;
335 
336 	while (test__start_subtest("btf: too many locks")) {
337 		btf = init_btf();
338 		if (!ASSERT_OK_PTR(btf, "init_btf"))
339 			break;
340 		id = btf__add_struct(btf, "foo", 24);
341 		if (!ASSERT_EQ(id, 5, "btf__add_struct foo"))
342 			break;
343 		err = btf__add_field(btf, "a", SPIN_LOCK, 0, 0);
344 		if (!ASSERT_OK(err, "btf__add_struct foo::a"))
345 			break;
346 		err = btf__add_field(btf, "b", SPIN_LOCK, 32, 0);
347 		if (!ASSERT_OK(err, "btf__add_struct foo::a"))
348 			break;
349 		err = btf__add_field(btf, "c", LIST_HEAD, 64, 0);
350 		if (!ASSERT_OK(err, "btf__add_struct foo::a"))
351 			break;
352 
353 		err = btf__load_into_kernel(btf);
354 		ASSERT_EQ(err, -E2BIG, "check btf");
355 		btf__free(btf);
356 		break;
357 	}
358 
359 	while (test__start_subtest("btf: missing lock")) {
360 		btf = init_btf();
361 		if (!ASSERT_OK_PTR(btf, "init_btf"))
362 			break;
363 		id = btf__add_struct(btf, "foo", 16);
364 		if (!ASSERT_EQ(id, 5, "btf__add_struct foo"))
365 			break;
366 		err = btf__add_field(btf, "a", LIST_HEAD, 0, 0);
367 		if (!ASSERT_OK(err, "btf__add_struct foo::a"))
368 			break;
369 		id = btf__add_decl_tag(btf, "contains:baz:a", 5, 0);
370 		if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:baz:a"))
371 			break;
372 		id = btf__add_struct(btf, "baz", 16);
373 		if (!ASSERT_EQ(id, 7, "btf__add_struct baz"))
374 			break;
375 		err = btf__add_field(btf, "a", LIST_NODE, 0, 0);
376 		if (!ASSERT_OK(err, "btf__add_field baz::a"))
377 			break;
378 
379 		err = btf__load_into_kernel(btf);
380 		ASSERT_EQ(err, -EINVAL, "check btf");
381 		btf__free(btf);
382 		break;
383 	}
384 
385 	while (test__start_subtest("btf: bad offset")) {
386 		btf = init_btf();
387 		if (!ASSERT_OK_PTR(btf, "init_btf"))
388 			break;
389 		id = btf__add_struct(btf, "foo", 36);
390 		if (!ASSERT_EQ(id, 5, "btf__add_struct foo"))
391 			break;
392 		err = btf__add_field(btf, "a", LIST_HEAD, 0, 0);
393 		if (!ASSERT_OK(err, "btf__add_field foo::a"))
394 			break;
395 		err = btf__add_field(btf, "b", LIST_NODE, 0, 0);
396 		if (!ASSERT_OK(err, "btf__add_field foo::b"))
397 			break;
398 		err = btf__add_field(btf, "c", SPIN_LOCK, 0, 0);
399 		if (!ASSERT_OK(err, "btf__add_field foo::c"))
400 			break;
401 		id = btf__add_decl_tag(btf, "contains:foo:b", 5, 0);
402 		if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:foo:b"))
403 			break;
404 
405 		err = btf__load_into_kernel(btf);
406 		ASSERT_EQ(err, -EEXIST, "check btf");
407 		btf__free(btf);
408 		break;
409 	}
410 
411 	while (test__start_subtest("btf: missing contains:")) {
412 		btf = init_btf();
413 		if (!ASSERT_OK_PTR(btf, "init_btf"))
414 			break;
415 		id = btf__add_struct(btf, "foo", 24);
416 		if (!ASSERT_EQ(id, 5, "btf__add_struct foo"))
417 			break;
418 		err = btf__add_field(btf, "a", SPIN_LOCK, 0, 0);
419 		if (!ASSERT_OK(err, "btf__add_field foo::a"))
420 			break;
421 		err = btf__add_field(btf, "b", LIST_HEAD, 64, 0);
422 		if (!ASSERT_OK(err, "btf__add_field foo::b"))
423 			break;
424 
425 		err = btf__load_into_kernel(btf);
426 		ASSERT_EQ(err, -EINVAL, "check btf");
427 		btf__free(btf);
428 		break;
429 	}
430 
431 	while (test__start_subtest("btf: missing struct")) {
432 		btf = init_btf();
433 		if (!ASSERT_OK_PTR(btf, "init_btf"))
434 			break;
435 		id = btf__add_struct(btf, "foo", 24);
436 		if (!ASSERT_EQ(id, 5, "btf__add_struct foo"))
437 			break;
438 		err = btf__add_field(btf, "a", SPIN_LOCK, 0, 0);
439 		if (!ASSERT_OK(err, "btf__add_field foo::a"))
440 			break;
441 		err = btf__add_field(btf, "b", LIST_HEAD, 64, 0);
442 		if (!ASSERT_OK(err, "btf__add_field foo::b"))
443 			break;
444 		id = btf__add_decl_tag(btf, "contains:bar:bar", 5, 1);
445 		if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:bar:bar"))
446 			break;
447 
448 		err = btf__load_into_kernel(btf);
449 		ASSERT_EQ(err, -ENOENT, "check btf");
450 		btf__free(btf);
451 		break;
452 	}
453 
454 	while (test__start_subtest("btf: missing node")) {
455 		btf = init_btf();
456 		if (!ASSERT_OK_PTR(btf, "init_btf"))
457 			break;
458 		id = btf__add_struct(btf, "foo", 24);
459 		if (!ASSERT_EQ(id, 5, "btf__add_struct foo"))
460 			break;
461 		err = btf__add_field(btf, "a", SPIN_LOCK, 0, 0);
462 		if (!ASSERT_OK(err, "btf__add_field foo::a"))
463 			break;
464 		err = btf__add_field(btf, "b", LIST_HEAD, 64, 0);
465 		if (!ASSERT_OK(err, "btf__add_field foo::b"))
466 			break;
467 		id = btf__add_decl_tag(btf, "contains:foo:c", 5, 1);
468 		if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:foo:c"))
469 			break;
470 
471 		err = btf__load_into_kernel(btf);
472 		btf__free(btf);
473 		ASSERT_EQ(err, -ENOENT, "check btf");
474 		break;
475 	}
476 
477 	while (test__start_subtest("btf: node incorrect type")) {
478 		btf = init_btf();
479 		if (!ASSERT_OK_PTR(btf, "init_btf"))
480 			break;
481 		id = btf__add_struct(btf, "foo", 20);
482 		if (!ASSERT_EQ(id, 5, "btf__add_struct foo"))
483 			break;
484 		err = btf__add_field(btf, "a", LIST_HEAD, 0, 0);
485 		if (!ASSERT_OK(err, "btf__add_field foo::a"))
486 			break;
487 		err = btf__add_field(btf, "b", SPIN_LOCK, 128, 0);
488 		if (!ASSERT_OK(err, "btf__add_field foo::b"))
489 			break;
490 		id = btf__add_decl_tag(btf, "contains:bar:a", 5, 0);
491 		if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:bar:a"))
492 			break;
493 		id = btf__add_struct(btf, "bar", 4);
494 		if (!ASSERT_EQ(id, 7, "btf__add_struct bar"))
495 			break;
496 		err = btf__add_field(btf, "a", SPIN_LOCK, 0, 0);
497 		if (!ASSERT_OK(err, "btf__add_field bar::a"))
498 			break;
499 
500 		err = btf__load_into_kernel(btf);
501 		ASSERT_EQ(err, -EINVAL, "check btf");
502 		btf__free(btf);
503 		break;
504 	}
505 
506 	while (test__start_subtest("btf: multiple bpf_list_node with name b")) {
507 		btf = init_btf();
508 		if (!ASSERT_OK_PTR(btf, "init_btf"))
509 			break;
510 		id = btf__add_struct(btf, "foo", 52);
511 		if (!ASSERT_EQ(id, 5, "btf__add_struct foo"))
512 			break;
513 		err = btf__add_field(btf, "a", LIST_HEAD, 0, 0);
514 		if (!ASSERT_OK(err, "btf__add_field foo::a"))
515 			break;
516 		err = btf__add_field(btf, "b", LIST_NODE, 128, 0);
517 		if (!ASSERT_OK(err, "btf__add_field foo::b"))
518 			break;
519 		err = btf__add_field(btf, "b", LIST_NODE, 256, 0);
520 		if (!ASSERT_OK(err, "btf__add_field foo::c"))
521 			break;
522 		err = btf__add_field(btf, "d", SPIN_LOCK, 384, 0);
523 		if (!ASSERT_OK(err, "btf__add_field foo::d"))
524 			break;
525 		id = btf__add_decl_tag(btf, "contains:foo:b", 5, 0);
526 		if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:foo:b"))
527 			break;
528 
529 		err = btf__load_into_kernel(btf);
530 		ASSERT_EQ(err, -EINVAL, "check btf");
531 		btf__free(btf);
532 		break;
533 	}
534 
535 	while (test__start_subtest("btf: owning | owned AA cycle")) {
536 		btf = init_btf();
537 		if (!ASSERT_OK_PTR(btf, "init_btf"))
538 			break;
539 		id = btf__add_struct(btf, "foo", 44);
540 		if (!ASSERT_EQ(id, 5, "btf__add_struct foo"))
541 			break;
542 		err = btf__add_field(btf, "a", LIST_HEAD, 0, 0);
543 		if (!ASSERT_OK(err, "btf__add_field foo::a"))
544 			break;
545 		err = btf__add_field(btf, "b", LIST_NODE, 128, 0);
546 		if (!ASSERT_OK(err, "btf__add_field foo::b"))
547 			break;
548 		err = btf__add_field(btf, "c", SPIN_LOCK, 320, 0);
549 		if (!ASSERT_OK(err, "btf__add_field foo::c"))
550 			break;
551 		id = btf__add_decl_tag(btf, "contains:foo:b", 5, 0);
552 		if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:foo:b"))
553 			break;
554 
555 		err = btf__load_into_kernel(btf);
556 		ASSERT_EQ(err, -ELOOP, "check btf");
557 		btf__free(btf);
558 		break;
559 	}
560 
561 	while (test__start_subtest("btf: owning | owned ABA cycle")) {
562 		btf = init_btf();
563 		if (!ASSERT_OK_PTR(btf, "init_btf"))
564 			break;
565 		id = btf__add_struct(btf, "foo", 44);
566 		if (!ASSERT_EQ(id, 5, "btf__add_struct foo"))
567 			break;
568 		err = btf__add_field(btf, "a", LIST_HEAD, 0, 0);
569 		if (!ASSERT_OK(err, "btf__add_field foo::a"))
570 			break;
571 		err = btf__add_field(btf, "b", LIST_NODE, 128, 0);
572 		if (!ASSERT_OK(err, "btf__add_field foo::b"))
573 			break;
574 		err = btf__add_field(btf, "c", SPIN_LOCK, 320, 0);
575 		if (!ASSERT_OK(err, "btf__add_field foo::c"))
576 			break;
577 		id = btf__add_decl_tag(btf, "contains:bar:b", 5, 0);
578 		if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:bar:b"))
579 			break;
580 		id = btf__add_struct(btf, "bar", 44);
581 		if (!ASSERT_EQ(id, 7, "btf__add_struct bar"))
582 			break;
583 		err = btf__add_field(btf, "a", LIST_HEAD, 0, 0);
584 		if (!ASSERT_OK(err, "btf__add_field bar::a"))
585 			break;
586 		err = btf__add_field(btf, "b", LIST_NODE, 128, 0);
587 		if (!ASSERT_OK(err, "btf__add_field bar::b"))
588 			break;
589 		err = btf__add_field(btf, "c", SPIN_LOCK, 320, 0);
590 		if (!ASSERT_OK(err, "btf__add_field bar::c"))
591 			break;
592 		id = btf__add_decl_tag(btf, "contains:foo:b", 7, 0);
593 		if (!ASSERT_EQ(id, 8, "btf__add_decl_tag contains:foo:b"))
594 			break;
595 
596 		err = btf__load_into_kernel(btf);
597 		ASSERT_EQ(err, -ELOOP, "check btf");
598 		btf__free(btf);
599 		break;
600 	}
601 
602 	while (test__start_subtest("btf: owning -> owned")) {
603 		btf = init_btf();
604 		if (!ASSERT_OK_PTR(btf, "init_btf"))
605 			break;
606 		id = btf__add_struct(btf, "foo", 28);
607 		if (!ASSERT_EQ(id, 5, "btf__add_struct foo"))
608 			break;
609 		err = btf__add_field(btf, "a", LIST_HEAD, 0, 0);
610 		if (!ASSERT_OK(err, "btf__add_field foo::a"))
611 			break;
612 		err = btf__add_field(btf, "b", SPIN_LOCK, 192, 0);
613 		if (!ASSERT_OK(err, "btf__add_field foo::b"))
614 			break;
615 		id = btf__add_decl_tag(btf, "contains:bar:a", 5, 0);
616 		if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:bar:a"))
617 			break;
618 		id = btf__add_struct(btf, "bar", 24);
619 		if (!ASSERT_EQ(id, 7, "btf__add_struct bar"))
620 			break;
621 		err = btf__add_field(btf, "a", LIST_NODE, 0, 0);
622 		if (!ASSERT_OK(err, "btf__add_field bar::a"))
623 			break;
624 
625 		err = btf__load_into_kernel(btf);
626 		ASSERT_EQ(err, 0, "check btf");
627 		btf__free(btf);
628 		break;
629 	}
630 
631 	while (test__start_subtest("btf: owning -> owning | owned -> owned")) {
632 		btf = init_btf();
633 		if (!ASSERT_OK_PTR(btf, "init_btf"))
634 			break;
635 		id = btf__add_struct(btf, "foo", 28);
636 		if (!ASSERT_EQ(id, 5, "btf__add_struct foo"))
637 			break;
638 		err = btf__add_field(btf, "a", LIST_HEAD, 0, 0);
639 		if (!ASSERT_OK(err, "btf__add_field foo::a"))
640 			break;
641 		err = btf__add_field(btf, "b", SPIN_LOCK, 192, 0);
642 		if (!ASSERT_OK(err, "btf__add_field foo::b"))
643 			break;
644 		id = btf__add_decl_tag(btf, "contains:bar:b", 5, 0);
645 		if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:bar:b"))
646 			break;
647 		id = btf__add_struct(btf, "bar", 44);
648 		if (!ASSERT_EQ(id, 7, "btf__add_struct bar"))
649 			break;
650 		err = btf__add_field(btf, "a", LIST_HEAD, 0, 0);
651 		if (!ASSERT_OK(err, "btf__add_field bar::a"))
652 			break;
653 		err = btf__add_field(btf, "b", LIST_NODE, 128, 0);
654 		if (!ASSERT_OK(err, "btf__add_field bar::b"))
655 			break;
656 		err = btf__add_field(btf, "c", SPIN_LOCK, 320, 0);
657 		if (!ASSERT_OK(err, "btf__add_field bar::c"))
658 			break;
659 		id = btf__add_decl_tag(btf, "contains:baz:a", 7, 0);
660 		if (!ASSERT_EQ(id, 8, "btf__add_decl_tag contains:baz:a"))
661 			break;
662 		id = btf__add_struct(btf, "baz", 24);
663 		if (!ASSERT_EQ(id, 9, "btf__add_struct baz"))
664 			break;
665 		err = btf__add_field(btf, "a", LIST_NODE, 0, 0);
666 		if (!ASSERT_OK(err, "btf__add_field baz:a"))
667 			break;
668 
669 		err = btf__load_into_kernel(btf);
670 		ASSERT_EQ(err, 0, "check btf");
671 		btf__free(btf);
672 		break;
673 	}
674 
675 	while (test__start_subtest("btf: owning | owned -> owning | owned -> owned")) {
676 		btf = init_btf();
677 		if (!ASSERT_OK_PTR(btf, "init_btf"))
678 			break;
679 		id = btf__add_struct(btf, "foo", 44);
680 		if (!ASSERT_EQ(id, 5, "btf__add_struct foo"))
681 			break;
682 		err = btf__add_field(btf, "a", LIST_HEAD, 0, 0);
683 		if (!ASSERT_OK(err, "btf__add_field foo::a"))
684 			break;
685 		err = btf__add_field(btf, "b", LIST_NODE, 128, 0);
686 		if (!ASSERT_OK(err, "btf__add_field foo::b"))
687 			break;
688 		err = btf__add_field(btf, "c", SPIN_LOCK, 320, 0);
689 		if (!ASSERT_OK(err, "btf__add_field foo::c"))
690 			break;
691 		id = btf__add_decl_tag(btf, "contains:bar:b", 5, 0);
692 		if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:bar:b"))
693 			break;
694 		id = btf__add_struct(btf, "bar", 44);
695 		if (!ASSERT_EQ(id, 7, "btf__add_struct bar"))
696 			break;
697 		err = btf__add_field(btf, "a", LIST_HEAD, 0, 0);
698 		if (!ASSERT_OK(err, "btf__add_field bar:a"))
699 			break;
700 		err = btf__add_field(btf, "b", LIST_NODE, 128, 0);
701 		if (!ASSERT_OK(err, "btf__add_field bar:b"))
702 			break;
703 		err = btf__add_field(btf, "c", SPIN_LOCK, 320, 0);
704 		if (!ASSERT_OK(err, "btf__add_field bar:c"))
705 			break;
706 		id = btf__add_decl_tag(btf, "contains:baz:a", 7, 0);
707 		if (!ASSERT_EQ(id, 8, "btf__add_decl_tag contains:baz:a"))
708 			break;
709 		id = btf__add_struct(btf, "baz", 24);
710 		if (!ASSERT_EQ(id, 9, "btf__add_struct baz"))
711 			break;
712 		err = btf__add_field(btf, "a", LIST_NODE, 0, 0);
713 		if (!ASSERT_OK(err, "btf__add_field baz:a"))
714 			break;
715 
716 		err = btf__load_into_kernel(btf);
717 		ASSERT_EQ(err, -ELOOP, "check btf");
718 		btf__free(btf);
719 		break;
720 	}
721 
722 	while (test__start_subtest("btf: owning -> owning | owned -> owning | owned -> owned")) {
723 		btf = init_btf();
724 		if (!ASSERT_OK_PTR(btf, "init_btf"))
725 			break;
726 		id = btf__add_struct(btf, "foo", 20);
727 		if (!ASSERT_EQ(id, 5, "btf__add_struct foo"))
728 			break;
729 		err = btf__add_field(btf, "a", LIST_HEAD, 0, 0);
730 		if (!ASSERT_OK(err, "btf__add_field foo::a"))
731 			break;
732 		err = btf__add_field(btf, "b", SPIN_LOCK, 128, 0);
733 		if (!ASSERT_OK(err, "btf__add_field foo::b"))
734 			break;
735 		id = btf__add_decl_tag(btf, "contains:bar:b", 5, 0);
736 		if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:bar:b"))
737 			break;
738 		id = btf__add_struct(btf, "bar", 44);
739 		if (!ASSERT_EQ(id, 7, "btf__add_struct bar"))
740 			break;
741 		err = btf__add_field(btf, "a", LIST_HEAD, 0, 0);
742 		if (!ASSERT_OK(err, "btf__add_field bar::a"))
743 			break;
744 		err = btf__add_field(btf, "b", LIST_NODE, 128, 0);
745 		if (!ASSERT_OK(err, "btf__add_field bar::b"))
746 			break;
747 		err = btf__add_field(btf, "c", SPIN_LOCK, 320, 0);
748 		if (!ASSERT_OK(err, "btf__add_field bar::c"))
749 			break;
750 		id = btf__add_decl_tag(btf, "contains:baz:b", 7, 0);
751 		if (!ASSERT_EQ(id, 8, "btf__add_decl_tag"))
752 			break;
753 		id = btf__add_struct(btf, "baz", 44);
754 		if (!ASSERT_EQ(id, 9, "btf__add_struct baz"))
755 			break;
756 		err = btf__add_field(btf, "a", LIST_HEAD, 0, 0);
757 		if (!ASSERT_OK(err, "btf__add_field bar::a"))
758 			break;
759 		err = btf__add_field(btf, "b", LIST_NODE, 128, 0);
760 		if (!ASSERT_OK(err, "btf__add_field bar::b"))
761 			break;
762 		err = btf__add_field(btf, "c", SPIN_LOCK, 320, 0);
763 		if (!ASSERT_OK(err, "btf__add_field bar::c"))
764 			break;
765 		id = btf__add_decl_tag(btf, "contains:bam:a", 9, 0);
766 		if (!ASSERT_EQ(id, 10, "btf__add_decl_tag contains:bam:a"))
767 			break;
768 		id = btf__add_struct(btf, "bam", 24);
769 		if (!ASSERT_EQ(id, 11, "btf__add_struct bam"))
770 			break;
771 		err = btf__add_field(btf, "a", LIST_NODE, 0, 0);
772 		if (!ASSERT_OK(err, "btf__add_field bam::a"))
773 			break;
774 
775 		err = btf__load_into_kernel(btf);
776 		ASSERT_EQ(err, -ELOOP, "check btf");
777 		btf__free(btf);
778 		break;
779 	}
780 
781 	while (test__start_subtest("btf: list_node and rb_node in same struct")) {
782 		list_and_rb_node_same_struct(true);
783 		break;
784 	}
785 
786 	while (test__start_subtest("btf: list_node and rb_node in same struct, no bpf_refcount")) {
787 		list_and_rb_node_same_struct(false);
788 		break;
789 	}
790 }
791 
test_linked_list(void)792 void test_linked_list(void)
793 {
794 	int i;
795 
796 	for (i = 0; i < ARRAY_SIZE(linked_list_fail_tests); i++) {
797 		if (!test__start_subtest(linked_list_fail_tests[i].prog_name))
798 			continue;
799 		test_linked_list_fail_prog(linked_list_fail_tests[i].prog_name,
800 					   linked_list_fail_tests[i].err_msg);
801 	}
802 	test_btf();
803 	test_linked_list_success(PUSH_POP, false);
804 	test_linked_list_success(PUSH_POP, true);
805 	test_linked_list_success(PUSH_POP_MULT, false);
806 	test_linked_list_success(PUSH_POP_MULT, true);
807 	test_linked_list_success(LIST_IN_LIST, false);
808 	test_linked_list_success(LIST_IN_LIST, true);
809 	test_linked_list_success(TEST_ALL, false);
810 }
811 
test_linked_list_peek(void)812 void test_linked_list_peek(void)
813 {
814 	RUN_TESTS(linked_list_peek);
815 }
816