1300f19dcSKumar Kartikeya Dwivedi // SPDX-License-Identifier: GPL-2.0
2300f19dcSKumar Kartikeya Dwivedi #include <vmlinux.h>
3300f19dcSKumar Kartikeya Dwivedi #include <bpf/bpf_tracing.h>
4300f19dcSKumar Kartikeya Dwivedi #include <bpf/bpf_helpers.h>
5300f19dcSKumar Kartikeya Dwivedi #include <bpf/bpf_core_read.h>
6300f19dcSKumar Kartikeya Dwivedi #include "bpf_experimental.h"
7300f19dcSKumar Kartikeya Dwivedi 
8300f19dcSKumar Kartikeya Dwivedi #include "linked_list.h"
9300f19dcSKumar Kartikeya Dwivedi 
10300f19dcSKumar Kartikeya Dwivedi #define INIT                                                  \
11300f19dcSKumar Kartikeya Dwivedi 	struct map_value *v, *v2, *iv, *iv2;                  \
12300f19dcSKumar Kartikeya Dwivedi 	struct foo *f, *f1, *f2;                              \
13300f19dcSKumar Kartikeya Dwivedi 	struct bar *b;                                        \
14300f19dcSKumar Kartikeya Dwivedi 	void *map;                                            \
15300f19dcSKumar Kartikeya Dwivedi                                                               \
16300f19dcSKumar Kartikeya Dwivedi 	map = bpf_map_lookup_elem(&map_of_maps, &(int){ 0 }); \
17300f19dcSKumar Kartikeya Dwivedi 	if (!map)                                             \
18300f19dcSKumar Kartikeya Dwivedi 		return 0;                                     \
19300f19dcSKumar Kartikeya Dwivedi 	v = bpf_map_lookup_elem(&array_map, &(int){ 0 });     \
20300f19dcSKumar Kartikeya Dwivedi 	if (!v)                                               \
21300f19dcSKumar Kartikeya Dwivedi 		return 0;                                     \
22300f19dcSKumar Kartikeya Dwivedi 	v2 = bpf_map_lookup_elem(&array_map, &(int){ 0 });    \
23300f19dcSKumar Kartikeya Dwivedi 	if (!v2)                                              \
24300f19dcSKumar Kartikeya Dwivedi 		return 0;                                     \
25300f19dcSKumar Kartikeya Dwivedi 	iv = bpf_map_lookup_elem(map, &(int){ 0 });           \
26300f19dcSKumar Kartikeya Dwivedi 	if (!iv)                                              \
27300f19dcSKumar Kartikeya Dwivedi 		return 0;                                     \
28300f19dcSKumar Kartikeya Dwivedi 	iv2 = bpf_map_lookup_elem(map, &(int){ 0 });          \
29300f19dcSKumar Kartikeya Dwivedi 	if (!iv2)                                             \
30300f19dcSKumar Kartikeya Dwivedi 		return 0;                                     \
31300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));                          \
32300f19dcSKumar Kartikeya Dwivedi 	if (!f)                                               \
33300f19dcSKumar Kartikeya Dwivedi 		return 0;                                     \
34300f19dcSKumar Kartikeya Dwivedi 	f1 = f;                                               \
35300f19dcSKumar Kartikeya Dwivedi 	f2 = bpf_obj_new(typeof(*f2));                        \
36300f19dcSKumar Kartikeya Dwivedi 	if (!f2) {                                            \
37300f19dcSKumar Kartikeya Dwivedi 		bpf_obj_drop(f1);                             \
38300f19dcSKumar Kartikeya Dwivedi 		return 0;                                     \
39300f19dcSKumar Kartikeya Dwivedi 	}                                                     \
40300f19dcSKumar Kartikeya Dwivedi 	b = bpf_obj_new(typeof(*b));                          \
41300f19dcSKumar Kartikeya Dwivedi 	if (!b) {                                             \
42300f19dcSKumar Kartikeya Dwivedi 		bpf_obj_drop(f2);                             \
43300f19dcSKumar Kartikeya Dwivedi 		bpf_obj_drop(f1);                             \
44300f19dcSKumar Kartikeya Dwivedi 		return 0;                                     \
45300f19dcSKumar Kartikeya Dwivedi 	}
46300f19dcSKumar Kartikeya Dwivedi 
47300f19dcSKumar Kartikeya Dwivedi #define CHECK(test, op, hexpr)                              \
48300f19dcSKumar Kartikeya Dwivedi 	SEC("?tc")                                          \
49300f19dcSKumar Kartikeya Dwivedi 	int test##_missing_lock_##op(void *ctx)             \
50300f19dcSKumar Kartikeya Dwivedi 	{                                                   \
51300f19dcSKumar Kartikeya Dwivedi 		INIT;                                       \
52300f19dcSKumar Kartikeya Dwivedi 		void (*p)(void *) = (void *)&bpf_list_##op; \
53300f19dcSKumar Kartikeya Dwivedi 		p(hexpr);                                   \
54300f19dcSKumar Kartikeya Dwivedi 		return 0;                                   \
55300f19dcSKumar Kartikeya Dwivedi 	}
56300f19dcSKumar Kartikeya Dwivedi 
57300f19dcSKumar Kartikeya Dwivedi CHECK(kptr, pop_front, &f->head);
58300f19dcSKumar Kartikeya Dwivedi CHECK(kptr, pop_back, &f->head);
59300f19dcSKumar Kartikeya Dwivedi 
60300f19dcSKumar Kartikeya Dwivedi CHECK(global, pop_front, &ghead);
61300f19dcSKumar Kartikeya Dwivedi CHECK(global, pop_back, &ghead);
62300f19dcSKumar Kartikeya Dwivedi 
63300f19dcSKumar Kartikeya Dwivedi CHECK(map, pop_front, &v->head);
64300f19dcSKumar Kartikeya Dwivedi CHECK(map, pop_back, &v->head);
65300f19dcSKumar Kartikeya Dwivedi 
66300f19dcSKumar Kartikeya Dwivedi CHECK(inner_map, pop_front, &iv->head);
67300f19dcSKumar Kartikeya Dwivedi CHECK(inner_map, pop_back, &iv->head);
68300f19dcSKumar Kartikeya Dwivedi 
69300f19dcSKumar Kartikeya Dwivedi #undef CHECK
70300f19dcSKumar Kartikeya Dwivedi 
71*6a3cd331SDave Marchevsky #define CHECK(test, op, hexpr, nexpr)					\
72*6a3cd331SDave Marchevsky 	SEC("?tc")							\
73*6a3cd331SDave Marchevsky 	int test##_missing_lock_##op(void *ctx)				\
74*6a3cd331SDave Marchevsky 	{								\
75*6a3cd331SDave Marchevsky 		INIT;							\
76*6a3cd331SDave Marchevsky 		void (*p)(void *, void *) = (void *)&bpf_list_##op;	\
77*6a3cd331SDave Marchevsky 		p(hexpr, nexpr);					\
78*6a3cd331SDave Marchevsky 		return 0;						\
79*6a3cd331SDave Marchevsky 	}
80*6a3cd331SDave Marchevsky 
81*6a3cd331SDave Marchevsky CHECK(kptr, push_front, &f->head, b);
82*6a3cd331SDave Marchevsky CHECK(kptr, push_back, &f->head, b);
83*6a3cd331SDave Marchevsky 
84*6a3cd331SDave Marchevsky CHECK(global, push_front, &ghead, f);
85*6a3cd331SDave Marchevsky CHECK(global, push_back, &ghead, f);
86*6a3cd331SDave Marchevsky 
87*6a3cd331SDave Marchevsky CHECK(map, push_front, &v->head, f);
88*6a3cd331SDave Marchevsky CHECK(map, push_back, &v->head, f);
89*6a3cd331SDave Marchevsky 
90*6a3cd331SDave Marchevsky CHECK(inner_map, push_front, &iv->head, f);
91*6a3cd331SDave Marchevsky CHECK(inner_map, push_back, &iv->head, f);
92*6a3cd331SDave Marchevsky 
93*6a3cd331SDave Marchevsky #undef CHECK
94*6a3cd331SDave Marchevsky 
95300f19dcSKumar Kartikeya Dwivedi #define CHECK(test, op, lexpr, hexpr)                       \
96300f19dcSKumar Kartikeya Dwivedi 	SEC("?tc")                                          \
97300f19dcSKumar Kartikeya Dwivedi 	int test##_incorrect_lock_##op(void *ctx)           \
98300f19dcSKumar Kartikeya Dwivedi 	{                                                   \
99300f19dcSKumar Kartikeya Dwivedi 		INIT;                                       \
100300f19dcSKumar Kartikeya Dwivedi 		void (*p)(void *) = (void *)&bpf_list_##op; \
101300f19dcSKumar Kartikeya Dwivedi 		bpf_spin_lock(lexpr);                       \
102300f19dcSKumar Kartikeya Dwivedi 		p(hexpr);                                   \
103300f19dcSKumar Kartikeya Dwivedi 		return 0;                                   \
104300f19dcSKumar Kartikeya Dwivedi 	}
105300f19dcSKumar Kartikeya Dwivedi 
106300f19dcSKumar Kartikeya Dwivedi #define CHECK_OP(op)                                           \
107300f19dcSKumar Kartikeya Dwivedi 	CHECK(kptr_kptr, op, &f1->lock, &f2->head);            \
1080b2971a2SAlexei Starovoitov 	CHECK(kptr_global, op, &f1->lock, &ghead);             \
109300f19dcSKumar Kartikeya Dwivedi 	CHECK(kptr_map, op, &f1->lock, &v->head);              \
110300f19dcSKumar Kartikeya Dwivedi 	CHECK(kptr_inner_map, op, &f1->lock, &iv->head);       \
111300f19dcSKumar Kartikeya Dwivedi                                                                \
1120b2971a2SAlexei Starovoitov 	CHECK(global_global, op, &glock2, &ghead);             \
1130b2971a2SAlexei Starovoitov 	CHECK(global_kptr, op, &glock, &f1->head);             \
1140b2971a2SAlexei Starovoitov 	CHECK(global_map, op, &glock, &v->head);               \
1150b2971a2SAlexei Starovoitov 	CHECK(global_inner_map, op, &glock, &iv->head);        \
1160b2971a2SAlexei Starovoitov                                                                \
117300f19dcSKumar Kartikeya Dwivedi 	CHECK(map_map, op, &v->lock, &v2->head);               \
118300f19dcSKumar Kartikeya Dwivedi 	CHECK(map_kptr, op, &v->lock, &f2->head);              \
1190b2971a2SAlexei Starovoitov 	CHECK(map_global, op, &v->lock, &ghead);               \
120300f19dcSKumar Kartikeya Dwivedi 	CHECK(map_inner_map, op, &v->lock, &iv->head);         \
121300f19dcSKumar Kartikeya Dwivedi                                                                \
122300f19dcSKumar Kartikeya Dwivedi 	CHECK(inner_map_inner_map, op, &iv->lock, &iv2->head); \
123300f19dcSKumar Kartikeya Dwivedi 	CHECK(inner_map_kptr, op, &iv->lock, &f2->head);       \
1240b2971a2SAlexei Starovoitov 	CHECK(inner_map_global, op, &iv->lock, &ghead);        \
125300f19dcSKumar Kartikeya Dwivedi 	CHECK(inner_map_map, op, &iv->lock, &v->head);
126300f19dcSKumar Kartikeya Dwivedi 
127300f19dcSKumar Kartikeya Dwivedi CHECK_OP(pop_front);
128300f19dcSKumar Kartikeya Dwivedi CHECK_OP(pop_back);
129300f19dcSKumar Kartikeya Dwivedi 
130300f19dcSKumar Kartikeya Dwivedi #undef CHECK
131300f19dcSKumar Kartikeya Dwivedi #undef CHECK_OP
132*6a3cd331SDave Marchevsky 
133*6a3cd331SDave Marchevsky #define CHECK(test, op, lexpr, hexpr, nexpr)				\
134*6a3cd331SDave Marchevsky 	SEC("?tc")							\
135*6a3cd331SDave Marchevsky 	int test##_incorrect_lock_##op(void *ctx)			\
136*6a3cd331SDave Marchevsky 	{								\
137*6a3cd331SDave Marchevsky 		INIT;							\
138*6a3cd331SDave Marchevsky 		void (*p)(void *, void*) = (void *)&bpf_list_##op;	\
139*6a3cd331SDave Marchevsky 		bpf_spin_lock(lexpr);					\
140*6a3cd331SDave Marchevsky 		p(hexpr, nexpr);					\
141*6a3cd331SDave Marchevsky 		return 0;						\
142*6a3cd331SDave Marchevsky 	}
143*6a3cd331SDave Marchevsky 
144*6a3cd331SDave Marchevsky #define CHECK_OP(op)							\
145*6a3cd331SDave Marchevsky 	CHECK(kptr_kptr, op, &f1->lock, &f2->head, b);			\
146*6a3cd331SDave Marchevsky 	CHECK(kptr_global, op, &f1->lock, &ghead, f);			\
147*6a3cd331SDave Marchevsky 	CHECK(kptr_map, op, &f1->lock, &v->head, f);			\
148*6a3cd331SDave Marchevsky 	CHECK(kptr_inner_map, op, &f1->lock, &iv->head, f);		\
149*6a3cd331SDave Marchevsky 									\
150*6a3cd331SDave Marchevsky 	CHECK(global_global, op, &glock2, &ghead, f);			\
151*6a3cd331SDave Marchevsky 	CHECK(global_kptr, op, &glock, &f1->head, b);			\
152*6a3cd331SDave Marchevsky 	CHECK(global_map, op, &glock, &v->head, f);			\
153*6a3cd331SDave Marchevsky 	CHECK(global_inner_map, op, &glock, &iv->head, f);		\
154*6a3cd331SDave Marchevsky 									\
155*6a3cd331SDave Marchevsky 	CHECK(map_map, op, &v->lock, &v2->head, f);			\
156*6a3cd331SDave Marchevsky 	CHECK(map_kptr, op, &v->lock, &f2->head, b);			\
157*6a3cd331SDave Marchevsky 	CHECK(map_global, op, &v->lock, &ghead, f);			\
158*6a3cd331SDave Marchevsky 	CHECK(map_inner_map, op, &v->lock, &iv->head, f);		\
159*6a3cd331SDave Marchevsky 									\
160*6a3cd331SDave Marchevsky 	CHECK(inner_map_inner_map, op, &iv->lock, &iv2->head, f);	\
161*6a3cd331SDave Marchevsky 	CHECK(inner_map_kptr, op, &iv->lock, &f2->head, b);		\
162*6a3cd331SDave Marchevsky 	CHECK(inner_map_global, op, &iv->lock, &ghead, f);		\
163*6a3cd331SDave Marchevsky 	CHECK(inner_map_map, op, &iv->lock, &v->head, f);
164*6a3cd331SDave Marchevsky 
165*6a3cd331SDave Marchevsky CHECK_OP(push_front);
166*6a3cd331SDave Marchevsky CHECK_OP(push_back);
167*6a3cd331SDave Marchevsky 
168*6a3cd331SDave Marchevsky #undef CHECK
169*6a3cd331SDave Marchevsky #undef CHECK_OP
170300f19dcSKumar Kartikeya Dwivedi #undef INIT
171300f19dcSKumar Kartikeya Dwivedi 
172300f19dcSKumar Kartikeya Dwivedi SEC("?kprobe/xyz")
173300f19dcSKumar Kartikeya Dwivedi int map_compat_kprobe(void *ctx)
174300f19dcSKumar Kartikeya Dwivedi {
175300f19dcSKumar Kartikeya Dwivedi 	bpf_list_push_front(&ghead, NULL);
176300f19dcSKumar Kartikeya Dwivedi 	return 0;
177300f19dcSKumar Kartikeya Dwivedi }
178300f19dcSKumar Kartikeya Dwivedi 
179300f19dcSKumar Kartikeya Dwivedi SEC("?kretprobe/xyz")
180300f19dcSKumar Kartikeya Dwivedi int map_compat_kretprobe(void *ctx)
181300f19dcSKumar Kartikeya Dwivedi {
182300f19dcSKumar Kartikeya Dwivedi 	bpf_list_push_front(&ghead, NULL);
183300f19dcSKumar Kartikeya Dwivedi 	return 0;
184300f19dcSKumar Kartikeya Dwivedi }
185300f19dcSKumar Kartikeya Dwivedi 
186300f19dcSKumar Kartikeya Dwivedi SEC("?tracepoint/xyz")
187300f19dcSKumar Kartikeya Dwivedi int map_compat_tp(void *ctx)
188300f19dcSKumar Kartikeya Dwivedi {
189300f19dcSKumar Kartikeya Dwivedi 	bpf_list_push_front(&ghead, NULL);
190300f19dcSKumar Kartikeya Dwivedi 	return 0;
191300f19dcSKumar Kartikeya Dwivedi }
192300f19dcSKumar Kartikeya Dwivedi 
193300f19dcSKumar Kartikeya Dwivedi SEC("?perf_event")
194300f19dcSKumar Kartikeya Dwivedi int map_compat_perf(void *ctx)
195300f19dcSKumar Kartikeya Dwivedi {
196300f19dcSKumar Kartikeya Dwivedi 	bpf_list_push_front(&ghead, NULL);
197300f19dcSKumar Kartikeya Dwivedi 	return 0;
198300f19dcSKumar Kartikeya Dwivedi }
199300f19dcSKumar Kartikeya Dwivedi 
200300f19dcSKumar Kartikeya Dwivedi SEC("?raw_tp/xyz")
201300f19dcSKumar Kartikeya Dwivedi int map_compat_raw_tp(void *ctx)
202300f19dcSKumar Kartikeya Dwivedi {
203300f19dcSKumar Kartikeya Dwivedi 	bpf_list_push_front(&ghead, NULL);
204300f19dcSKumar Kartikeya Dwivedi 	return 0;
205300f19dcSKumar Kartikeya Dwivedi }
206300f19dcSKumar Kartikeya Dwivedi 
207300f19dcSKumar Kartikeya Dwivedi SEC("?raw_tp.w/xyz")
208300f19dcSKumar Kartikeya Dwivedi int map_compat_raw_tp_w(void *ctx)
209300f19dcSKumar Kartikeya Dwivedi {
210300f19dcSKumar Kartikeya Dwivedi 	bpf_list_push_front(&ghead, NULL);
211300f19dcSKumar Kartikeya Dwivedi 	return 0;
212300f19dcSKumar Kartikeya Dwivedi }
213300f19dcSKumar Kartikeya Dwivedi 
214300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
215300f19dcSKumar Kartikeya Dwivedi int obj_type_id_oor(void *ctx)
216300f19dcSKumar Kartikeya Dwivedi {
217300f19dcSKumar Kartikeya Dwivedi 	bpf_obj_new_impl(~0UL, NULL);
218300f19dcSKumar Kartikeya Dwivedi 	return 0;
219300f19dcSKumar Kartikeya Dwivedi }
220300f19dcSKumar Kartikeya Dwivedi 
221300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
222300f19dcSKumar Kartikeya Dwivedi int obj_new_no_composite(void *ctx)
223300f19dcSKumar Kartikeya Dwivedi {
224300f19dcSKumar Kartikeya Dwivedi 	bpf_obj_new_impl(bpf_core_type_id_local(int), (void *)42);
225300f19dcSKumar Kartikeya Dwivedi 	return 0;
226300f19dcSKumar Kartikeya Dwivedi }
227300f19dcSKumar Kartikeya Dwivedi 
228300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
229300f19dcSKumar Kartikeya Dwivedi int obj_new_no_struct(void *ctx)
230300f19dcSKumar Kartikeya Dwivedi {
231300f19dcSKumar Kartikeya Dwivedi 
232300f19dcSKumar Kartikeya Dwivedi 	bpf_obj_new(union { int data; unsigned udata; });
233300f19dcSKumar Kartikeya Dwivedi 	return 0;
234300f19dcSKumar Kartikeya Dwivedi }
235300f19dcSKumar Kartikeya Dwivedi 
236300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
237300f19dcSKumar Kartikeya Dwivedi int obj_drop_non_zero_off(void *ctx)
238300f19dcSKumar Kartikeya Dwivedi {
239300f19dcSKumar Kartikeya Dwivedi 	void *f;
240300f19dcSKumar Kartikeya Dwivedi 
241300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(struct foo);
242300f19dcSKumar Kartikeya Dwivedi 	if (!f)
243300f19dcSKumar Kartikeya Dwivedi 		return 0;
244300f19dcSKumar Kartikeya Dwivedi 	bpf_obj_drop(f+1);
245300f19dcSKumar Kartikeya Dwivedi 	return 0;
246300f19dcSKumar Kartikeya Dwivedi }
247300f19dcSKumar Kartikeya Dwivedi 
248300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
249300f19dcSKumar Kartikeya Dwivedi int new_null_ret(void *ctx)
250300f19dcSKumar Kartikeya Dwivedi {
251300f19dcSKumar Kartikeya Dwivedi 	return bpf_obj_new(struct foo)->data;
252300f19dcSKumar Kartikeya Dwivedi }
253300f19dcSKumar Kartikeya Dwivedi 
254300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
255300f19dcSKumar Kartikeya Dwivedi int obj_new_acq(void *ctx)
256300f19dcSKumar Kartikeya Dwivedi {
257300f19dcSKumar Kartikeya Dwivedi 	bpf_obj_new(struct foo);
258300f19dcSKumar Kartikeya Dwivedi 	return 0;
259300f19dcSKumar Kartikeya Dwivedi }
260300f19dcSKumar Kartikeya Dwivedi 
261300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
262300f19dcSKumar Kartikeya Dwivedi int use_after_drop(void *ctx)
263300f19dcSKumar Kartikeya Dwivedi {
264300f19dcSKumar Kartikeya Dwivedi 	struct foo *f;
265300f19dcSKumar Kartikeya Dwivedi 
266300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
267300f19dcSKumar Kartikeya Dwivedi 	if (!f)
268300f19dcSKumar Kartikeya Dwivedi 		return 0;
269300f19dcSKumar Kartikeya Dwivedi 	bpf_obj_drop(f);
270300f19dcSKumar Kartikeya Dwivedi 	return f->data;
271300f19dcSKumar Kartikeya Dwivedi }
272300f19dcSKumar Kartikeya Dwivedi 
273300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
274300f19dcSKumar Kartikeya Dwivedi int ptr_walk_scalar(void *ctx)
275300f19dcSKumar Kartikeya Dwivedi {
276300f19dcSKumar Kartikeya Dwivedi 	struct test1 {
277300f19dcSKumar Kartikeya Dwivedi 		struct test2 {
278300f19dcSKumar Kartikeya Dwivedi 			struct test2 *next;
279300f19dcSKumar Kartikeya Dwivedi 		} *ptr;
280300f19dcSKumar Kartikeya Dwivedi 	} *p;
281300f19dcSKumar Kartikeya Dwivedi 
282300f19dcSKumar Kartikeya Dwivedi 	p = bpf_obj_new(typeof(*p));
283300f19dcSKumar Kartikeya Dwivedi 	if (!p)
284300f19dcSKumar Kartikeya Dwivedi 		return 0;
285300f19dcSKumar Kartikeya Dwivedi 	bpf_this_cpu_ptr(p->ptr);
286300f19dcSKumar Kartikeya Dwivedi 	return 0;
287300f19dcSKumar Kartikeya Dwivedi }
288300f19dcSKumar Kartikeya Dwivedi 
289300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
290300f19dcSKumar Kartikeya Dwivedi int direct_read_lock(void *ctx)
291300f19dcSKumar Kartikeya Dwivedi {
292300f19dcSKumar Kartikeya Dwivedi 	struct foo *f;
293300f19dcSKumar Kartikeya Dwivedi 
294300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
295300f19dcSKumar Kartikeya Dwivedi 	if (!f)
296300f19dcSKumar Kartikeya Dwivedi 		return 0;
297300f19dcSKumar Kartikeya Dwivedi 	return *(int *)&f->lock;
298300f19dcSKumar Kartikeya Dwivedi }
299300f19dcSKumar Kartikeya Dwivedi 
300300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
301300f19dcSKumar Kartikeya Dwivedi int direct_write_lock(void *ctx)
302300f19dcSKumar Kartikeya Dwivedi {
303300f19dcSKumar Kartikeya Dwivedi 	struct foo *f;
304300f19dcSKumar Kartikeya Dwivedi 
305300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
306300f19dcSKumar Kartikeya Dwivedi 	if (!f)
307300f19dcSKumar Kartikeya Dwivedi 		return 0;
308300f19dcSKumar Kartikeya Dwivedi 	*(int *)&f->lock = 0;
309300f19dcSKumar Kartikeya Dwivedi 	return 0;
310300f19dcSKumar Kartikeya Dwivedi }
311300f19dcSKumar Kartikeya Dwivedi 
312300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
313300f19dcSKumar Kartikeya Dwivedi int direct_read_head(void *ctx)
314300f19dcSKumar Kartikeya Dwivedi {
315300f19dcSKumar Kartikeya Dwivedi 	struct foo *f;
316300f19dcSKumar Kartikeya Dwivedi 
317300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
318300f19dcSKumar Kartikeya Dwivedi 	if (!f)
319300f19dcSKumar Kartikeya Dwivedi 		return 0;
320300f19dcSKumar Kartikeya Dwivedi 	return *(int *)&f->head;
321300f19dcSKumar Kartikeya Dwivedi }
322300f19dcSKumar Kartikeya Dwivedi 
323300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
324300f19dcSKumar Kartikeya Dwivedi int direct_write_head(void *ctx)
325300f19dcSKumar Kartikeya Dwivedi {
326300f19dcSKumar Kartikeya Dwivedi 	struct foo *f;
327300f19dcSKumar Kartikeya Dwivedi 
328300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
329300f19dcSKumar Kartikeya Dwivedi 	if (!f)
330300f19dcSKumar Kartikeya Dwivedi 		return 0;
331300f19dcSKumar Kartikeya Dwivedi 	*(int *)&f->head = 0;
332300f19dcSKumar Kartikeya Dwivedi 	return 0;
333300f19dcSKumar Kartikeya Dwivedi }
334300f19dcSKumar Kartikeya Dwivedi 
335300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
336300f19dcSKumar Kartikeya Dwivedi int direct_read_node(void *ctx)
337300f19dcSKumar Kartikeya Dwivedi {
338300f19dcSKumar Kartikeya Dwivedi 	struct foo *f;
339300f19dcSKumar Kartikeya Dwivedi 
340300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
341300f19dcSKumar Kartikeya Dwivedi 	if (!f)
342300f19dcSKumar Kartikeya Dwivedi 		return 0;
343300f19dcSKumar Kartikeya Dwivedi 	return *(int *)&f->node;
344300f19dcSKumar Kartikeya Dwivedi }
345300f19dcSKumar Kartikeya Dwivedi 
346300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
347300f19dcSKumar Kartikeya Dwivedi int direct_write_node(void *ctx)
348300f19dcSKumar Kartikeya Dwivedi {
349300f19dcSKumar Kartikeya Dwivedi 	struct foo *f;
350300f19dcSKumar Kartikeya Dwivedi 
351300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
352300f19dcSKumar Kartikeya Dwivedi 	if (!f)
353300f19dcSKumar Kartikeya Dwivedi 		return 0;
354300f19dcSKumar Kartikeya Dwivedi 	*(int *)&f->node = 0;
355300f19dcSKumar Kartikeya Dwivedi 	return 0;
356300f19dcSKumar Kartikeya Dwivedi }
357300f19dcSKumar Kartikeya Dwivedi 
358300f19dcSKumar Kartikeya Dwivedi static __always_inline
359300f19dcSKumar Kartikeya Dwivedi int use_after_unlock(void (*op)(void *head, void *node))
360300f19dcSKumar Kartikeya Dwivedi {
361300f19dcSKumar Kartikeya Dwivedi 	struct foo *f;
362300f19dcSKumar Kartikeya Dwivedi 
363300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
364300f19dcSKumar Kartikeya Dwivedi 	if (!f)
365300f19dcSKumar Kartikeya Dwivedi 		return 0;
366300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_lock(&glock);
367300f19dcSKumar Kartikeya Dwivedi 	f->data = 42;
368300f19dcSKumar Kartikeya Dwivedi 	op(&ghead, &f->node);
369300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_unlock(&glock);
370300f19dcSKumar Kartikeya Dwivedi 
371300f19dcSKumar Kartikeya Dwivedi 	return f->data;
372300f19dcSKumar Kartikeya Dwivedi }
373300f19dcSKumar Kartikeya Dwivedi 
374300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
375300f19dcSKumar Kartikeya Dwivedi int use_after_unlock_push_front(void *ctx)
376300f19dcSKumar Kartikeya Dwivedi {
377300f19dcSKumar Kartikeya Dwivedi 	return use_after_unlock((void *)bpf_list_push_front);
378300f19dcSKumar Kartikeya Dwivedi }
379300f19dcSKumar Kartikeya Dwivedi 
380300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
381300f19dcSKumar Kartikeya Dwivedi int use_after_unlock_push_back(void *ctx)
382300f19dcSKumar Kartikeya Dwivedi {
383300f19dcSKumar Kartikeya Dwivedi 	return use_after_unlock((void *)bpf_list_push_back);
384300f19dcSKumar Kartikeya Dwivedi }
385300f19dcSKumar Kartikeya Dwivedi 
386300f19dcSKumar Kartikeya Dwivedi static __always_inline
387300f19dcSKumar Kartikeya Dwivedi int list_double_add(void (*op)(void *head, void *node))
388300f19dcSKumar Kartikeya Dwivedi {
389300f19dcSKumar Kartikeya Dwivedi 	struct foo *f;
390300f19dcSKumar Kartikeya Dwivedi 
391300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
392300f19dcSKumar Kartikeya Dwivedi 	if (!f)
393300f19dcSKumar Kartikeya Dwivedi 		return 0;
394300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_lock(&glock);
395300f19dcSKumar Kartikeya Dwivedi 	op(&ghead, &f->node);
396300f19dcSKumar Kartikeya Dwivedi 	op(&ghead, &f->node);
397300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_unlock(&glock);
398300f19dcSKumar Kartikeya Dwivedi 
399300f19dcSKumar Kartikeya Dwivedi 	return 0;
400300f19dcSKumar Kartikeya Dwivedi }
401300f19dcSKumar Kartikeya Dwivedi 
402300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
403300f19dcSKumar Kartikeya Dwivedi int double_push_front(void *ctx)
404300f19dcSKumar Kartikeya Dwivedi {
405300f19dcSKumar Kartikeya Dwivedi 	return list_double_add((void *)bpf_list_push_front);
406300f19dcSKumar Kartikeya Dwivedi }
407300f19dcSKumar Kartikeya Dwivedi 
408300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
409300f19dcSKumar Kartikeya Dwivedi int double_push_back(void *ctx)
410300f19dcSKumar Kartikeya Dwivedi {
411300f19dcSKumar Kartikeya Dwivedi 	return list_double_add((void *)bpf_list_push_back);
412300f19dcSKumar Kartikeya Dwivedi }
413300f19dcSKumar Kartikeya Dwivedi 
414300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
415300f19dcSKumar Kartikeya Dwivedi int no_node_value_type(void *ctx)
416300f19dcSKumar Kartikeya Dwivedi {
417300f19dcSKumar Kartikeya Dwivedi 	void *p;
418300f19dcSKumar Kartikeya Dwivedi 
419300f19dcSKumar Kartikeya Dwivedi 	p = bpf_obj_new(struct { int data; });
420300f19dcSKumar Kartikeya Dwivedi 	if (!p)
421300f19dcSKumar Kartikeya Dwivedi 		return 0;
422300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_lock(&glock);
423300f19dcSKumar Kartikeya Dwivedi 	bpf_list_push_front(&ghead, p);
424300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_unlock(&glock);
425300f19dcSKumar Kartikeya Dwivedi 
426300f19dcSKumar Kartikeya Dwivedi 	return 0;
427300f19dcSKumar Kartikeya Dwivedi }
428300f19dcSKumar Kartikeya Dwivedi 
429300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
430300f19dcSKumar Kartikeya Dwivedi int incorrect_value_type(void *ctx)
431300f19dcSKumar Kartikeya Dwivedi {
432300f19dcSKumar Kartikeya Dwivedi 	struct bar *b;
433300f19dcSKumar Kartikeya Dwivedi 
434300f19dcSKumar Kartikeya Dwivedi 	b = bpf_obj_new(typeof(*b));
435300f19dcSKumar Kartikeya Dwivedi 	if (!b)
436300f19dcSKumar Kartikeya Dwivedi 		return 0;
437300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_lock(&glock);
438300f19dcSKumar Kartikeya Dwivedi 	bpf_list_push_front(&ghead, &b->node);
439300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_unlock(&glock);
440300f19dcSKumar Kartikeya Dwivedi 
441300f19dcSKumar Kartikeya Dwivedi 	return 0;
442300f19dcSKumar Kartikeya Dwivedi }
443300f19dcSKumar Kartikeya Dwivedi 
444300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
445300f19dcSKumar Kartikeya Dwivedi int incorrect_node_var_off(struct __sk_buff *ctx)
446300f19dcSKumar Kartikeya Dwivedi {
447300f19dcSKumar Kartikeya Dwivedi 	struct foo *f;
448300f19dcSKumar Kartikeya Dwivedi 
449300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
450300f19dcSKumar Kartikeya Dwivedi 	if (!f)
451300f19dcSKumar Kartikeya Dwivedi 		return 0;
452300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_lock(&glock);
453300f19dcSKumar Kartikeya Dwivedi 	bpf_list_push_front(&ghead, (void *)&f->node + ctx->protocol);
454300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_unlock(&glock);
455300f19dcSKumar Kartikeya Dwivedi 
456300f19dcSKumar Kartikeya Dwivedi 	return 0;
457300f19dcSKumar Kartikeya Dwivedi }
458300f19dcSKumar Kartikeya Dwivedi 
459300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
460300f19dcSKumar Kartikeya Dwivedi int incorrect_node_off1(void *ctx)
461300f19dcSKumar Kartikeya Dwivedi {
462300f19dcSKumar Kartikeya Dwivedi 	struct foo *f;
463300f19dcSKumar Kartikeya Dwivedi 
464300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
465300f19dcSKumar Kartikeya Dwivedi 	if (!f)
466300f19dcSKumar Kartikeya Dwivedi 		return 0;
467300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_lock(&glock);
468300f19dcSKumar Kartikeya Dwivedi 	bpf_list_push_front(&ghead, (void *)&f->node + 1);
469300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_unlock(&glock);
470300f19dcSKumar Kartikeya Dwivedi 
471300f19dcSKumar Kartikeya Dwivedi 	return 0;
472300f19dcSKumar Kartikeya Dwivedi }
473300f19dcSKumar Kartikeya Dwivedi 
474300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
475300f19dcSKumar Kartikeya Dwivedi int incorrect_node_off2(void *ctx)
476300f19dcSKumar Kartikeya Dwivedi {
477300f19dcSKumar Kartikeya Dwivedi 	struct foo *f;
478300f19dcSKumar Kartikeya Dwivedi 
479300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
480300f19dcSKumar Kartikeya Dwivedi 	if (!f)
481300f19dcSKumar Kartikeya Dwivedi 		return 0;
482300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_lock(&glock);
483300f19dcSKumar Kartikeya Dwivedi 	bpf_list_push_front(&ghead, &f->node2);
484300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_unlock(&glock);
485300f19dcSKumar Kartikeya Dwivedi 
486300f19dcSKumar Kartikeya Dwivedi 	return 0;
487300f19dcSKumar Kartikeya Dwivedi }
488300f19dcSKumar Kartikeya Dwivedi 
489300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
490300f19dcSKumar Kartikeya Dwivedi int no_head_type(void *ctx)
491300f19dcSKumar Kartikeya Dwivedi {
492300f19dcSKumar Kartikeya Dwivedi 	void *p;
493300f19dcSKumar Kartikeya Dwivedi 
494300f19dcSKumar Kartikeya Dwivedi 	p = bpf_obj_new(typeof(struct { int data; }));
495300f19dcSKumar Kartikeya Dwivedi 	if (!p)
496300f19dcSKumar Kartikeya Dwivedi 		return 0;
497300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_lock(&glock);
498300f19dcSKumar Kartikeya Dwivedi 	bpf_list_push_front(p, NULL);
499300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_lock(&glock);
500300f19dcSKumar Kartikeya Dwivedi 
501300f19dcSKumar Kartikeya Dwivedi 	return 0;
502300f19dcSKumar Kartikeya Dwivedi }
503300f19dcSKumar Kartikeya Dwivedi 
504300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
505300f19dcSKumar Kartikeya Dwivedi int incorrect_head_var_off1(struct __sk_buff *ctx)
506300f19dcSKumar Kartikeya Dwivedi {
507300f19dcSKumar Kartikeya Dwivedi 	struct foo *f;
508300f19dcSKumar Kartikeya Dwivedi 
509300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
510300f19dcSKumar Kartikeya Dwivedi 	if (!f)
511300f19dcSKumar Kartikeya Dwivedi 		return 0;
512300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_lock(&glock);
513300f19dcSKumar Kartikeya Dwivedi 	bpf_list_push_front((void *)&ghead + ctx->protocol, &f->node);
514300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_unlock(&glock);
515300f19dcSKumar Kartikeya Dwivedi 
516300f19dcSKumar Kartikeya Dwivedi 	return 0;
517300f19dcSKumar Kartikeya Dwivedi }
518300f19dcSKumar Kartikeya Dwivedi 
519300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
520300f19dcSKumar Kartikeya Dwivedi int incorrect_head_var_off2(struct __sk_buff *ctx)
521300f19dcSKumar Kartikeya Dwivedi {
522300f19dcSKumar Kartikeya Dwivedi 	struct foo *f;
523300f19dcSKumar Kartikeya Dwivedi 
524300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
525300f19dcSKumar Kartikeya Dwivedi 	if (!f)
526300f19dcSKumar Kartikeya Dwivedi 		return 0;
527300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_lock(&glock);
528300f19dcSKumar Kartikeya Dwivedi 	bpf_list_push_front((void *)&f->head + ctx->protocol, &f->node);
529300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_unlock(&glock);
530300f19dcSKumar Kartikeya Dwivedi 
531300f19dcSKumar Kartikeya Dwivedi 	return 0;
532300f19dcSKumar Kartikeya Dwivedi }
533300f19dcSKumar Kartikeya Dwivedi 
534300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
535300f19dcSKumar Kartikeya Dwivedi int incorrect_head_off1(void *ctx)
536300f19dcSKumar Kartikeya Dwivedi {
537300f19dcSKumar Kartikeya Dwivedi 	struct foo *f;
538300f19dcSKumar Kartikeya Dwivedi 	struct bar *b;
539300f19dcSKumar Kartikeya Dwivedi 
540300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
541300f19dcSKumar Kartikeya Dwivedi 	if (!f)
542300f19dcSKumar Kartikeya Dwivedi 		return 0;
543300f19dcSKumar Kartikeya Dwivedi 	b = bpf_obj_new(typeof(*b));
544300f19dcSKumar Kartikeya Dwivedi 	if (!b) {
545300f19dcSKumar Kartikeya Dwivedi 		bpf_obj_drop(f);
546300f19dcSKumar Kartikeya Dwivedi 		return 0;
547300f19dcSKumar Kartikeya Dwivedi 	}
548300f19dcSKumar Kartikeya Dwivedi 
549300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_lock(&f->lock);
550300f19dcSKumar Kartikeya Dwivedi 	bpf_list_push_front((void *)&f->head + 1, &b->node);
551300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_unlock(&f->lock);
552300f19dcSKumar Kartikeya Dwivedi 
553300f19dcSKumar Kartikeya Dwivedi 	return 0;
554300f19dcSKumar Kartikeya Dwivedi }
555300f19dcSKumar Kartikeya Dwivedi 
556300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
557300f19dcSKumar Kartikeya Dwivedi int incorrect_head_off2(void *ctx)
558300f19dcSKumar Kartikeya Dwivedi {
559300f19dcSKumar Kartikeya Dwivedi 	struct foo *f;
560300f19dcSKumar Kartikeya Dwivedi 	struct bar *b;
561300f19dcSKumar Kartikeya Dwivedi 
562300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
563300f19dcSKumar Kartikeya Dwivedi 	if (!f)
564300f19dcSKumar Kartikeya Dwivedi 		return 0;
565300f19dcSKumar Kartikeya Dwivedi 
566300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_lock(&glock);
567300f19dcSKumar Kartikeya Dwivedi 	bpf_list_push_front((void *)&ghead + 1, &f->node);
568300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_unlock(&glock);
569300f19dcSKumar Kartikeya Dwivedi 
570300f19dcSKumar Kartikeya Dwivedi 	return 0;
571300f19dcSKumar Kartikeya Dwivedi }
572300f19dcSKumar Kartikeya Dwivedi 
573300f19dcSKumar Kartikeya Dwivedi static __always_inline
574300f19dcSKumar Kartikeya Dwivedi int pop_ptr_off(void *(*op)(void *head))
575300f19dcSKumar Kartikeya Dwivedi {
576300f19dcSKumar Kartikeya Dwivedi 	struct {
577300f19dcSKumar Kartikeya Dwivedi 		struct bpf_list_head head __contains(foo, node2);
578300f19dcSKumar Kartikeya Dwivedi 		struct bpf_spin_lock lock;
579300f19dcSKumar Kartikeya Dwivedi 	} *p;
580300f19dcSKumar Kartikeya Dwivedi 	struct bpf_list_node *n;
581300f19dcSKumar Kartikeya Dwivedi 
582300f19dcSKumar Kartikeya Dwivedi 	p = bpf_obj_new(typeof(*p));
583300f19dcSKumar Kartikeya Dwivedi 	if (!p)
584300f19dcSKumar Kartikeya Dwivedi 		return 0;
585300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_lock(&p->lock);
586300f19dcSKumar Kartikeya Dwivedi 	n = op(&p->head);
587300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_unlock(&p->lock);
588300f19dcSKumar Kartikeya Dwivedi 
589300f19dcSKumar Kartikeya Dwivedi 	bpf_this_cpu_ptr(n);
590300f19dcSKumar Kartikeya Dwivedi 	return 0;
591300f19dcSKumar Kartikeya Dwivedi }
592300f19dcSKumar Kartikeya Dwivedi 
593300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
594300f19dcSKumar Kartikeya Dwivedi int pop_front_off(void *ctx)
595300f19dcSKumar Kartikeya Dwivedi {
596300f19dcSKumar Kartikeya Dwivedi 	return pop_ptr_off((void *)bpf_list_pop_front);
597300f19dcSKumar Kartikeya Dwivedi }
598300f19dcSKumar Kartikeya Dwivedi 
599300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
600300f19dcSKumar Kartikeya Dwivedi int pop_back_off(void *ctx)
601300f19dcSKumar Kartikeya Dwivedi {
602300f19dcSKumar Kartikeya Dwivedi 	return pop_ptr_off((void *)bpf_list_pop_back);
603300f19dcSKumar Kartikeya Dwivedi }
604300f19dcSKumar Kartikeya Dwivedi 
605300f19dcSKumar Kartikeya Dwivedi char _license[] SEC("license") = "GPL";
606