brintos

brintos / linux-shallow public Read only

0
0
Text · 26.0 KiB · 77d07e0 Raw
808 lines · c
1// SPDX-License-Identifier: GPL-2.02#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 TEST31#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 TEST61	{ "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	ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.global_list_push_pop_nested), &opts);187	ASSERT_OK(ret, "global_list_push_pop_nested");188	ASSERT_OK(opts.retval, "global_list_push_pop_nested retval");189	if (!leave_in_map)190		clear_fields(skel->maps.bss_A);191 192	ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.global_list_array_push_pop), &opts);193	ASSERT_OK(ret, "global_list_array_push_pop");194	ASSERT_OK(opts.retval, "global_list_array_push_pop retval");195	if (!leave_in_map)196		clear_fields(skel->maps.bss_A);197 198	if (mode == PUSH_POP)199		goto end;200 201ppm:202	ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.map_list_push_pop_multiple), &opts);203	ASSERT_OK(ret, "map_list_push_pop_multiple");204	ASSERT_OK(opts.retval, "map_list_push_pop_multiple retval");205	if (!leave_in_map)206		clear_fields(skel->maps.array_map);207 208	ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.inner_map_list_push_pop_multiple), &opts);209	ASSERT_OK(ret, "inner_map_list_push_pop_multiple");210	ASSERT_OK(opts.retval, "inner_map_list_push_pop_multiple retval");211	if (!leave_in_map)212		clear_fields(skel->maps.inner_map);213 214	ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.global_list_push_pop_multiple), &opts);215	ASSERT_OK(ret, "global_list_push_pop_multiple");216	ASSERT_OK(opts.retval, "global_list_push_pop_multiple retval");217	if (!leave_in_map)218		clear_fields(skel->maps.bss_A);219 220	if (mode == PUSH_POP_MULT)221		goto end;222 223lil:224	ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.map_list_in_list), &opts);225	ASSERT_OK(ret, "map_list_in_list");226	ASSERT_OK(opts.retval, "map_list_in_list retval");227	if (!leave_in_map)228		clear_fields(skel->maps.array_map);229 230	ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.inner_map_list_in_list), &opts);231	ASSERT_OK(ret, "inner_map_list_in_list");232	ASSERT_OK(opts.retval, "inner_map_list_in_list retval");233	if (!leave_in_map)234		clear_fields(skel->maps.inner_map);235 236	ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.global_list_in_list), &opts);237	ASSERT_OK(ret, "global_list_in_list");238	ASSERT_OK(opts.retval, "global_list_in_list retval");239	if (!leave_in_map)240		clear_fields(skel->maps.bss_A);241end:242	linked_list__destroy(skel);243}244 245#define SPIN_LOCK 2246#define LIST_HEAD 3247#define LIST_NODE 4248 249static struct btf *init_btf(void)250{251	int id, lid, hid, nid;252	struct btf *btf;253 254	btf = btf__new_empty();255	if (!ASSERT_OK_PTR(btf, "btf__new_empty"))256		return NULL;257	id = btf__add_int(btf, "int", 4, BTF_INT_SIGNED);258	if (!ASSERT_EQ(id, 1, "btf__add_int"))259		goto end;260	lid = btf__add_struct(btf, "bpf_spin_lock", 4);261	if (!ASSERT_EQ(lid, SPIN_LOCK, "btf__add_struct bpf_spin_lock"))262		goto end;263	hid = btf__add_struct(btf, "bpf_list_head", 16);264	if (!ASSERT_EQ(hid, LIST_HEAD, "btf__add_struct bpf_list_head"))265		goto end;266	nid = btf__add_struct(btf, "bpf_list_node", 24);267	if (!ASSERT_EQ(nid, LIST_NODE, "btf__add_struct bpf_list_node"))268		goto end;269	return btf;270end:271	btf__free(btf);272	return NULL;273}274 275static void list_and_rb_node_same_struct(bool refcount_field)276{277	int bpf_rb_node_btf_id, bpf_refcount_btf_id = 0, foo_btf_id;278	struct btf *btf;279	int id, err;280 281	btf = init_btf();282	if (!ASSERT_OK_PTR(btf, "init_btf"))283		return;284 285	bpf_rb_node_btf_id = btf__add_struct(btf, "bpf_rb_node", 32);286	if (!ASSERT_GT(bpf_rb_node_btf_id, 0, "btf__add_struct bpf_rb_node"))287		return;288 289	if (refcount_field) {290		bpf_refcount_btf_id = btf__add_struct(btf, "bpf_refcount", 4);291		if (!ASSERT_GT(bpf_refcount_btf_id, 0, "btf__add_struct bpf_refcount"))292			return;293	}294 295	id = btf__add_struct(btf, "bar", refcount_field ? 60 : 56);296	if (!ASSERT_GT(id, 0, "btf__add_struct bar"))297		return;298	err = btf__add_field(btf, "a", LIST_NODE, 0, 0);299	if (!ASSERT_OK(err, "btf__add_field bar::a"))300		return;301	err = btf__add_field(btf, "c", bpf_rb_node_btf_id, 192, 0);302	if (!ASSERT_OK(err, "btf__add_field bar::c"))303		return;304	if (refcount_field) {305		err = btf__add_field(btf, "ref", bpf_refcount_btf_id, 448, 0);306		if (!ASSERT_OK(err, "btf__add_field bar::ref"))307			return;308	}309 310	foo_btf_id = btf__add_struct(btf, "foo", 20);311	if (!ASSERT_GT(foo_btf_id, 0, "btf__add_struct foo"))312		return;313	err = btf__add_field(btf, "a", LIST_HEAD, 0, 0);314	if (!ASSERT_OK(err, "btf__add_field foo::a"))315		return;316	err = btf__add_field(btf, "b", SPIN_LOCK, 128, 0);317	if (!ASSERT_OK(err, "btf__add_field foo::b"))318		return;319	id = btf__add_decl_tag(btf, "contains:bar:a", foo_btf_id, 0);320	if (!ASSERT_GT(id, 0, "btf__add_decl_tag contains:bar:a"))321		return;322 323	err = btf__load_into_kernel(btf);324	ASSERT_EQ(err, refcount_field ? 0 : -EINVAL, "check btf");325	btf__free(btf);326}327 328static void test_btf(void)329{330	struct btf *btf = NULL;331	int id, err;332 333	while (test__start_subtest("btf: too many locks")) {334		btf = init_btf();335		if (!ASSERT_OK_PTR(btf, "init_btf"))336			break;337		id = btf__add_struct(btf, "foo", 24);338		if (!ASSERT_EQ(id, 5, "btf__add_struct foo"))339			break;340		err = btf__add_field(btf, "a", SPIN_LOCK, 0, 0);341		if (!ASSERT_OK(err, "btf__add_struct foo::a"))342			break;343		err = btf__add_field(btf, "b", SPIN_LOCK, 32, 0);344		if (!ASSERT_OK(err, "btf__add_struct foo::a"))345			break;346		err = btf__add_field(btf, "c", LIST_HEAD, 64, 0);347		if (!ASSERT_OK(err, "btf__add_struct foo::a"))348			break;349 350		err = btf__load_into_kernel(btf);351		ASSERT_EQ(err, -E2BIG, "check btf");352		btf__free(btf);353		break;354	}355 356	while (test__start_subtest("btf: missing lock")) {357		btf = init_btf();358		if (!ASSERT_OK_PTR(btf, "init_btf"))359			break;360		id = btf__add_struct(btf, "foo", 16);361		if (!ASSERT_EQ(id, 5, "btf__add_struct foo"))362			break;363		err = btf__add_field(btf, "a", LIST_HEAD, 0, 0);364		if (!ASSERT_OK(err, "btf__add_struct foo::a"))365			break;366		id = btf__add_decl_tag(btf, "contains:baz:a", 5, 0);367		if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:baz:a"))368			break;369		id = btf__add_struct(btf, "baz", 16);370		if (!ASSERT_EQ(id, 7, "btf__add_struct baz"))371			break;372		err = btf__add_field(btf, "a", LIST_NODE, 0, 0);373		if (!ASSERT_OK(err, "btf__add_field baz::a"))374			break;375 376		err = btf__load_into_kernel(btf);377		ASSERT_EQ(err, -EINVAL, "check btf");378		btf__free(btf);379		break;380	}381 382	while (test__start_subtest("btf: bad offset")) {383		btf = init_btf();384		if (!ASSERT_OK_PTR(btf, "init_btf"))385			break;386		id = btf__add_struct(btf, "foo", 36);387		if (!ASSERT_EQ(id, 5, "btf__add_struct foo"))388			break;389		err = btf__add_field(btf, "a", LIST_HEAD, 0, 0);390		if (!ASSERT_OK(err, "btf__add_field foo::a"))391			break;392		err = btf__add_field(btf, "b", LIST_NODE, 0, 0);393		if (!ASSERT_OK(err, "btf__add_field foo::b"))394			break;395		err = btf__add_field(btf, "c", SPIN_LOCK, 0, 0);396		if (!ASSERT_OK(err, "btf__add_field foo::c"))397			break;398		id = btf__add_decl_tag(btf, "contains:foo:b", 5, 0);399		if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:foo:b"))400			break;401 402		err = btf__load_into_kernel(btf);403		ASSERT_EQ(err, -EEXIST, "check btf");404		btf__free(btf);405		break;406	}407 408	while (test__start_subtest("btf: missing contains:")) {409		btf = init_btf();410		if (!ASSERT_OK_PTR(btf, "init_btf"))411			break;412		id = btf__add_struct(btf, "foo", 24);413		if (!ASSERT_EQ(id, 5, "btf__add_struct foo"))414			break;415		err = btf__add_field(btf, "a", SPIN_LOCK, 0, 0);416		if (!ASSERT_OK(err, "btf__add_field foo::a"))417			break;418		err = btf__add_field(btf, "b", LIST_HEAD, 64, 0);419		if (!ASSERT_OK(err, "btf__add_field foo::b"))420			break;421 422		err = btf__load_into_kernel(btf);423		ASSERT_EQ(err, -EINVAL, "check btf");424		btf__free(btf);425		break;426	}427 428	while (test__start_subtest("btf: missing struct")) {429		btf = init_btf();430		if (!ASSERT_OK_PTR(btf, "init_btf"))431			break;432		id = btf__add_struct(btf, "foo", 24);433		if (!ASSERT_EQ(id, 5, "btf__add_struct foo"))434			break;435		err = btf__add_field(btf, "a", SPIN_LOCK, 0, 0);436		if (!ASSERT_OK(err, "btf__add_field foo::a"))437			break;438		err = btf__add_field(btf, "b", LIST_HEAD, 64, 0);439		if (!ASSERT_OK(err, "btf__add_field foo::b"))440			break;441		id = btf__add_decl_tag(btf, "contains:bar:bar", 5, 1);442		if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:bar:bar"))443			break;444 445		err = btf__load_into_kernel(btf);446		ASSERT_EQ(err, -ENOENT, "check btf");447		btf__free(btf);448		break;449	}450 451	while (test__start_subtest("btf: missing node")) {452		btf = init_btf();453		if (!ASSERT_OK_PTR(btf, "init_btf"))454			break;455		id = btf__add_struct(btf, "foo", 24);456		if (!ASSERT_EQ(id, 5, "btf__add_struct foo"))457			break;458		err = btf__add_field(btf, "a", SPIN_LOCK, 0, 0);459		if (!ASSERT_OK(err, "btf__add_field foo::a"))460			break;461		err = btf__add_field(btf, "b", LIST_HEAD, 64, 0);462		if (!ASSERT_OK(err, "btf__add_field foo::b"))463			break;464		id = btf__add_decl_tag(btf, "contains:foo:c", 5, 1);465		if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:foo:c"))466			break;467 468		err = btf__load_into_kernel(btf);469		btf__free(btf);470		ASSERT_EQ(err, -ENOENT, "check btf");471		break;472	}473 474	while (test__start_subtest("btf: node incorrect type")) {475		btf = init_btf();476		if (!ASSERT_OK_PTR(btf, "init_btf"))477			break;478		id = btf__add_struct(btf, "foo", 20);479		if (!ASSERT_EQ(id, 5, "btf__add_struct foo"))480			break;481		err = btf__add_field(btf, "a", LIST_HEAD, 0, 0);482		if (!ASSERT_OK(err, "btf__add_field foo::a"))483			break;484		err = btf__add_field(btf, "b", SPIN_LOCK, 128, 0);485		if (!ASSERT_OK(err, "btf__add_field foo::b"))486			break;487		id = btf__add_decl_tag(btf, "contains:bar:a", 5, 0);488		if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:bar:a"))489			break;490		id = btf__add_struct(btf, "bar", 4);491		if (!ASSERT_EQ(id, 7, "btf__add_struct bar"))492			break;493		err = btf__add_field(btf, "a", SPIN_LOCK, 0, 0);494		if (!ASSERT_OK(err, "btf__add_field bar::a"))495			break;496 497		err = btf__load_into_kernel(btf);498		ASSERT_EQ(err, -EINVAL, "check btf");499		btf__free(btf);500		break;501	}502 503	while (test__start_subtest("btf: multiple bpf_list_node with name b")) {504		btf = init_btf();505		if (!ASSERT_OK_PTR(btf, "init_btf"))506			break;507		id = btf__add_struct(btf, "foo", 52);508		if (!ASSERT_EQ(id, 5, "btf__add_struct foo"))509			break;510		err = btf__add_field(btf, "a", LIST_HEAD, 0, 0);511		if (!ASSERT_OK(err, "btf__add_field foo::a"))512			break;513		err = btf__add_field(btf, "b", LIST_NODE, 128, 0);514		if (!ASSERT_OK(err, "btf__add_field foo::b"))515			break;516		err = btf__add_field(btf, "b", LIST_NODE, 256, 0);517		if (!ASSERT_OK(err, "btf__add_field foo::c"))518			break;519		err = btf__add_field(btf, "d", SPIN_LOCK, 384, 0);520		if (!ASSERT_OK(err, "btf__add_field foo::d"))521			break;522		id = btf__add_decl_tag(btf, "contains:foo:b", 5, 0);523		if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:foo:b"))524			break;525 526		err = btf__load_into_kernel(btf);527		ASSERT_EQ(err, -EINVAL, "check btf");528		btf__free(btf);529		break;530	}531 532	while (test__start_subtest("btf: owning | owned AA cycle")) {533		btf = init_btf();534		if (!ASSERT_OK_PTR(btf, "init_btf"))535			break;536		id = btf__add_struct(btf, "foo", 44);537		if (!ASSERT_EQ(id, 5, "btf__add_struct foo"))538			break;539		err = btf__add_field(btf, "a", LIST_HEAD, 0, 0);540		if (!ASSERT_OK(err, "btf__add_field foo::a"))541			break;542		err = btf__add_field(btf, "b", LIST_NODE, 128, 0);543		if (!ASSERT_OK(err, "btf__add_field foo::b"))544			break;545		err = btf__add_field(btf, "c", SPIN_LOCK, 320, 0);546		if (!ASSERT_OK(err, "btf__add_field foo::c"))547			break;548		id = btf__add_decl_tag(btf, "contains:foo:b", 5, 0);549		if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:foo:b"))550			break;551 552		err = btf__load_into_kernel(btf);553		ASSERT_EQ(err, -ELOOP, "check btf");554		btf__free(btf);555		break;556	}557 558	while (test__start_subtest("btf: owning | owned ABA cycle")) {559		btf = init_btf();560		if (!ASSERT_OK_PTR(btf, "init_btf"))561			break;562		id = btf__add_struct(btf, "foo", 44);563		if (!ASSERT_EQ(id, 5, "btf__add_struct foo"))564			break;565		err = btf__add_field(btf, "a", LIST_HEAD, 0, 0);566		if (!ASSERT_OK(err, "btf__add_field foo::a"))567			break;568		err = btf__add_field(btf, "b", LIST_NODE, 128, 0);569		if (!ASSERT_OK(err, "btf__add_field foo::b"))570			break;571		err = btf__add_field(btf, "c", SPIN_LOCK, 320, 0);572		if (!ASSERT_OK(err, "btf__add_field foo::c"))573			break;574		id = btf__add_decl_tag(btf, "contains:bar:b", 5, 0);575		if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:bar:b"))576			break;577		id = btf__add_struct(btf, "bar", 44);578		if (!ASSERT_EQ(id, 7, "btf__add_struct bar"))579			break;580		err = btf__add_field(btf, "a", LIST_HEAD, 0, 0);581		if (!ASSERT_OK(err, "btf__add_field bar::a"))582			break;583		err = btf__add_field(btf, "b", LIST_NODE, 128, 0);584		if (!ASSERT_OK(err, "btf__add_field bar::b"))585			break;586		err = btf__add_field(btf, "c", SPIN_LOCK, 320, 0);587		if (!ASSERT_OK(err, "btf__add_field bar::c"))588			break;589		id = btf__add_decl_tag(btf, "contains:foo:b", 7, 0);590		if (!ASSERT_EQ(id, 8, "btf__add_decl_tag contains:foo:b"))591			break;592 593		err = btf__load_into_kernel(btf);594		ASSERT_EQ(err, -ELOOP, "check btf");595		btf__free(btf);596		break;597	}598 599	while (test__start_subtest("btf: owning -> owned")) {600		btf = init_btf();601		if (!ASSERT_OK_PTR(btf, "init_btf"))602			break;603		id = btf__add_struct(btf, "foo", 28);604		if (!ASSERT_EQ(id, 5, "btf__add_struct foo"))605			break;606		err = btf__add_field(btf, "a", LIST_HEAD, 0, 0);607		if (!ASSERT_OK(err, "btf__add_field foo::a"))608			break;609		err = btf__add_field(btf, "b", SPIN_LOCK, 192, 0);610		if (!ASSERT_OK(err, "btf__add_field foo::b"))611			break;612		id = btf__add_decl_tag(btf, "contains:bar:a", 5, 0);613		if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:bar:a"))614			break;615		id = btf__add_struct(btf, "bar", 24);616		if (!ASSERT_EQ(id, 7, "btf__add_struct bar"))617			break;618		err = btf__add_field(btf, "a", LIST_NODE, 0, 0);619		if (!ASSERT_OK(err, "btf__add_field bar::a"))620			break;621 622		err = btf__load_into_kernel(btf);623		ASSERT_EQ(err, 0, "check btf");624		btf__free(btf);625		break;626	}627 628	while (test__start_subtest("btf: owning -> owning | owned -> owned")) {629		btf = init_btf();630		if (!ASSERT_OK_PTR(btf, "init_btf"))631			break;632		id = btf__add_struct(btf, "foo", 28);633		if (!ASSERT_EQ(id, 5, "btf__add_struct foo"))634			break;635		err = btf__add_field(btf, "a", LIST_HEAD, 0, 0);636		if (!ASSERT_OK(err, "btf__add_field foo::a"))637			break;638		err = btf__add_field(btf, "b", SPIN_LOCK, 192, 0);639		if (!ASSERT_OK(err, "btf__add_field foo::b"))640			break;641		id = btf__add_decl_tag(btf, "contains:bar:b", 5, 0);642		if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:bar:b"))643			break;644		id = btf__add_struct(btf, "bar", 44);645		if (!ASSERT_EQ(id, 7, "btf__add_struct bar"))646			break;647		err = btf__add_field(btf, "a", LIST_HEAD, 0, 0);648		if (!ASSERT_OK(err, "btf__add_field bar::a"))649			break;650		err = btf__add_field(btf, "b", LIST_NODE, 128, 0);651		if (!ASSERT_OK(err, "btf__add_field bar::b"))652			break;653		err = btf__add_field(btf, "c", SPIN_LOCK, 320, 0);654		if (!ASSERT_OK(err, "btf__add_field bar::c"))655			break;656		id = btf__add_decl_tag(btf, "contains:baz:a", 7, 0);657		if (!ASSERT_EQ(id, 8, "btf__add_decl_tag contains:baz:a"))658			break;659		id = btf__add_struct(btf, "baz", 24);660		if (!ASSERT_EQ(id, 9, "btf__add_struct baz"))661			break;662		err = btf__add_field(btf, "a", LIST_NODE, 0, 0);663		if (!ASSERT_OK(err, "btf__add_field baz:a"))664			break;665 666		err = btf__load_into_kernel(btf);667		ASSERT_EQ(err, 0, "check btf");668		btf__free(btf);669		break;670	}671 672	while (test__start_subtest("btf: owning | owned -> owning | owned -> owned")) {673		btf = init_btf();674		if (!ASSERT_OK_PTR(btf, "init_btf"))675			break;676		id = btf__add_struct(btf, "foo", 44);677		if (!ASSERT_EQ(id, 5, "btf__add_struct foo"))678			break;679		err = btf__add_field(btf, "a", LIST_HEAD, 0, 0);680		if (!ASSERT_OK(err, "btf__add_field foo::a"))681			break;682		err = btf__add_field(btf, "b", LIST_NODE, 128, 0);683		if (!ASSERT_OK(err, "btf__add_field foo::b"))684			break;685		err = btf__add_field(btf, "c", SPIN_LOCK, 320, 0);686		if (!ASSERT_OK(err, "btf__add_field foo::c"))687			break;688		id = btf__add_decl_tag(btf, "contains:bar:b", 5, 0);689		if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:bar:b"))690			break;691		id = btf__add_struct(btf, "bar", 44);692		if (!ASSERT_EQ(id, 7, "btf__add_struct bar"))693			break;694		err = btf__add_field(btf, "a", LIST_HEAD, 0, 0);695		if (!ASSERT_OK(err, "btf__add_field bar:a"))696			break;697		err = btf__add_field(btf, "b", LIST_NODE, 128, 0);698		if (!ASSERT_OK(err, "btf__add_field bar:b"))699			break;700		err = btf__add_field(btf, "c", SPIN_LOCK, 320, 0);701		if (!ASSERT_OK(err, "btf__add_field bar:c"))702			break;703		id = btf__add_decl_tag(btf, "contains:baz:a", 7, 0);704		if (!ASSERT_EQ(id, 8, "btf__add_decl_tag contains:baz:a"))705			break;706		id = btf__add_struct(btf, "baz", 24);707		if (!ASSERT_EQ(id, 9, "btf__add_struct baz"))708			break;709		err = btf__add_field(btf, "a", LIST_NODE, 0, 0);710		if (!ASSERT_OK(err, "btf__add_field baz:a"))711			break;712 713		err = btf__load_into_kernel(btf);714		ASSERT_EQ(err, -ELOOP, "check btf");715		btf__free(btf);716		break;717	}718 719	while (test__start_subtest("btf: owning -> owning | owned -> owning | owned -> owned")) {720		btf = init_btf();721		if (!ASSERT_OK_PTR(btf, "init_btf"))722			break;723		id = btf__add_struct(btf, "foo", 20);724		if (!ASSERT_EQ(id, 5, "btf__add_struct foo"))725			break;726		err = btf__add_field(btf, "a", LIST_HEAD, 0, 0);727		if (!ASSERT_OK(err, "btf__add_field foo::a"))728			break;729		err = btf__add_field(btf, "b", SPIN_LOCK, 128, 0);730		if (!ASSERT_OK(err, "btf__add_field foo::b"))731			break;732		id = btf__add_decl_tag(btf, "contains:bar:b", 5, 0);733		if (!ASSERT_EQ(id, 6, "btf__add_decl_tag contains:bar:b"))734			break;735		id = btf__add_struct(btf, "bar", 44);736		if (!ASSERT_EQ(id, 7, "btf__add_struct bar"))737			break;738		err = btf__add_field(btf, "a", LIST_HEAD, 0, 0);739		if (!ASSERT_OK(err, "btf__add_field bar::a"))740			break;741		err = btf__add_field(btf, "b", LIST_NODE, 128, 0);742		if (!ASSERT_OK(err, "btf__add_field bar::b"))743			break;744		err = btf__add_field(btf, "c", SPIN_LOCK, 320, 0);745		if (!ASSERT_OK(err, "btf__add_field bar::c"))746			break;747		id = btf__add_decl_tag(btf, "contains:baz:b", 7, 0);748		if (!ASSERT_EQ(id, 8, "btf__add_decl_tag"))749			break;750		id = btf__add_struct(btf, "baz", 44);751		if (!ASSERT_EQ(id, 9, "btf__add_struct baz"))752			break;753		err = btf__add_field(btf, "a", LIST_HEAD, 0, 0);754		if (!ASSERT_OK(err, "btf__add_field bar::a"))755			break;756		err = btf__add_field(btf, "b", LIST_NODE, 128, 0);757		if (!ASSERT_OK(err, "btf__add_field bar::b"))758			break;759		err = btf__add_field(btf, "c", SPIN_LOCK, 320, 0);760		if (!ASSERT_OK(err, "btf__add_field bar::c"))761			break;762		id = btf__add_decl_tag(btf, "contains:bam:a", 9, 0);763		if (!ASSERT_EQ(id, 10, "btf__add_decl_tag contains:bam:a"))764			break;765		id = btf__add_struct(btf, "bam", 24);766		if (!ASSERT_EQ(id, 11, "btf__add_struct bam"))767			break;768		err = btf__add_field(btf, "a", LIST_NODE, 0, 0);769		if (!ASSERT_OK(err, "btf__add_field bam::a"))770			break;771 772		err = btf__load_into_kernel(btf);773		ASSERT_EQ(err, -ELOOP, "check btf");774		btf__free(btf);775		break;776	}777 778	while (test__start_subtest("btf: list_node and rb_node in same struct")) {779		list_and_rb_node_same_struct(true);780		break;781	}782 783	while (test__start_subtest("btf: list_node and rb_node in same struct, no bpf_refcount")) {784		list_and_rb_node_same_struct(false);785		break;786	}787}788 789void test_linked_list(void)790{791	int i;792 793	for (i = 0; i < ARRAY_SIZE(linked_list_fail_tests); i++) {794		if (!test__start_subtest(linked_list_fail_tests[i].prog_name))795			continue;796		test_linked_list_fail_prog(linked_list_fail_tests[i].prog_name,797					   linked_list_fail_tests[i].err_msg);798	}799	test_btf();800	test_linked_list_success(PUSH_POP, false);801	test_linked_list_success(PUSH_POP, true);802	test_linked_list_success(PUSH_POP_MULT, false);803	test_linked_list_success(PUSH_POP_MULT, true);804	test_linked_list_success(LIST_IN_LIST, false);805	test_linked_list_success(LIST_IN_LIST, true);806	test_linked_list_success(TEST_ALL, false);807}808