1// SPDX-License-Identifier: GPL-2.0
2#include <vmlinux.h>
3#include <bpf/bpf_tracing.h>
4#include <bpf/bpf_helpers.h>
5#include <bpf/bpf_core_read.h>
6
7struct map_value {
8	char buf[8];
9	struct prog_test_ref_kfunc __kptr *unref_ptr;
10	struct prog_test_ref_kfunc __kptr_ref *ref_ptr;
11	struct prog_test_member __kptr_ref *ref_memb_ptr;
12};
13
14struct array_map {
15	__uint(type, BPF_MAP_TYPE_ARRAY);
16	__type(key, int);
17	__type(value, struct map_value);
18	__uint(max_entries, 1);
19} array_map SEC(".maps");
20
21extern struct prog_test_ref_kfunc *bpf_kfunc_call_test_acquire(unsigned long *sp) __ksym;
22extern struct prog_test_ref_kfunc *
23bpf_kfunc_call_test_kptr_get(struct prog_test_ref_kfunc **p, int a, int b) __ksym;
24
25SEC("?tc")
26int size_not_bpf_dw(struct __sk_buff *ctx)
27{
28	struct map_value *v;
29	int key = 0;
30
31	v = bpf_map_lookup_elem(&array_map, &key);
32	if (!v)
33		return 0;
34
35	*(u32 *)&v->unref_ptr = 0;
36	return 0;
37}
38
39SEC("?tc")
40int non_const_var_off(struct __sk_buff *ctx)
41{
42	struct map_value *v;
43	int key = 0, id;
44
45	v = bpf_map_lookup_elem(&array_map, &key);
46	if (!v)
47		return 0;
48
49	id = ctx->protocol;
50	if (id < 4 || id > 12)
51		return 0;
52	*(u64 *)((void *)v + id) = 0;
53
54	return 0;
55}
56
57SEC("?tc")
58int non_const_var_off_kptr_xchg(struct __sk_buff *ctx)
59{
60	struct map_value *v;
61	int key = 0, id;
62
63	v = bpf_map_lookup_elem(&array_map, &key);
64	if (!v)
65		return 0;
66
67	id = ctx->protocol;
68	if (id < 4 || id > 12)
69		return 0;
70	bpf_kptr_xchg((void *)v + id, NULL);
71
72	return 0;
73}
74
75SEC("?tc")
76int misaligned_access_write(struct __sk_buff *ctx)
77{
78	struct map_value *v;
79	int key = 0;
80
81	v = bpf_map_lookup_elem(&array_map, &key);
82	if (!v)
83		return 0;
84
85	*(void **)((void *)v + 7) = NULL;
86
87	return 0;
88}
89
90SEC("?tc")
91int misaligned_access_read(struct __sk_buff *ctx)
92{
93	struct map_value *v;
94	int key = 0;
95
96	v = bpf_map_lookup_elem(&array_map, &key);
97	if (!v)
98		return 0;
99
100	return *(u64 *)((void *)v + 1);
101}
102
103SEC("?tc")
104int reject_var_off_store(struct __sk_buff *ctx)
105{
106	struct prog_test_ref_kfunc *unref_ptr;
107	struct map_value *v;
108	int key = 0, id;
109
110	v = bpf_map_lookup_elem(&array_map, &key);
111	if (!v)
112		return 0;
113
114	unref_ptr = v->unref_ptr;
115	if (!unref_ptr)
116		return 0;
117	id = ctx->protocol;
118	if (id < 4 || id > 12)
119		return 0;
120	unref_ptr += id;
121	v->unref_ptr = unref_ptr;
122
123	return 0;
124}
125
126SEC("?tc")
127int reject_bad_type_match(struct __sk_buff *ctx)
128{
129	struct prog_test_ref_kfunc *unref_ptr;
130	struct map_value *v;
131	int key = 0;
132
133	v = bpf_map_lookup_elem(&array_map, &key);
134	if (!v)
135		return 0;
136
137	unref_ptr = v->unref_ptr;
138	if (!unref_ptr)
139		return 0;
140	unref_ptr = (void *)unref_ptr + 4;
141	v->unref_ptr = unref_ptr;
142
143	return 0;
144}
145
146SEC("?tc")
147int marked_as_untrusted_or_null(struct __sk_buff *ctx)
148{
149	struct map_value *v;
150	int key = 0;
151
152	v = bpf_map_lookup_elem(&array_map, &key);
153	if (!v)
154		return 0;
155
156	bpf_this_cpu_ptr(v->unref_ptr);
157	return 0;
158}
159
160SEC("?tc")
161int correct_btf_id_check_size(struct __sk_buff *ctx)
162{
163	struct prog_test_ref_kfunc *p;
164	struct map_value *v;
165	int key = 0;
166
167	v = bpf_map_lookup_elem(&array_map, &key);
168	if (!v)
169		return 0;
170
171	p = v->unref_ptr;
172	if (!p)
173		return 0;
174	return *(int *)((void *)p + bpf_core_type_size(struct prog_test_ref_kfunc));
175}
176
177SEC("?tc")
178int inherit_untrusted_on_walk(struct __sk_buff *ctx)
179{
180	struct prog_test_ref_kfunc *unref_ptr;
181	struct map_value *v;
182	int key = 0;
183
184	v = bpf_map_lookup_elem(&array_map, &key);
185	if (!v)
186		return 0;
187
188	unref_ptr = v->unref_ptr;
189	if (!unref_ptr)
190		return 0;
191	unref_ptr = unref_ptr->next;
192	bpf_this_cpu_ptr(unref_ptr);
193	return 0;
194}
195
196SEC("?tc")
197int reject_kptr_xchg_on_unref(struct __sk_buff *ctx)
198{
199	struct map_value *v;
200	int key = 0;
201
202	v = bpf_map_lookup_elem(&array_map, &key);
203	if (!v)
204		return 0;
205
206	bpf_kptr_xchg(&v->unref_ptr, NULL);
207	return 0;
208}
209
210SEC("?tc")
211int reject_kptr_get_no_map_val(struct __sk_buff *ctx)
212{
213	bpf_kfunc_call_test_kptr_get((void *)&ctx, 0, 0);
214	return 0;
215}
216
217SEC("?tc")
218int reject_kptr_get_no_null_map_val(struct __sk_buff *ctx)
219{
220	bpf_kfunc_call_test_kptr_get(bpf_map_lookup_elem(&array_map, &(int){0}), 0, 0);
221	return 0;
222}
223
224SEC("?tc")
225int reject_kptr_get_no_kptr(struct __sk_buff *ctx)
226{
227	struct map_value *v;
228	int key = 0;
229
230	v = bpf_map_lookup_elem(&array_map, &key);
231	if (!v)
232		return 0;
233
234	bpf_kfunc_call_test_kptr_get((void *)v, 0, 0);
235	return 0;
236}
237
238SEC("?tc")
239int reject_kptr_get_on_unref(struct __sk_buff *ctx)
240{
241	struct map_value *v;
242	int key = 0;
243
244	v = bpf_map_lookup_elem(&array_map, &key);
245	if (!v)
246		return 0;
247
248	bpf_kfunc_call_test_kptr_get(&v->unref_ptr, 0, 0);
249	return 0;
250}
251
252SEC("?tc")
253int reject_kptr_get_bad_type_match(struct __sk_buff *ctx)
254{
255	struct map_value *v;
256	int key = 0;
257
258	v = bpf_map_lookup_elem(&array_map, &key);
259	if (!v)
260		return 0;
261
262	bpf_kfunc_call_test_kptr_get((void *)&v->ref_memb_ptr, 0, 0);
263	return 0;
264}
265
266SEC("?tc")
267int mark_ref_as_untrusted_or_null(struct __sk_buff *ctx)
268{
269	struct map_value *v;
270	int key = 0;
271
272	v = bpf_map_lookup_elem(&array_map, &key);
273	if (!v)
274		return 0;
275
276	bpf_this_cpu_ptr(v->ref_ptr);
277	return 0;
278}
279
280SEC("?tc")
281int reject_untrusted_store_to_ref(struct __sk_buff *ctx)
282{
283	struct prog_test_ref_kfunc *p;
284	struct map_value *v;
285	int key = 0;
286
287	v = bpf_map_lookup_elem(&array_map, &key);
288	if (!v)
289		return 0;
290
291	p = v->ref_ptr;
292	if (!p)
293		return 0;
294	/* Checkmate, clang */
295	*(struct prog_test_ref_kfunc * volatile *)&v->ref_ptr = p;
296	return 0;
297}
298
299SEC("?tc")
300int reject_untrusted_xchg(struct __sk_buff *ctx)
301{
302	struct prog_test_ref_kfunc *p;
303	struct map_value *v;
304	int key = 0;
305
306	v = bpf_map_lookup_elem(&array_map, &key);
307	if (!v)
308		return 0;
309
310	p = v->ref_ptr;
311	if (!p)
312		return 0;
313	bpf_kptr_xchg(&v->ref_ptr, p);
314	return 0;
315}
316
317SEC("?tc")
318int reject_bad_type_xchg(struct __sk_buff *ctx)
319{
320	struct prog_test_ref_kfunc *ref_ptr;
321	struct map_value *v;
322	int key = 0;
323
324	v = bpf_map_lookup_elem(&array_map, &key);
325	if (!v)
326		return 0;
327
328	ref_ptr = bpf_kfunc_call_test_acquire(&(unsigned long){0});
329	if (!ref_ptr)
330		return 0;
331	bpf_kptr_xchg(&v->ref_memb_ptr, ref_ptr);
332	return 0;
333}
334
335SEC("?tc")
336int reject_member_of_ref_xchg(struct __sk_buff *ctx)
337{
338	struct prog_test_ref_kfunc *ref_ptr;
339	struct map_value *v;
340	int key = 0;
341
342	v = bpf_map_lookup_elem(&array_map, &key);
343	if (!v)
344		return 0;
345
346	ref_ptr = bpf_kfunc_call_test_acquire(&(unsigned long){0});
347	if (!ref_ptr)
348		return 0;
349	bpf_kptr_xchg(&v->ref_memb_ptr, &ref_ptr->memb);
350	return 0;
351}
352
353SEC("?syscall")
354int reject_indirect_helper_access(struct __sk_buff *ctx)
355{
356	struct map_value *v;
357	int key = 0;
358
359	v = bpf_map_lookup_elem(&array_map, &key);
360	if (!v)
361		return 0;
362
363	bpf_get_current_comm(v, sizeof(v->buf) + 1);
364	return 0;
365}
366
367__noinline
368int write_func(int *p)
369{
370	return p ? *p = 42 : 0;
371}
372
373SEC("?tc")
374int reject_indirect_global_func_access(struct __sk_buff *ctx)
375{
376	struct map_value *v;
377	int key = 0;
378
379	v = bpf_map_lookup_elem(&array_map, &key);
380	if (!v)
381		return 0;
382
383	return write_func((void *)v + 5);
384}
385
386SEC("?tc")
387int kptr_xchg_ref_state(struct __sk_buff *ctx)
388{
389	struct prog_test_ref_kfunc *p;
390	struct map_value *v;
391	int key = 0;
392
393	v = bpf_map_lookup_elem(&array_map, &key);
394	if (!v)
395		return 0;
396
397	p = bpf_kfunc_call_test_acquire(&(unsigned long){0});
398	if (!p)
399		return 0;
400	bpf_kptr_xchg(&v->ref_ptr, p);
401	return 0;
402}
403
404SEC("?tc")
405int kptr_get_ref_state(struct __sk_buff *ctx)
406{
407	struct map_value *v;
408	int key = 0;
409
410	v = bpf_map_lookup_elem(&array_map, &key);
411	if (!v)
412		return 0;
413
414	bpf_kfunc_call_test_kptr_get(&v->ref_ptr, 0, 0);
415	return 0;
416}
417
418char _license[] SEC("license") = "GPL";
419