xref: /linux/tools/testing/selftests/bpf/progs/verifier_global_subprogs.c (revision 48eb03dd26304c24f03bdbb9382e89c8564e71df)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
3 
4 #include <stdbool.h>
5 #include <errno.h>
6 #include <string.h>
7 #include <linux/bpf.h>
8 #include <bpf/bpf_helpers.h>
9 #include "bpf_misc.h"
10 
11 int arr[1];
12 int unkn_idx;
13 
14 __noinline long global_bad(void)
15 {
16 	return arr[unkn_idx]; /* BOOM */
17 }
18 
19 __noinline long global_good(void)
20 {
21 	return arr[0];
22 }
23 
24 __noinline long global_calls_bad(void)
25 {
26 	return global_good() + global_bad() /* does BOOM indirectly */;
27 }
28 
29 __noinline long global_calls_good_only(void)
30 {
31 	return global_good();
32 }
33 
34 SEC("?raw_tp")
35 __success __log_level(2)
36 /* main prog is validated completely first */
37 __msg("('global_calls_good_only') is global and assumed valid.")
38 __msg("1: (95) exit")
39 /* eventually global_good() is transitively validated as well */
40 __msg("Validating global_good() func")
41 __msg("('global_good') is safe for any args that match its prototype")
42 int chained_global_func_calls_success(void)
43 {
44 	return global_calls_good_only();
45 }
46 
47 SEC("?raw_tp")
48 __failure __log_level(2)
49 /* main prog validated successfully first */
50 __msg("1: (95) exit")
51 /* eventually we validate global_bad() and fail */
52 __msg("Validating global_bad() func")
53 __msg("math between map_value pointer and register") /* BOOM */
54 int chained_global_func_calls_bad(void)
55 {
56 	return global_calls_bad();
57 }
58 
59 /* do out of bounds access forcing verifier to fail verification if this
60  * global func is called
61  */
62 __noinline int global_unsupp(const int *mem)
63 {
64 	if (!mem)
65 		return 0;
66 	return mem[100]; /* BOOM */
67 }
68 
69 const volatile bool skip_unsupp_global = true;
70 
71 SEC("?raw_tp")
72 __success
73 int guarded_unsupp_global_called(void)
74 {
75 	if (!skip_unsupp_global)
76 		return global_unsupp(NULL);
77 	return 0;
78 }
79 
80 SEC("?raw_tp")
81 __failure __log_level(2)
82 __msg("Func#1 ('global_unsupp') is global and assumed valid.")
83 __msg("Validating global_unsupp() func#1...")
84 __msg("value is outside of the allowed memory range")
85 int unguarded_unsupp_global_called(void)
86 {
87 	int x = 0;
88 
89 	return global_unsupp(&x);
90 }
91 
92 char _license[] SEC("license") = "GPL";
93