1 // SPDX-License-Identifier: GPL-2.0
3 #include <bpf/bpf_tracing.h>
4 #include <bpf/bpf_helpers.h>
5 #include <bpf/bpf_core_read.h>
6 #include "bpf_experimental.h"
8 #include "linked_list.h"
11 struct map_value *v, *v2, *iv, *iv2; \
12 struct foo *f, *f1, *f2; \
16 map = bpf_map_lookup_elem(&map_of_maps, &(int){ 0 }); \
19 v = bpf_map_lookup_elem(&array_map, &(int){ 0 }); \
22 v2 = bpf_map_lookup_elem(&array_map, &(int){ 0 }); \
25 iv = bpf_map_lookup_elem(map, &(int){ 0 }); \
28 iv2 = bpf_map_lookup_elem(map, &(int){ 0 }); \
31 f = bpf_obj_new(typeof(*f)); \
35 f2 = bpf_obj_new(typeof(*f2)); \
40 b = bpf_obj_new(typeof(*b)); \
47 #define CHECK(test, op, hexpr) \
49 int test##_missing_lock_##op(void *ctx) \
52 void (*p)(void *) = (void *)&bpf_list_##op; \
57 CHECK(kptr, pop_front, &f->head);
58 CHECK(kptr, pop_back, &f->head);
60 CHECK(global, pop_front, &ghead);
61 CHECK(global, pop_back, &ghead);
63 CHECK(map, pop_front, &v->head);
64 CHECK(map, pop_back, &v->head);
66 CHECK(inner_map, pop_front, &iv->head);
67 CHECK(inner_map, pop_back, &iv->head);
71 #define CHECK(test, op, hexpr, nexpr) \
73 int test##_missing_lock_##op(void *ctx) \
76 bpf_list_##op(hexpr, nexpr); \
80 CHECK(kptr, push_front, &f->head, &b->node);
81 CHECK(kptr, push_back, &f->head, &b->node);
83 CHECK(global, push_front, &ghead, &f->node2);
84 CHECK(global, push_back, &ghead, &f->node2);
86 CHECK(map, push_front, &v->head, &f->node2);
87 CHECK(map, push_back, &v->head, &f->node2);
89 CHECK(inner_map, push_front, &iv->head, &f->node2);
90 CHECK(inner_map, push_back, &iv->head, &f->node2);
94 #define CHECK(test, op, lexpr, hexpr) \
96 int test##_incorrect_lock_##op(void *ctx) \
99 void (*p)(void *) = (void *)&bpf_list_##op; \
100 bpf_spin_lock(lexpr); \
105 #define CHECK_OP(op) \
106 CHECK(kptr_kptr, op, &f1->lock, &f2->head); \
107 CHECK(kptr_global, op, &f1->lock, &ghead); \
108 CHECK(kptr_map, op, &f1->lock, &v->head); \
109 CHECK(kptr_inner_map, op, &f1->lock, &iv->head); \
111 CHECK(global_global, op, &glock2, &ghead); \
112 CHECK(global_kptr, op, &glock, &f1->head); \
113 CHECK(global_map, op, &glock, &v->head); \
114 CHECK(global_inner_map, op, &glock, &iv->head); \
116 CHECK(map_map, op, &v->lock, &v2->head); \
117 CHECK(map_kptr, op, &v->lock, &f2->head); \
118 CHECK(map_global, op, &v->lock, &ghead); \
119 CHECK(map_inner_map, op, &v->lock, &iv->head); \
121 CHECK(inner_map_inner_map, op, &iv->lock, &iv2->head); \
122 CHECK(inner_map_kptr, op, &iv->lock, &f2->head); \
123 CHECK(inner_map_global, op, &iv->lock, &ghead); \
124 CHECK(inner_map_map, op, &iv->lock, &v->head);
132 #define CHECK(test, op, lexpr, hexpr, nexpr) \
134 int test##_incorrect_lock_##op(void *ctx) \
137 bpf_spin_lock(lexpr); \
138 bpf_list_##op(hexpr, nexpr); \
142 #define CHECK_OP(op) \
143 CHECK(kptr_kptr, op, &f1->lock, &f2->head, &b->node); \
144 CHECK(kptr_global, op, &f1->lock, &ghead, &f->node2); \
145 CHECK(kptr_map, op, &f1->lock, &v->head, &f->node2); \
146 CHECK(kptr_inner_map, op, &f1->lock, &iv->head, &f->node2); \
148 CHECK(global_global, op, &glock2, &ghead, &f->node2); \
149 CHECK(global_kptr, op, &glock, &f1->head, &b->node); \
150 CHECK(global_map, op, &glock, &v->head, &f->node2); \
151 CHECK(global_inner_map, op, &glock, &iv->head, &f->node2); \
153 CHECK(map_map, op, &v->lock, &v2->head, &f->node2); \
154 CHECK(map_kptr, op, &v->lock, &f2->head, &b->node); \
155 CHECK(map_global, op, &v->lock, &ghead, &f->node2); \
156 CHECK(map_inner_map, op, &v->lock, &iv->head, &f->node2); \
158 CHECK(inner_map_inner_map, op, &iv->lock, &iv2->head, &f->node2);\
159 CHECK(inner_map_kptr, op, &iv->lock, &f2->head, &b->node); \
160 CHECK(inner_map_global, op, &iv->lock, &ghead, &f->node2); \
161 CHECK(inner_map_map, op, &iv->lock, &v->head, &f->node2);
163 CHECK_OP(push_front);
171 int map_compat_kprobe(void *ctx)
173 bpf_list_push_front(&ghead, NULL);
177 SEC("?kretprobe/xyz")
178 int map_compat_kretprobe(void *ctx)
180 bpf_list_push_front(&ghead, NULL);
184 SEC("?tracepoint/xyz")
185 int map_compat_tp(void *ctx)
187 bpf_list_push_front(&ghead, NULL);
192 int map_compat_perf(void *ctx)
194 bpf_list_push_front(&ghead, NULL);
199 int map_compat_raw_tp(void *ctx)
201 bpf_list_push_front(&ghead, NULL);
206 int map_compat_raw_tp_w(void *ctx)
208 bpf_list_push_front(&ghead, NULL);
213 int obj_type_id_oor(void *ctx)
215 bpf_obj_new_impl(~0UL, NULL);
220 int obj_new_no_composite(void *ctx)
222 bpf_obj_new_impl(bpf_core_type_id_local(int), (void *)42);
227 int obj_new_no_struct(void *ctx)
230 bpf_obj_new(union { int data; unsigned udata; });
235 int obj_drop_non_zero_off(void *ctx)
239 f = bpf_obj_new(struct foo);
247 int new_null_ret(void *ctx)
249 return bpf_obj_new(struct foo)->data;
253 int obj_new_acq(void *ctx)
255 bpf_obj_new(struct foo);
260 int use_after_drop(void *ctx)
264 f = bpf_obj_new(typeof(*f));
272 int ptr_walk_scalar(void *ctx)
280 p = bpf_obj_new(typeof(*p));
283 bpf_this_cpu_ptr(p->ptr);
288 int direct_read_lock(void *ctx)
292 f = bpf_obj_new(typeof(*f));
295 return *(int *)&f->lock;
299 int direct_write_lock(void *ctx)
303 f = bpf_obj_new(typeof(*f));
306 *(int *)&f->lock = 0;
311 int direct_read_head(void *ctx)
315 f = bpf_obj_new(typeof(*f));
318 return *(int *)&f->head;
322 int direct_write_head(void *ctx)
326 f = bpf_obj_new(typeof(*f));
329 *(int *)&f->head = 0;
334 int direct_read_node(void *ctx)
338 f = bpf_obj_new(typeof(*f));
341 return *(int *)&f->node2;
345 int direct_write_node(void *ctx)
349 f = bpf_obj_new(typeof(*f));
352 *(int *)&f->node2 = 0;
356 static __always_inline
357 int use_after_unlock(bool push_front)
361 f = bpf_obj_new(typeof(*f));
364 bpf_spin_lock(&glock);
367 bpf_list_push_front(&ghead, &f->node2);
369 bpf_list_push_back(&ghead, &f->node2);
370 bpf_spin_unlock(&glock);
376 int use_after_unlock_push_front(void *ctx)
378 return use_after_unlock(true);
382 int use_after_unlock_push_back(void *ctx)
384 return use_after_unlock(false);
387 static __always_inline
388 int list_double_add(bool push_front)
392 f = bpf_obj_new(typeof(*f));
395 bpf_spin_lock(&glock);
397 bpf_list_push_front(&ghead, &f->node2);
398 bpf_list_push_front(&ghead, &f->node2);
400 bpf_list_push_back(&ghead, &f->node2);
401 bpf_list_push_back(&ghead, &f->node2);
403 bpf_spin_unlock(&glock);
409 int double_push_front(void *ctx)
411 return list_double_add(true);
415 int double_push_back(void *ctx)
417 return list_double_add(false);
421 int no_node_value_type(void *ctx)
425 p = bpf_obj_new(struct { int data; });
428 bpf_spin_lock(&glock);
429 bpf_list_push_front(&ghead, p);
430 bpf_spin_unlock(&glock);
436 int incorrect_value_type(void *ctx)
440 b = bpf_obj_new(typeof(*b));
443 bpf_spin_lock(&glock);
444 bpf_list_push_front(&ghead, &b->node);
445 bpf_spin_unlock(&glock);
451 int incorrect_node_var_off(struct __sk_buff *ctx)
455 f = bpf_obj_new(typeof(*f));
458 bpf_spin_lock(&glock);
459 bpf_list_push_front(&ghead, (void *)&f->node2 + ctx->protocol);
460 bpf_spin_unlock(&glock);
466 int incorrect_node_off1(void *ctx)
470 f = bpf_obj_new(typeof(*f));
473 bpf_spin_lock(&glock);
474 bpf_list_push_front(&ghead, (void *)&f->node2 + 1);
475 bpf_spin_unlock(&glock);
481 int incorrect_node_off2(void *ctx)
485 f = bpf_obj_new(typeof(*f));
488 bpf_spin_lock(&glock);
489 bpf_list_push_front(&ghead, &f->node);
490 bpf_spin_unlock(&glock);
496 int no_head_type(void *ctx)
500 p = bpf_obj_new(typeof(struct { int data; }));
503 bpf_spin_lock(&glock);
504 bpf_list_push_front(p, NULL);
505 bpf_spin_lock(&glock);
511 int incorrect_head_var_off1(struct __sk_buff *ctx)
515 f = bpf_obj_new(typeof(*f));
518 bpf_spin_lock(&glock);
519 bpf_list_push_front((void *)&ghead + ctx->protocol, &f->node2);
520 bpf_spin_unlock(&glock);
526 int incorrect_head_var_off2(struct __sk_buff *ctx)
530 f = bpf_obj_new(typeof(*f));
533 bpf_spin_lock(&glock);
534 bpf_list_push_front((void *)&f->head + ctx->protocol, &f->node2);
535 bpf_spin_unlock(&glock);
541 int incorrect_head_off1(void *ctx)
546 f = bpf_obj_new(typeof(*f));
549 b = bpf_obj_new(typeof(*b));
555 bpf_spin_lock(&f->lock);
556 bpf_list_push_front((void *)&f->head + 1, &b->node);
557 bpf_spin_unlock(&f->lock);
563 int incorrect_head_off2(void *ctx)
567 f = bpf_obj_new(typeof(*f));
571 bpf_spin_lock(&glock);
572 bpf_list_push_front((void *)&ghead + 1, &f->node2);
573 bpf_spin_unlock(&glock);
578 static __always_inline
579 int pop_ptr_off(void *(*op)(void *head))
582 struct bpf_list_head head __contains(foo, node2);
583 struct bpf_spin_lock lock;
585 struct bpf_list_node *n;
587 p = bpf_obj_new(typeof(*p));
590 bpf_spin_lock(&p->lock);
592 bpf_spin_unlock(&p->lock);
596 bpf_spin_lock((void *)n);
601 int pop_front_off(void *ctx)
603 return pop_ptr_off((void *)bpf_list_pop_front);
607 int pop_back_off(void *ctx)
609 return pop_ptr_off((void *)bpf_list_pop_back);
612 char _license[] SEC("license") = "GPL";