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