1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2022 Facebook */
3 
4 #include <errno.h>
5 #include <string.h>
6 #include <linux/bpf.h>
7 #include <bpf/bpf_helpers.h>
8 #include "bpf_misc.h"
9 
10 char _license[] SEC("license") = "GPL";
11 
12 struct test_info {
13 	int x;
14 	struct bpf_dynptr ptr;
15 };
16 
17 struct {
18 	__uint(type, BPF_MAP_TYPE_ARRAY);
19 	__uint(max_entries, 1);
20 	__type(key, __u32);
21 	__type(value, struct bpf_dynptr);
22 } array_map1 SEC(".maps");
23 
24 struct {
25 	__uint(type, BPF_MAP_TYPE_ARRAY);
26 	__uint(max_entries, 1);
27 	__type(key, __u32);
28 	__type(value, struct test_info);
29 } array_map2 SEC(".maps");
30 
31 struct {
32 	__uint(type, BPF_MAP_TYPE_ARRAY);
33 	__uint(max_entries, 1);
34 	__type(key, __u32);
35 	__type(value, __u32);
36 } array_map3 SEC(".maps");
37 
38 struct sample {
39 	int pid;
40 	long value;
41 	char comm[16];
42 };
43 
44 struct {
45 	__uint(type, BPF_MAP_TYPE_RINGBUF);
46 	__uint(max_entries, 4096);
47 } ringbuf SEC(".maps");
48 
49 int err, val;
50 
51 static int get_map_val_dynptr(struct bpf_dynptr *ptr)
52 {
53 	__u32 key = 0, *map_val;
54 
55 	bpf_map_update_elem(&array_map3, &key, &val, 0);
56 
57 	map_val = bpf_map_lookup_elem(&array_map3, &key);
58 	if (!map_val)
59 		return -ENOENT;
60 
61 	bpf_dynptr_from_mem(map_val, sizeof(*map_val), 0, ptr);
62 
63 	return 0;
64 }
65 
66 /* Every bpf_ringbuf_reserve_dynptr call must have a corresponding
67  * bpf_ringbuf_submit/discard_dynptr call
68  */
69 SEC("?raw_tp")
70 __failure __msg("Unreleased reference id=1")
71 int ringbuf_missing_release1(void *ctx)
72 {
73 	struct bpf_dynptr ptr;
74 
75 	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
76 
77 	/* missing a call to bpf_ringbuf_discard/submit_dynptr */
78 
79 	return 0;
80 }
81 
82 SEC("?raw_tp")
83 __failure __msg("Unreleased reference id=2")
84 int ringbuf_missing_release2(void *ctx)
85 {
86 	struct bpf_dynptr ptr1, ptr2;
87 	struct sample *sample;
88 
89 	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr1);
90 	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr2);
91 
92 	sample = bpf_dynptr_data(&ptr1, 0, sizeof(*sample));
93 	if (!sample) {
94 		bpf_ringbuf_discard_dynptr(&ptr1, 0);
95 		bpf_ringbuf_discard_dynptr(&ptr2, 0);
96 		return 0;
97 	}
98 
99 	bpf_ringbuf_submit_dynptr(&ptr1, 0);
100 
101 	/* missing a call to bpf_ringbuf_discard/submit_dynptr on ptr2 */
102 
103 	return 0;
104 }
105 
106 static int missing_release_callback_fn(__u32 index, void *data)
107 {
108 	struct bpf_dynptr ptr;
109 
110 	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
111 
112 	/* missing a call to bpf_ringbuf_discard/submit_dynptr */
113 
114 	return 0;
115 }
116 
117 /* Any dynptr initialized within a callback must have bpf_dynptr_put called */
118 SEC("?raw_tp")
119 __failure __msg("Unreleased reference id")
120 int ringbuf_missing_release_callback(void *ctx)
121 {
122 	bpf_loop(10, missing_release_callback_fn, NULL, 0);
123 	return 0;
124 }
125 
126 /* Can't call bpf_ringbuf_submit/discard_dynptr on a non-initialized dynptr */
127 SEC("?raw_tp")
128 __failure __msg("arg 1 is an unacquired reference")
129 int ringbuf_release_uninit_dynptr(void *ctx)
130 {
131 	struct bpf_dynptr ptr;
132 
133 	/* this should fail */
134 	bpf_ringbuf_submit_dynptr(&ptr, 0);
135 
136 	return 0;
137 }
138 
139 /* A dynptr can't be used after it has been invalidated */
140 SEC("?raw_tp")
141 __failure __msg("Expected an initialized dynptr as arg #3")
142 int use_after_invalid(void *ctx)
143 {
144 	struct bpf_dynptr ptr;
145 	char read_data[64];
146 
147 	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(read_data), 0, &ptr);
148 
149 	bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0);
150 
151 	bpf_ringbuf_submit_dynptr(&ptr, 0);
152 
153 	/* this should fail */
154 	bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0);
155 
156 	return 0;
157 }
158 
159 /* Can't call non-dynptr ringbuf APIs on a dynptr ringbuf sample */
160 SEC("?raw_tp")
161 __failure __msg("type=mem expected=ringbuf_mem")
162 int ringbuf_invalid_api(void *ctx)
163 {
164 	struct bpf_dynptr ptr;
165 	struct sample *sample;
166 
167 	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr);
168 	sample = bpf_dynptr_data(&ptr, 0, sizeof(*sample));
169 	if (!sample)
170 		goto done;
171 
172 	sample->pid = 123;
173 
174 	/* invalid API use. need to use dynptr API to submit/discard */
175 	bpf_ringbuf_submit(sample, 0);
176 
177 done:
178 	bpf_ringbuf_discard_dynptr(&ptr, 0);
179 	return 0;
180 }
181 
182 /* Can't add a dynptr to a map */
183 SEC("?raw_tp")
184 __failure __msg("invalid indirect read from stack")
185 int add_dynptr_to_map1(void *ctx)
186 {
187 	struct bpf_dynptr ptr;
188 	int key = 0;
189 
190 	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
191 
192 	/* this should fail */
193 	bpf_map_update_elem(&array_map1, &key, &ptr, 0);
194 
195 	bpf_ringbuf_submit_dynptr(&ptr, 0);
196 
197 	return 0;
198 }
199 
200 /* Can't add a struct with an embedded dynptr to a map */
201 SEC("?raw_tp")
202 __failure __msg("invalid indirect read from stack")
203 int add_dynptr_to_map2(void *ctx)
204 {
205 	struct test_info x;
206 	int key = 0;
207 
208 	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &x.ptr);
209 
210 	/* this should fail */
211 	bpf_map_update_elem(&array_map2, &key, &x, 0);
212 
213 	bpf_ringbuf_submit_dynptr(&x.ptr, 0);
214 
215 	return 0;
216 }
217 
218 /* A data slice can't be accessed out of bounds */
219 SEC("?raw_tp")
220 __failure __msg("value is outside of the allowed memory range")
221 int data_slice_out_of_bounds_ringbuf(void *ctx)
222 {
223 	struct bpf_dynptr ptr;
224 	void *data;
225 
226 	bpf_ringbuf_reserve_dynptr(&ringbuf, 8, 0, &ptr);
227 
228 	data  = bpf_dynptr_data(&ptr, 0, 8);
229 	if (!data)
230 		goto done;
231 
232 	/* can't index out of bounds of the data slice */
233 	val = *((char *)data + 8);
234 
235 done:
236 	bpf_ringbuf_submit_dynptr(&ptr, 0);
237 	return 0;
238 }
239 
240 SEC("?raw_tp")
241 __failure __msg("value is outside of the allowed memory range")
242 int data_slice_out_of_bounds_map_value(void *ctx)
243 {
244 	__u32 key = 0, map_val;
245 	struct bpf_dynptr ptr;
246 	void *data;
247 
248 	get_map_val_dynptr(&ptr);
249 
250 	data  = bpf_dynptr_data(&ptr, 0, sizeof(map_val));
251 	if (!data)
252 		return 0;
253 
254 	/* can't index out of bounds of the data slice */
255 	val = *((char *)data + (sizeof(map_val) + 1));
256 
257 	return 0;
258 }
259 
260 /* A data slice can't be used after it has been released */
261 SEC("?raw_tp")
262 __failure __msg("invalid mem access 'scalar'")
263 int data_slice_use_after_release1(void *ctx)
264 {
265 	struct bpf_dynptr ptr;
266 	struct sample *sample;
267 
268 	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr);
269 	sample = bpf_dynptr_data(&ptr, 0, sizeof(*sample));
270 	if (!sample)
271 		goto done;
272 
273 	sample->pid = 123;
274 
275 	bpf_ringbuf_submit_dynptr(&ptr, 0);
276 
277 	/* this should fail */
278 	val = sample->pid;
279 
280 	return 0;
281 
282 done:
283 	bpf_ringbuf_discard_dynptr(&ptr, 0);
284 	return 0;
285 }
286 
287 /* A data slice can't be used after it has been released.
288  *
289  * This tests the case where the data slice tracks a dynptr (ptr2)
290  * that is at a non-zero offset from the frame pointer (ptr1 is at fp,
291  * ptr2 is at fp - 16).
292  */
293 SEC("?raw_tp")
294 __failure __msg("invalid mem access 'scalar'")
295 int data_slice_use_after_release2(void *ctx)
296 {
297 	struct bpf_dynptr ptr1, ptr2;
298 	struct sample *sample;
299 
300 	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr1);
301 	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr2);
302 
303 	sample = bpf_dynptr_data(&ptr2, 0, sizeof(*sample));
304 	if (!sample)
305 		goto done;
306 
307 	sample->pid = 23;
308 
309 	bpf_ringbuf_submit_dynptr(&ptr2, 0);
310 
311 	/* this should fail */
312 	sample->pid = 23;
313 
314 	bpf_ringbuf_submit_dynptr(&ptr1, 0);
315 
316 	return 0;
317 
318 done:
319 	bpf_ringbuf_discard_dynptr(&ptr2, 0);
320 	bpf_ringbuf_discard_dynptr(&ptr1, 0);
321 	return 0;
322 }
323 
324 /* A data slice must be first checked for NULL */
325 SEC("?raw_tp")
326 __failure __msg("invalid mem access 'mem_or_null'")
327 int data_slice_missing_null_check1(void *ctx)
328 {
329 	struct bpf_dynptr ptr;
330 	void *data;
331 
332 	bpf_ringbuf_reserve_dynptr(&ringbuf, 8, 0, &ptr);
333 
334 	data  = bpf_dynptr_data(&ptr, 0, 8);
335 
336 	/* missing if (!data) check */
337 
338 	/* this should fail */
339 	*(__u8 *)data = 3;
340 
341 	bpf_ringbuf_submit_dynptr(&ptr, 0);
342 	return 0;
343 }
344 
345 /* A data slice can't be dereferenced if it wasn't checked for null */
346 SEC("?raw_tp")
347 __failure __msg("invalid mem access 'mem_or_null'")
348 int data_slice_missing_null_check2(void *ctx)
349 {
350 	struct bpf_dynptr ptr;
351 	__u64 *data1, *data2;
352 
353 	bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr);
354 
355 	data1 = bpf_dynptr_data(&ptr, 0, 8);
356 	data2 = bpf_dynptr_data(&ptr, 0, 8);
357 	if (data1)
358 		/* this should fail */
359 		*data2 = 3;
360 
361 done:
362 	bpf_ringbuf_discard_dynptr(&ptr, 0);
363 	return 0;
364 }
365 
366 /* Can't pass in a dynptr as an arg to a helper function that doesn't take in a
367  * dynptr argument
368  */
369 SEC("?raw_tp")
370 __failure __msg("invalid indirect read from stack")
371 int invalid_helper1(void *ctx)
372 {
373 	struct bpf_dynptr ptr;
374 
375 	get_map_val_dynptr(&ptr);
376 
377 	/* this should fail */
378 	bpf_strncmp((const char *)&ptr, sizeof(ptr), "hello!");
379 
380 	return 0;
381 }
382 
383 /* A dynptr can't be passed into a helper function at a non-zero offset */
384 SEC("?raw_tp")
385 __failure __msg("Expected an initialized dynptr as arg #3")
386 int invalid_helper2(void *ctx)
387 {
388 	struct bpf_dynptr ptr;
389 	char read_data[64];
390 
391 	get_map_val_dynptr(&ptr);
392 
393 	/* this should fail */
394 	bpf_dynptr_read(read_data, sizeof(read_data), (void *)&ptr + 8, 0, 0);
395 
396 	return 0;
397 }
398 
399 /* A bpf_dynptr is invalidated if it's been written into */
400 SEC("?raw_tp")
401 __failure __msg("Expected an initialized dynptr as arg #1")
402 int invalid_write1(void *ctx)
403 {
404 	struct bpf_dynptr ptr;
405 	void *data;
406 	__u8 x = 0;
407 
408 	get_map_val_dynptr(&ptr);
409 
410 	memcpy(&ptr, &x, sizeof(x));
411 
412 	/* this should fail */
413 	data = bpf_dynptr_data(&ptr, 0, 1);
414 
415 	return 0;
416 }
417 
418 /*
419  * A bpf_dynptr can't be used as a dynptr if it has been written into at a fixed
420  * offset
421  */
422 SEC("?raw_tp")
423 __failure __msg("Expected an initialized dynptr as arg #3")
424 int invalid_write2(void *ctx)
425 {
426 	struct bpf_dynptr ptr;
427 	char read_data[64];
428 	__u8 x = 0;
429 
430 	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);
431 
432 	memcpy((void *)&ptr + 8, &x, sizeof(x));
433 
434 	/* this should fail */
435 	bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0);
436 
437 	bpf_ringbuf_submit_dynptr(&ptr, 0);
438 
439 	return 0;
440 }
441 
442 /*
443  * A bpf_dynptr can't be used as a dynptr if it has been written into at a
444  * non-const offset
445  */
446 SEC("?raw_tp")
447 __failure __msg("Expected an initialized dynptr as arg #1")
448 int invalid_write3(void *ctx)
449 {
450 	struct bpf_dynptr ptr;
451 	char stack_buf[16];
452 	unsigned long len;
453 	__u8 x = 0;
454 
455 	bpf_ringbuf_reserve_dynptr(&ringbuf, 8, 0, &ptr);
456 
457 	memcpy(stack_buf, &val, sizeof(val));
458 	len = stack_buf[0] & 0xf;
459 
460 	memcpy((void *)&ptr + len, &x, sizeof(x));
461 
462 	/* this should fail */
463 	bpf_ringbuf_submit_dynptr(&ptr, 0);
464 
465 	return 0;
466 }
467 
468 static int invalid_write4_callback(__u32 index, void *data)
469 {
470 	*(__u32 *)data = 123;
471 
472 	return 0;
473 }
474 
475 /* If the dynptr is written into in a callback function, it should
476  * be invalidated as a dynptr
477  */
478 SEC("?raw_tp")
479 __failure __msg("arg 1 is an unacquired reference")
480 int invalid_write4(void *ctx)
481 {
482 	struct bpf_dynptr ptr;
483 
484 	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);
485 
486 	bpf_loop(10, invalid_write4_callback, &ptr, 0);
487 
488 	/* this should fail */
489 	bpf_ringbuf_submit_dynptr(&ptr, 0);
490 
491 	return 0;
492 }
493 
494 /* A globally-defined bpf_dynptr can't be used (it must reside as a stack frame) */
495 struct bpf_dynptr global_dynptr;
496 
497 SEC("?raw_tp")
498 __failure __msg("type=map_value expected=fp")
499 int global(void *ctx)
500 {
501 	/* this should fail */
502 	bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &global_dynptr);
503 
504 	bpf_ringbuf_discard_dynptr(&global_dynptr, 0);
505 
506 	return 0;
507 }
508 
509 /* A direct read should fail */
510 SEC("?raw_tp")
511 __failure __msg("invalid read from stack")
512 int invalid_read1(void *ctx)
513 {
514 	struct bpf_dynptr ptr;
515 
516 	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);
517 
518 	/* this should fail */
519 	val = *(int *)&ptr;
520 
521 	bpf_ringbuf_discard_dynptr(&ptr, 0);
522 
523 	return 0;
524 }
525 
526 /* A direct read at an offset should fail */
527 SEC("?raw_tp")
528 __failure __msg("cannot pass in dynptr at an offset")
529 int invalid_read2(void *ctx)
530 {
531 	struct bpf_dynptr ptr;
532 	char read_data[64];
533 
534 	get_map_val_dynptr(&ptr);
535 
536 	/* this should fail */
537 	bpf_dynptr_read(read_data, sizeof(read_data), (void *)&ptr + 1, 0, 0);
538 
539 	return 0;
540 }
541 
542 /* A direct read at an offset into the lower stack slot should fail */
543 SEC("?raw_tp")
544 __failure __msg("invalid read from stack")
545 int invalid_read3(void *ctx)
546 {
547 	struct bpf_dynptr ptr1, ptr2;
548 
549 	bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr1);
550 	bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr2);
551 
552 	/* this should fail */
553 	memcpy(&val, (void *)&ptr1 + 8, sizeof(val));
554 
555 	bpf_ringbuf_discard_dynptr(&ptr1, 0);
556 	bpf_ringbuf_discard_dynptr(&ptr2, 0);
557 
558 	return 0;
559 }
560 
561 static int invalid_read4_callback(__u32 index, void *data)
562 {
563 	/* this should fail */
564 	val = *(__u32 *)data;
565 
566 	return 0;
567 }
568 
569 /* A direct read within a callback function should fail */
570 SEC("?raw_tp")
571 __failure __msg("invalid read from stack")
572 int invalid_read4(void *ctx)
573 {
574 	struct bpf_dynptr ptr;
575 
576 	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);
577 
578 	bpf_loop(10, invalid_read4_callback, &ptr, 0);
579 
580 	bpf_ringbuf_submit_dynptr(&ptr, 0);
581 
582 	return 0;
583 }
584 
585 /* Initializing a dynptr on an offset should fail */
586 SEC("?raw_tp")
587 __failure __msg("invalid write to stack")
588 int invalid_offset(void *ctx)
589 {
590 	struct bpf_dynptr ptr;
591 
592 	/* this should fail */
593 	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr + 1);
594 
595 	bpf_ringbuf_discard_dynptr(&ptr, 0);
596 
597 	return 0;
598 }
599 
600 /* Can't release a dynptr twice */
601 SEC("?raw_tp")
602 __failure __msg("arg 1 is an unacquired reference")
603 int release_twice(void *ctx)
604 {
605 	struct bpf_dynptr ptr;
606 
607 	bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr);
608 
609 	bpf_ringbuf_discard_dynptr(&ptr, 0);
610 
611 	/* this second release should fail */
612 	bpf_ringbuf_discard_dynptr(&ptr, 0);
613 
614 	return 0;
615 }
616 
617 static int release_twice_callback_fn(__u32 index, void *data)
618 {
619 	/* this should fail */
620 	bpf_ringbuf_discard_dynptr(data, 0);
621 
622 	return 0;
623 }
624 
625 /* Test that releasing a dynptr twice, where one of the releases happens
626  * within a calback function, fails
627  */
628 SEC("?raw_tp")
629 __failure __msg("arg 1 is an unacquired reference")
630 int release_twice_callback(void *ctx)
631 {
632 	struct bpf_dynptr ptr;
633 
634 	bpf_ringbuf_reserve_dynptr(&ringbuf, 32, 0, &ptr);
635 
636 	bpf_ringbuf_discard_dynptr(&ptr, 0);
637 
638 	bpf_loop(10, release_twice_callback_fn, &ptr, 0);
639 
640 	return 0;
641 }
642 
643 /* Reject unsupported local mem types for dynptr_from_mem API */
644 SEC("?raw_tp")
645 __failure __msg("Unsupported reg type fp for bpf_dynptr_from_mem data")
646 int dynptr_from_mem_invalid_api(void *ctx)
647 {
648 	struct bpf_dynptr ptr;
649 	int x = 0;
650 
651 	/* this should fail */
652 	bpf_dynptr_from_mem(&x, sizeof(x), 0, &ptr);
653 
654 	return 0;
655 }
656