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