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, push_front, &f->head);
58300f19dcSKumar Kartikeya Dwivedi CHECK(kptr, push_back, &f->head);
59300f19dcSKumar Kartikeya Dwivedi CHECK(kptr, pop_front, &f->head);
60300f19dcSKumar Kartikeya Dwivedi CHECK(kptr, pop_back, &f->head);
61300f19dcSKumar Kartikeya Dwivedi 
62300f19dcSKumar Kartikeya Dwivedi CHECK(global, push_front, &ghead);
63300f19dcSKumar Kartikeya Dwivedi CHECK(global, push_back, &ghead);
64300f19dcSKumar Kartikeya Dwivedi CHECK(global, pop_front, &ghead);
65300f19dcSKumar Kartikeya Dwivedi CHECK(global, pop_back, &ghead);
66300f19dcSKumar Kartikeya Dwivedi 
67300f19dcSKumar Kartikeya Dwivedi CHECK(map, push_front, &v->head);
68300f19dcSKumar Kartikeya Dwivedi CHECK(map, push_back, &v->head);
69300f19dcSKumar Kartikeya Dwivedi CHECK(map, pop_front, &v->head);
70300f19dcSKumar Kartikeya Dwivedi CHECK(map, pop_back, &v->head);
71300f19dcSKumar Kartikeya Dwivedi 
72300f19dcSKumar Kartikeya Dwivedi CHECK(inner_map, push_front, &iv->head);
73300f19dcSKumar Kartikeya Dwivedi CHECK(inner_map, push_back, &iv->head);
74300f19dcSKumar Kartikeya Dwivedi CHECK(inner_map, pop_front, &iv->head);
75300f19dcSKumar Kartikeya Dwivedi CHECK(inner_map, pop_back, &iv->head);
76300f19dcSKumar Kartikeya Dwivedi 
77300f19dcSKumar Kartikeya Dwivedi #undef CHECK
78300f19dcSKumar Kartikeya Dwivedi 
79300f19dcSKumar Kartikeya Dwivedi #define CHECK(test, op, lexpr, hexpr)                       \
80300f19dcSKumar Kartikeya Dwivedi 	SEC("?tc")                                          \
81300f19dcSKumar Kartikeya Dwivedi 	int test##_incorrect_lock_##op(void *ctx)           \
82300f19dcSKumar Kartikeya Dwivedi 	{                                                   \
83300f19dcSKumar Kartikeya Dwivedi 		INIT;                                       \
84300f19dcSKumar Kartikeya Dwivedi 		void (*p)(void *) = (void *)&bpf_list_##op; \
85300f19dcSKumar Kartikeya Dwivedi 		bpf_spin_lock(lexpr);                       \
86300f19dcSKumar Kartikeya Dwivedi 		p(hexpr);                                   \
87300f19dcSKumar Kartikeya Dwivedi 		return 0;                                   \
88300f19dcSKumar Kartikeya Dwivedi 	}
89300f19dcSKumar Kartikeya Dwivedi 
90300f19dcSKumar Kartikeya Dwivedi #define CHECK_OP(op)                                           \
91300f19dcSKumar Kartikeya Dwivedi 	CHECK(kptr_kptr, op, &f1->lock, &f2->head);            \
92*0b2971a2SAlexei Starovoitov 	CHECK(kptr_global, op, &f1->lock, &ghead);             \
93300f19dcSKumar Kartikeya Dwivedi 	CHECK(kptr_map, op, &f1->lock, &v->head);              \
94300f19dcSKumar Kartikeya Dwivedi 	CHECK(kptr_inner_map, op, &f1->lock, &iv->head);       \
95300f19dcSKumar Kartikeya Dwivedi                                                                \
96*0b2971a2SAlexei Starovoitov 	CHECK(global_global, op, &glock2, &ghead);             \
97*0b2971a2SAlexei Starovoitov 	CHECK(global_kptr, op, &glock, &f1->head);             \
98*0b2971a2SAlexei Starovoitov 	CHECK(global_map, op, &glock, &v->head);               \
99*0b2971a2SAlexei Starovoitov 	CHECK(global_inner_map, op, &glock, &iv->head);        \
100*0b2971a2SAlexei Starovoitov                                                                \
101300f19dcSKumar Kartikeya Dwivedi 	CHECK(map_map, op, &v->lock, &v2->head);               \
102300f19dcSKumar Kartikeya Dwivedi 	CHECK(map_kptr, op, &v->lock, &f2->head);              \
103*0b2971a2SAlexei Starovoitov 	CHECK(map_global, op, &v->lock, &ghead);               \
104300f19dcSKumar Kartikeya Dwivedi 	CHECK(map_inner_map, op, &v->lock, &iv->head);         \
105300f19dcSKumar Kartikeya Dwivedi                                                                \
106300f19dcSKumar Kartikeya Dwivedi 	CHECK(inner_map_inner_map, op, &iv->lock, &iv2->head); \
107300f19dcSKumar Kartikeya Dwivedi 	CHECK(inner_map_kptr, op, &iv->lock, &f2->head);       \
108*0b2971a2SAlexei Starovoitov 	CHECK(inner_map_global, op, &iv->lock, &ghead);        \
109300f19dcSKumar Kartikeya Dwivedi 	CHECK(inner_map_map, op, &iv->lock, &v->head);
110300f19dcSKumar Kartikeya Dwivedi 
111300f19dcSKumar Kartikeya Dwivedi CHECK_OP(push_front);
112300f19dcSKumar Kartikeya Dwivedi CHECK_OP(push_back);
113300f19dcSKumar Kartikeya Dwivedi CHECK_OP(pop_front);
114300f19dcSKumar Kartikeya Dwivedi CHECK_OP(pop_back);
115300f19dcSKumar Kartikeya Dwivedi 
116300f19dcSKumar Kartikeya Dwivedi #undef CHECK
117300f19dcSKumar Kartikeya Dwivedi #undef CHECK_OP
118300f19dcSKumar Kartikeya Dwivedi #undef INIT
119300f19dcSKumar Kartikeya Dwivedi 
120300f19dcSKumar Kartikeya Dwivedi SEC("?kprobe/xyz")
121300f19dcSKumar Kartikeya Dwivedi int map_compat_kprobe(void *ctx)
122300f19dcSKumar Kartikeya Dwivedi {
123300f19dcSKumar Kartikeya Dwivedi 	bpf_list_push_front(&ghead, NULL);
124300f19dcSKumar Kartikeya Dwivedi 	return 0;
125300f19dcSKumar Kartikeya Dwivedi }
126300f19dcSKumar Kartikeya Dwivedi 
127300f19dcSKumar Kartikeya Dwivedi SEC("?kretprobe/xyz")
128300f19dcSKumar Kartikeya Dwivedi int map_compat_kretprobe(void *ctx)
129300f19dcSKumar Kartikeya Dwivedi {
130300f19dcSKumar Kartikeya Dwivedi 	bpf_list_push_front(&ghead, NULL);
131300f19dcSKumar Kartikeya Dwivedi 	return 0;
132300f19dcSKumar Kartikeya Dwivedi }
133300f19dcSKumar Kartikeya Dwivedi 
134300f19dcSKumar Kartikeya Dwivedi SEC("?tracepoint/xyz")
135300f19dcSKumar Kartikeya Dwivedi int map_compat_tp(void *ctx)
136300f19dcSKumar Kartikeya Dwivedi {
137300f19dcSKumar Kartikeya Dwivedi 	bpf_list_push_front(&ghead, NULL);
138300f19dcSKumar Kartikeya Dwivedi 	return 0;
139300f19dcSKumar Kartikeya Dwivedi }
140300f19dcSKumar Kartikeya Dwivedi 
141300f19dcSKumar Kartikeya Dwivedi SEC("?perf_event")
142300f19dcSKumar Kartikeya Dwivedi int map_compat_perf(void *ctx)
143300f19dcSKumar Kartikeya Dwivedi {
144300f19dcSKumar Kartikeya Dwivedi 	bpf_list_push_front(&ghead, NULL);
145300f19dcSKumar Kartikeya Dwivedi 	return 0;
146300f19dcSKumar Kartikeya Dwivedi }
147300f19dcSKumar Kartikeya Dwivedi 
148300f19dcSKumar Kartikeya Dwivedi SEC("?raw_tp/xyz")
149300f19dcSKumar Kartikeya Dwivedi int map_compat_raw_tp(void *ctx)
150300f19dcSKumar Kartikeya Dwivedi {
151300f19dcSKumar Kartikeya Dwivedi 	bpf_list_push_front(&ghead, NULL);
152300f19dcSKumar Kartikeya Dwivedi 	return 0;
153300f19dcSKumar Kartikeya Dwivedi }
154300f19dcSKumar Kartikeya Dwivedi 
155300f19dcSKumar Kartikeya Dwivedi SEC("?raw_tp.w/xyz")
156300f19dcSKumar Kartikeya Dwivedi int map_compat_raw_tp_w(void *ctx)
157300f19dcSKumar Kartikeya Dwivedi {
158300f19dcSKumar Kartikeya Dwivedi 	bpf_list_push_front(&ghead, NULL);
159300f19dcSKumar Kartikeya Dwivedi 	return 0;
160300f19dcSKumar Kartikeya Dwivedi }
161300f19dcSKumar Kartikeya Dwivedi 
162300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
163300f19dcSKumar Kartikeya Dwivedi int obj_type_id_oor(void *ctx)
164300f19dcSKumar Kartikeya Dwivedi {
165300f19dcSKumar Kartikeya Dwivedi 	bpf_obj_new_impl(~0UL, NULL);
166300f19dcSKumar Kartikeya Dwivedi 	return 0;
167300f19dcSKumar Kartikeya Dwivedi }
168300f19dcSKumar Kartikeya Dwivedi 
169300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
170300f19dcSKumar Kartikeya Dwivedi int obj_new_no_composite(void *ctx)
171300f19dcSKumar Kartikeya Dwivedi {
172300f19dcSKumar Kartikeya Dwivedi 	bpf_obj_new_impl(bpf_core_type_id_local(int), (void *)42);
173300f19dcSKumar Kartikeya Dwivedi 	return 0;
174300f19dcSKumar Kartikeya Dwivedi }
175300f19dcSKumar Kartikeya Dwivedi 
176300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
177300f19dcSKumar Kartikeya Dwivedi int obj_new_no_struct(void *ctx)
178300f19dcSKumar Kartikeya Dwivedi {
179300f19dcSKumar Kartikeya Dwivedi 
180300f19dcSKumar Kartikeya Dwivedi 	bpf_obj_new(union { int data; unsigned udata; });
181300f19dcSKumar Kartikeya Dwivedi 	return 0;
182300f19dcSKumar Kartikeya Dwivedi }
183300f19dcSKumar Kartikeya Dwivedi 
184300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
185300f19dcSKumar Kartikeya Dwivedi int obj_drop_non_zero_off(void *ctx)
186300f19dcSKumar Kartikeya Dwivedi {
187300f19dcSKumar Kartikeya Dwivedi 	void *f;
188300f19dcSKumar Kartikeya Dwivedi 
189300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(struct foo);
190300f19dcSKumar Kartikeya Dwivedi 	if (!f)
191300f19dcSKumar Kartikeya Dwivedi 		return 0;
192300f19dcSKumar Kartikeya Dwivedi 	bpf_obj_drop(f+1);
193300f19dcSKumar Kartikeya Dwivedi 	return 0;
194300f19dcSKumar Kartikeya Dwivedi }
195300f19dcSKumar Kartikeya Dwivedi 
196300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
197300f19dcSKumar Kartikeya Dwivedi int new_null_ret(void *ctx)
198300f19dcSKumar Kartikeya Dwivedi {
199300f19dcSKumar Kartikeya Dwivedi 	return bpf_obj_new(struct foo)->data;
200300f19dcSKumar Kartikeya Dwivedi }
201300f19dcSKumar Kartikeya Dwivedi 
202300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
203300f19dcSKumar Kartikeya Dwivedi int obj_new_acq(void *ctx)
204300f19dcSKumar Kartikeya Dwivedi {
205300f19dcSKumar Kartikeya Dwivedi 	bpf_obj_new(struct foo);
206300f19dcSKumar Kartikeya Dwivedi 	return 0;
207300f19dcSKumar Kartikeya Dwivedi }
208300f19dcSKumar Kartikeya Dwivedi 
209300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
210300f19dcSKumar Kartikeya Dwivedi int use_after_drop(void *ctx)
211300f19dcSKumar Kartikeya Dwivedi {
212300f19dcSKumar Kartikeya Dwivedi 	struct foo *f;
213300f19dcSKumar Kartikeya Dwivedi 
214300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
215300f19dcSKumar Kartikeya Dwivedi 	if (!f)
216300f19dcSKumar Kartikeya Dwivedi 		return 0;
217300f19dcSKumar Kartikeya Dwivedi 	bpf_obj_drop(f);
218300f19dcSKumar Kartikeya Dwivedi 	return f->data;
219300f19dcSKumar Kartikeya Dwivedi }
220300f19dcSKumar Kartikeya Dwivedi 
221300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
222300f19dcSKumar Kartikeya Dwivedi int ptr_walk_scalar(void *ctx)
223300f19dcSKumar Kartikeya Dwivedi {
224300f19dcSKumar Kartikeya Dwivedi 	struct test1 {
225300f19dcSKumar Kartikeya Dwivedi 		struct test2 {
226300f19dcSKumar Kartikeya Dwivedi 			struct test2 *next;
227300f19dcSKumar Kartikeya Dwivedi 		} *ptr;
228300f19dcSKumar Kartikeya Dwivedi 	} *p;
229300f19dcSKumar Kartikeya Dwivedi 
230300f19dcSKumar Kartikeya Dwivedi 	p = bpf_obj_new(typeof(*p));
231300f19dcSKumar Kartikeya Dwivedi 	if (!p)
232300f19dcSKumar Kartikeya Dwivedi 		return 0;
233300f19dcSKumar Kartikeya Dwivedi 	bpf_this_cpu_ptr(p->ptr);
234300f19dcSKumar Kartikeya Dwivedi 	return 0;
235300f19dcSKumar Kartikeya Dwivedi }
236300f19dcSKumar Kartikeya Dwivedi 
237300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
238300f19dcSKumar Kartikeya Dwivedi int direct_read_lock(void *ctx)
239300f19dcSKumar Kartikeya Dwivedi {
240300f19dcSKumar Kartikeya Dwivedi 	struct foo *f;
241300f19dcSKumar Kartikeya Dwivedi 
242300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
243300f19dcSKumar Kartikeya Dwivedi 	if (!f)
244300f19dcSKumar Kartikeya Dwivedi 		return 0;
245300f19dcSKumar Kartikeya Dwivedi 	return *(int *)&f->lock;
246300f19dcSKumar Kartikeya Dwivedi }
247300f19dcSKumar Kartikeya Dwivedi 
248300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
249300f19dcSKumar Kartikeya Dwivedi int direct_write_lock(void *ctx)
250300f19dcSKumar Kartikeya Dwivedi {
251300f19dcSKumar Kartikeya Dwivedi 	struct foo *f;
252300f19dcSKumar Kartikeya Dwivedi 
253300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
254300f19dcSKumar Kartikeya Dwivedi 	if (!f)
255300f19dcSKumar Kartikeya Dwivedi 		return 0;
256300f19dcSKumar Kartikeya Dwivedi 	*(int *)&f->lock = 0;
257300f19dcSKumar Kartikeya Dwivedi 	return 0;
258300f19dcSKumar Kartikeya Dwivedi }
259300f19dcSKumar Kartikeya Dwivedi 
260300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
261300f19dcSKumar Kartikeya Dwivedi int direct_read_head(void *ctx)
262300f19dcSKumar Kartikeya Dwivedi {
263300f19dcSKumar Kartikeya Dwivedi 	struct foo *f;
264300f19dcSKumar Kartikeya Dwivedi 
265300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
266300f19dcSKumar Kartikeya Dwivedi 	if (!f)
267300f19dcSKumar Kartikeya Dwivedi 		return 0;
268300f19dcSKumar Kartikeya Dwivedi 	return *(int *)&f->head;
269300f19dcSKumar Kartikeya Dwivedi }
270300f19dcSKumar Kartikeya Dwivedi 
271300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
272300f19dcSKumar Kartikeya Dwivedi int direct_write_head(void *ctx)
273300f19dcSKumar Kartikeya Dwivedi {
274300f19dcSKumar Kartikeya Dwivedi 	struct foo *f;
275300f19dcSKumar Kartikeya Dwivedi 
276300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
277300f19dcSKumar Kartikeya Dwivedi 	if (!f)
278300f19dcSKumar Kartikeya Dwivedi 		return 0;
279300f19dcSKumar Kartikeya Dwivedi 	*(int *)&f->head = 0;
280300f19dcSKumar Kartikeya Dwivedi 	return 0;
281300f19dcSKumar Kartikeya Dwivedi }
282300f19dcSKumar Kartikeya Dwivedi 
283300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
284300f19dcSKumar Kartikeya Dwivedi int direct_read_node(void *ctx)
285300f19dcSKumar Kartikeya Dwivedi {
286300f19dcSKumar Kartikeya Dwivedi 	struct foo *f;
287300f19dcSKumar Kartikeya Dwivedi 
288300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
289300f19dcSKumar Kartikeya Dwivedi 	if (!f)
290300f19dcSKumar Kartikeya Dwivedi 		return 0;
291300f19dcSKumar Kartikeya Dwivedi 	return *(int *)&f->node;
292300f19dcSKumar Kartikeya Dwivedi }
293300f19dcSKumar Kartikeya Dwivedi 
294300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
295300f19dcSKumar Kartikeya Dwivedi int direct_write_node(void *ctx)
296300f19dcSKumar Kartikeya Dwivedi {
297300f19dcSKumar Kartikeya Dwivedi 	struct foo *f;
298300f19dcSKumar Kartikeya Dwivedi 
299300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
300300f19dcSKumar Kartikeya Dwivedi 	if (!f)
301300f19dcSKumar Kartikeya Dwivedi 		return 0;
302300f19dcSKumar Kartikeya Dwivedi 	*(int *)&f->node = 0;
303300f19dcSKumar Kartikeya Dwivedi 	return 0;
304300f19dcSKumar Kartikeya Dwivedi }
305300f19dcSKumar Kartikeya Dwivedi 
306300f19dcSKumar Kartikeya Dwivedi static __always_inline
307300f19dcSKumar Kartikeya Dwivedi int write_after_op(void (*push_op)(void *head, void *node))
308300f19dcSKumar Kartikeya Dwivedi {
309300f19dcSKumar Kartikeya Dwivedi 	struct foo *f;
310300f19dcSKumar Kartikeya Dwivedi 
311300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
312300f19dcSKumar Kartikeya Dwivedi 	if (!f)
313300f19dcSKumar Kartikeya Dwivedi 		return 0;
314300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_lock(&glock);
315300f19dcSKumar Kartikeya Dwivedi 	push_op(&ghead, &f->node);
316300f19dcSKumar Kartikeya Dwivedi 	f->data = 42;
317300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_unlock(&glock);
318300f19dcSKumar Kartikeya Dwivedi 
319300f19dcSKumar Kartikeya Dwivedi 	return 0;
320300f19dcSKumar Kartikeya Dwivedi }
321300f19dcSKumar Kartikeya Dwivedi 
322300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
323300f19dcSKumar Kartikeya Dwivedi int write_after_push_front(void *ctx)
324300f19dcSKumar Kartikeya Dwivedi {
325300f19dcSKumar Kartikeya Dwivedi 	return write_after_op((void *)bpf_list_push_front);
326300f19dcSKumar Kartikeya Dwivedi }
327300f19dcSKumar Kartikeya Dwivedi 
328300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
329300f19dcSKumar Kartikeya Dwivedi int write_after_push_back(void *ctx)
330300f19dcSKumar Kartikeya Dwivedi {
331300f19dcSKumar Kartikeya Dwivedi 	return write_after_op((void *)bpf_list_push_back);
332300f19dcSKumar Kartikeya Dwivedi }
333300f19dcSKumar Kartikeya Dwivedi 
334300f19dcSKumar Kartikeya Dwivedi static __always_inline
335300f19dcSKumar Kartikeya Dwivedi int use_after_unlock(void (*op)(void *head, void *node))
336300f19dcSKumar Kartikeya Dwivedi {
337300f19dcSKumar Kartikeya Dwivedi 	struct foo *f;
338300f19dcSKumar Kartikeya Dwivedi 
339300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
340300f19dcSKumar Kartikeya Dwivedi 	if (!f)
341300f19dcSKumar Kartikeya Dwivedi 		return 0;
342300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_lock(&glock);
343300f19dcSKumar Kartikeya Dwivedi 	f->data = 42;
344300f19dcSKumar Kartikeya Dwivedi 	op(&ghead, &f->node);
345300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_unlock(&glock);
346300f19dcSKumar Kartikeya Dwivedi 
347300f19dcSKumar Kartikeya Dwivedi 	return f->data;
348300f19dcSKumar Kartikeya Dwivedi }
349300f19dcSKumar Kartikeya Dwivedi 
350300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
351300f19dcSKumar Kartikeya Dwivedi int use_after_unlock_push_front(void *ctx)
352300f19dcSKumar Kartikeya Dwivedi {
353300f19dcSKumar Kartikeya Dwivedi 	return use_after_unlock((void *)bpf_list_push_front);
354300f19dcSKumar Kartikeya Dwivedi }
355300f19dcSKumar Kartikeya Dwivedi 
356300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
357300f19dcSKumar Kartikeya Dwivedi int use_after_unlock_push_back(void *ctx)
358300f19dcSKumar Kartikeya Dwivedi {
359300f19dcSKumar Kartikeya Dwivedi 	return use_after_unlock((void *)bpf_list_push_back);
360300f19dcSKumar Kartikeya Dwivedi }
361300f19dcSKumar Kartikeya Dwivedi 
362300f19dcSKumar Kartikeya Dwivedi static __always_inline
363300f19dcSKumar Kartikeya Dwivedi int list_double_add(void (*op)(void *head, void *node))
364300f19dcSKumar Kartikeya Dwivedi {
365300f19dcSKumar Kartikeya Dwivedi 	struct foo *f;
366300f19dcSKumar Kartikeya Dwivedi 
367300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
368300f19dcSKumar Kartikeya Dwivedi 	if (!f)
369300f19dcSKumar Kartikeya Dwivedi 		return 0;
370300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_lock(&glock);
371300f19dcSKumar Kartikeya Dwivedi 	op(&ghead, &f->node);
372300f19dcSKumar Kartikeya Dwivedi 	op(&ghead, &f->node);
373300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_unlock(&glock);
374300f19dcSKumar Kartikeya Dwivedi 
375300f19dcSKumar Kartikeya Dwivedi 	return 0;
376300f19dcSKumar Kartikeya Dwivedi }
377300f19dcSKumar Kartikeya Dwivedi 
378300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
379300f19dcSKumar Kartikeya Dwivedi int double_push_front(void *ctx)
380300f19dcSKumar Kartikeya Dwivedi {
381300f19dcSKumar Kartikeya Dwivedi 	return list_double_add((void *)bpf_list_push_front);
382300f19dcSKumar Kartikeya Dwivedi }
383300f19dcSKumar Kartikeya Dwivedi 
384300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
385300f19dcSKumar Kartikeya Dwivedi int double_push_back(void *ctx)
386300f19dcSKumar Kartikeya Dwivedi {
387300f19dcSKumar Kartikeya Dwivedi 	return list_double_add((void *)bpf_list_push_back);
388300f19dcSKumar Kartikeya Dwivedi }
389300f19dcSKumar Kartikeya Dwivedi 
390300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
391300f19dcSKumar Kartikeya Dwivedi int no_node_value_type(void *ctx)
392300f19dcSKumar Kartikeya Dwivedi {
393300f19dcSKumar Kartikeya Dwivedi 	void *p;
394300f19dcSKumar Kartikeya Dwivedi 
395300f19dcSKumar Kartikeya Dwivedi 	p = bpf_obj_new(struct { int data; });
396300f19dcSKumar Kartikeya Dwivedi 	if (!p)
397300f19dcSKumar Kartikeya Dwivedi 		return 0;
398300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_lock(&glock);
399300f19dcSKumar Kartikeya Dwivedi 	bpf_list_push_front(&ghead, p);
400300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_unlock(&glock);
401300f19dcSKumar Kartikeya Dwivedi 
402300f19dcSKumar Kartikeya Dwivedi 	return 0;
403300f19dcSKumar Kartikeya Dwivedi }
404300f19dcSKumar Kartikeya Dwivedi 
405300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
406300f19dcSKumar Kartikeya Dwivedi int incorrect_value_type(void *ctx)
407300f19dcSKumar Kartikeya Dwivedi {
408300f19dcSKumar Kartikeya Dwivedi 	struct bar *b;
409300f19dcSKumar Kartikeya Dwivedi 
410300f19dcSKumar Kartikeya Dwivedi 	b = bpf_obj_new(typeof(*b));
411300f19dcSKumar Kartikeya Dwivedi 	if (!b)
412300f19dcSKumar Kartikeya Dwivedi 		return 0;
413300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_lock(&glock);
414300f19dcSKumar Kartikeya Dwivedi 	bpf_list_push_front(&ghead, &b->node);
415300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_unlock(&glock);
416300f19dcSKumar Kartikeya Dwivedi 
417300f19dcSKumar Kartikeya Dwivedi 	return 0;
418300f19dcSKumar Kartikeya Dwivedi }
419300f19dcSKumar Kartikeya Dwivedi 
420300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
421300f19dcSKumar Kartikeya Dwivedi int incorrect_node_var_off(struct __sk_buff *ctx)
422300f19dcSKumar Kartikeya Dwivedi {
423300f19dcSKumar Kartikeya Dwivedi 	struct foo *f;
424300f19dcSKumar Kartikeya Dwivedi 
425300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
426300f19dcSKumar Kartikeya Dwivedi 	if (!f)
427300f19dcSKumar Kartikeya Dwivedi 		return 0;
428300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_lock(&glock);
429300f19dcSKumar Kartikeya Dwivedi 	bpf_list_push_front(&ghead, (void *)&f->node + ctx->protocol);
430300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_unlock(&glock);
431300f19dcSKumar Kartikeya Dwivedi 
432300f19dcSKumar Kartikeya Dwivedi 	return 0;
433300f19dcSKumar Kartikeya Dwivedi }
434300f19dcSKumar Kartikeya Dwivedi 
435300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
436300f19dcSKumar Kartikeya Dwivedi int incorrect_node_off1(void *ctx)
437300f19dcSKumar Kartikeya Dwivedi {
438300f19dcSKumar Kartikeya Dwivedi 	struct foo *f;
439300f19dcSKumar Kartikeya Dwivedi 
440300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
441300f19dcSKumar Kartikeya Dwivedi 	if (!f)
442300f19dcSKumar Kartikeya Dwivedi 		return 0;
443300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_lock(&glock);
444300f19dcSKumar Kartikeya Dwivedi 	bpf_list_push_front(&ghead, (void *)&f->node + 1);
445300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_unlock(&glock);
446300f19dcSKumar Kartikeya Dwivedi 
447300f19dcSKumar Kartikeya Dwivedi 	return 0;
448300f19dcSKumar Kartikeya Dwivedi }
449300f19dcSKumar Kartikeya Dwivedi 
450300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
451300f19dcSKumar Kartikeya Dwivedi int incorrect_node_off2(void *ctx)
452300f19dcSKumar Kartikeya Dwivedi {
453300f19dcSKumar Kartikeya Dwivedi 	struct foo *f;
454300f19dcSKumar Kartikeya Dwivedi 
455300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
456300f19dcSKumar Kartikeya Dwivedi 	if (!f)
457300f19dcSKumar Kartikeya Dwivedi 		return 0;
458300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_lock(&glock);
459300f19dcSKumar Kartikeya Dwivedi 	bpf_list_push_front(&ghead, &f->node2);
460300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_unlock(&glock);
461300f19dcSKumar Kartikeya Dwivedi 
462300f19dcSKumar Kartikeya Dwivedi 	return 0;
463300f19dcSKumar Kartikeya Dwivedi }
464300f19dcSKumar Kartikeya Dwivedi 
465300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
466300f19dcSKumar Kartikeya Dwivedi int no_head_type(void *ctx)
467300f19dcSKumar Kartikeya Dwivedi {
468300f19dcSKumar Kartikeya Dwivedi 	void *p;
469300f19dcSKumar Kartikeya Dwivedi 
470300f19dcSKumar Kartikeya Dwivedi 	p = bpf_obj_new(typeof(struct { int data; }));
471300f19dcSKumar Kartikeya Dwivedi 	if (!p)
472300f19dcSKumar Kartikeya Dwivedi 		return 0;
473300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_lock(&glock);
474300f19dcSKumar Kartikeya Dwivedi 	bpf_list_push_front(p, NULL);
475300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_lock(&glock);
476300f19dcSKumar Kartikeya Dwivedi 
477300f19dcSKumar Kartikeya Dwivedi 	return 0;
478300f19dcSKumar Kartikeya Dwivedi }
479300f19dcSKumar Kartikeya Dwivedi 
480300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
481300f19dcSKumar Kartikeya Dwivedi int incorrect_head_var_off1(struct __sk_buff *ctx)
482300f19dcSKumar Kartikeya Dwivedi {
483300f19dcSKumar Kartikeya Dwivedi 	struct foo *f;
484300f19dcSKumar Kartikeya Dwivedi 
485300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
486300f19dcSKumar Kartikeya Dwivedi 	if (!f)
487300f19dcSKumar Kartikeya Dwivedi 		return 0;
488300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_lock(&glock);
489300f19dcSKumar Kartikeya Dwivedi 	bpf_list_push_front((void *)&ghead + ctx->protocol, &f->node);
490300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_unlock(&glock);
491300f19dcSKumar Kartikeya Dwivedi 
492300f19dcSKumar Kartikeya Dwivedi 	return 0;
493300f19dcSKumar Kartikeya Dwivedi }
494300f19dcSKumar Kartikeya Dwivedi 
495300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
496300f19dcSKumar Kartikeya Dwivedi int incorrect_head_var_off2(struct __sk_buff *ctx)
497300f19dcSKumar Kartikeya Dwivedi {
498300f19dcSKumar Kartikeya Dwivedi 	struct foo *f;
499300f19dcSKumar Kartikeya Dwivedi 
500300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
501300f19dcSKumar Kartikeya Dwivedi 	if (!f)
502300f19dcSKumar Kartikeya Dwivedi 		return 0;
503300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_lock(&glock);
504300f19dcSKumar Kartikeya Dwivedi 	bpf_list_push_front((void *)&f->head + ctx->protocol, &f->node);
505300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_unlock(&glock);
506300f19dcSKumar Kartikeya Dwivedi 
507300f19dcSKumar Kartikeya Dwivedi 	return 0;
508300f19dcSKumar Kartikeya Dwivedi }
509300f19dcSKumar Kartikeya Dwivedi 
510300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
511300f19dcSKumar Kartikeya Dwivedi int incorrect_head_off1(void *ctx)
512300f19dcSKumar Kartikeya Dwivedi {
513300f19dcSKumar Kartikeya Dwivedi 	struct foo *f;
514300f19dcSKumar Kartikeya Dwivedi 	struct bar *b;
515300f19dcSKumar Kartikeya Dwivedi 
516300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
517300f19dcSKumar Kartikeya Dwivedi 	if (!f)
518300f19dcSKumar Kartikeya Dwivedi 		return 0;
519300f19dcSKumar Kartikeya Dwivedi 	b = bpf_obj_new(typeof(*b));
520300f19dcSKumar Kartikeya Dwivedi 	if (!b) {
521300f19dcSKumar Kartikeya Dwivedi 		bpf_obj_drop(f);
522300f19dcSKumar Kartikeya Dwivedi 		return 0;
523300f19dcSKumar Kartikeya Dwivedi 	}
524300f19dcSKumar Kartikeya Dwivedi 
525300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_lock(&f->lock);
526300f19dcSKumar Kartikeya Dwivedi 	bpf_list_push_front((void *)&f->head + 1, &b->node);
527300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_unlock(&f->lock);
528300f19dcSKumar Kartikeya Dwivedi 
529300f19dcSKumar Kartikeya Dwivedi 	return 0;
530300f19dcSKumar Kartikeya Dwivedi }
531300f19dcSKumar Kartikeya Dwivedi 
532300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
533300f19dcSKumar Kartikeya Dwivedi int incorrect_head_off2(void *ctx)
534300f19dcSKumar Kartikeya Dwivedi {
535300f19dcSKumar Kartikeya Dwivedi 	struct foo *f;
536300f19dcSKumar Kartikeya Dwivedi 	struct bar *b;
537300f19dcSKumar Kartikeya Dwivedi 
538300f19dcSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
539300f19dcSKumar Kartikeya Dwivedi 	if (!f)
540300f19dcSKumar Kartikeya Dwivedi 		return 0;
541300f19dcSKumar Kartikeya Dwivedi 
542300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_lock(&glock);
543300f19dcSKumar Kartikeya Dwivedi 	bpf_list_push_front((void *)&ghead + 1, &f->node);
544300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_unlock(&glock);
545300f19dcSKumar Kartikeya Dwivedi 
546300f19dcSKumar Kartikeya Dwivedi 	return 0;
547300f19dcSKumar Kartikeya Dwivedi }
548300f19dcSKumar Kartikeya Dwivedi 
549300f19dcSKumar Kartikeya Dwivedi static __always_inline
550300f19dcSKumar Kartikeya Dwivedi int pop_ptr_off(void *(*op)(void *head))
551300f19dcSKumar Kartikeya Dwivedi {
552300f19dcSKumar Kartikeya Dwivedi 	struct {
553300f19dcSKumar Kartikeya Dwivedi 		struct bpf_list_head head __contains(foo, node2);
554300f19dcSKumar Kartikeya Dwivedi 		struct bpf_spin_lock lock;
555300f19dcSKumar Kartikeya Dwivedi 	} *p;
556300f19dcSKumar Kartikeya Dwivedi 	struct bpf_list_node *n;
557300f19dcSKumar Kartikeya Dwivedi 
558300f19dcSKumar Kartikeya Dwivedi 	p = bpf_obj_new(typeof(*p));
559300f19dcSKumar Kartikeya Dwivedi 	if (!p)
560300f19dcSKumar Kartikeya Dwivedi 		return 0;
561300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_lock(&p->lock);
562300f19dcSKumar Kartikeya Dwivedi 	n = op(&p->head);
563300f19dcSKumar Kartikeya Dwivedi 	bpf_spin_unlock(&p->lock);
564300f19dcSKumar Kartikeya Dwivedi 
565300f19dcSKumar Kartikeya Dwivedi 	bpf_this_cpu_ptr(n);
566300f19dcSKumar Kartikeya Dwivedi 	return 0;
567300f19dcSKumar Kartikeya Dwivedi }
568300f19dcSKumar Kartikeya Dwivedi 
569300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
570300f19dcSKumar Kartikeya Dwivedi int pop_front_off(void *ctx)
571300f19dcSKumar Kartikeya Dwivedi {
572300f19dcSKumar Kartikeya Dwivedi 	return pop_ptr_off((void *)bpf_list_pop_front);
573300f19dcSKumar Kartikeya Dwivedi }
574300f19dcSKumar Kartikeya Dwivedi 
575300f19dcSKumar Kartikeya Dwivedi SEC("?tc")
576300f19dcSKumar Kartikeya Dwivedi int pop_back_off(void *ctx)
577300f19dcSKumar Kartikeya Dwivedi {
578300f19dcSKumar Kartikeya Dwivedi 	return pop_ptr_off((void *)bpf_list_pop_back);
579300f19dcSKumar Kartikeya Dwivedi }
580300f19dcSKumar Kartikeya Dwivedi 
581300f19dcSKumar Kartikeya Dwivedi char _license[] SEC("license") = "GPL";
582