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