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 
7 struct 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 
14 struct 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 
21 extern struct prog_test_ref_kfunc *bpf_kfunc_call_test_acquire(unsigned long *sp) __ksym;
22 extern struct prog_test_ref_kfunc *
23 bpf_kfunc_call_test_kptr_get(struct prog_test_ref_kfunc **p, int a, int b) __ksym;
24 
25 SEC("?tc")
26 int 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 
39 SEC("?tc")
40 int 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 
57 SEC("?tc")
58 int 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 
75 SEC("?tc")
76 int 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 
90 SEC("?tc")
91 int 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 
103 SEC("?tc")
104 int 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 
126 SEC("?tc")
127 int 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 
146 SEC("?tc")
147 int 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 
160 SEC("?tc")
161 int 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 
177 SEC("?tc")
178 int 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 
196 SEC("?tc")
197 int 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 
210 SEC("?tc")
211 int 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 
217 SEC("?tc")
218 int 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 
224 SEC("?tc")
225 int 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 
238 SEC("?tc")
239 int 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 
252 SEC("?tc")
253 int 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 
266 SEC("?tc")
267 int 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 
280 SEC("?tc")
281 int 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 
299 SEC("?tc")
300 int 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 
317 SEC("?tc")
318 int 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 
335 SEC("?tc")
336 int 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 
353 SEC("?syscall")
354 int 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
368 int write_func(int *p)
369 {
370 	return p ? *p = 42 : 0;
371 }
372 
373 SEC("?tc")
374 int 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 
386 SEC("?tc")
387 int 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 
404 SEC("?tc")
405 int 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 
418 char _license[] SEC("license") = "GPL";
419