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