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