1 // SPDX-License-Identifier: GPL-2.0
2 #include <vmlinux.h>
3 #include <bpf/bpf_helpers.h>
4 #include <bpf/bpf_tracing.h>
5 #include <errno.h>
6
7 char _license[] SEC("license") = "GPL";
8
9 __u64 test1_result = 0;
10 SEC("fentry/bpf_fentry_test1")
BPF_PROG(test1)11 int BPF_PROG(test1)
12 {
13 __u64 cnt = bpf_get_func_arg_cnt(ctx);
14 __u64 a = 0, z = 0, ret = 0;
15 __s64 err;
16
17 test1_result = cnt == 1;
18
19 /* valid arguments */
20 err = bpf_get_func_arg(ctx, 0, &a);
21
22 /* We need to cast access to traced function argument values with
23 * proper type cast, because trampoline uses type specific instruction
24 * to save it, like for 'int a' with 32-bit mov like:
25 *
26 * mov %edi,-0x8(%rbp)
27 *
28 * so the upper 4 bytes are not zeroed.
29 */
30 test1_result &= err == 0 && ((int) a == 1);
31
32 /* not valid argument */
33 err = bpf_get_func_arg(ctx, 1, &z);
34 test1_result &= err == -EINVAL;
35
36 /* return value fails in fentry */
37 err = bpf_get_func_ret(ctx, &ret);
38 test1_result &= err == -EOPNOTSUPP;
39 return 0;
40 }
41
42 __u64 test2_result = 0;
43 SEC("fexit/bpf_fentry_test2")
BPF_PROG(test2)44 int BPF_PROG(test2)
45 {
46 __u64 cnt = bpf_get_func_arg_cnt(ctx);
47 __u64 a = 0, b = 0, z = 0, ret = 0;
48 __s64 err;
49
50 test2_result = cnt == 2;
51
52 /* valid arguments */
53 err = bpf_get_func_arg(ctx, 0, &a);
54 test2_result &= err == 0 && (int) a == 2;
55
56 err = bpf_get_func_arg(ctx, 1, &b);
57 test2_result &= err == 0 && b == 3;
58
59 /* not valid argument */
60 err = bpf_get_func_arg(ctx, 2, &z);
61 test2_result &= err == -EINVAL;
62
63 /* return value */
64 err = bpf_get_func_ret(ctx, &ret);
65 test2_result &= err == 0 && ret == 5;
66 return 0;
67 }
68
69 __u64 test3_result = 0;
70 SEC("fmod_ret/bpf_modify_return_test")
BPF_PROG(fmod_ret_test,int _a,int * _b,int _ret)71 int BPF_PROG(fmod_ret_test, int _a, int *_b, int _ret)
72 {
73 __u64 cnt = bpf_get_func_arg_cnt(ctx);
74 __u64 a = 0, b = 0, z = 0, ret = 0;
75 __s64 err;
76
77 test3_result = cnt == 2;
78
79 /* valid arguments */
80 err = bpf_get_func_arg(ctx, 0, &a);
81 test3_result &= err == 0 && ((int) a == 1);
82
83 err = bpf_get_func_arg(ctx, 1, &b);
84 test3_result &= err == 0 && ((int *) b == _b);
85
86 /* not valid argument */
87 err = bpf_get_func_arg(ctx, 2, &z);
88 test3_result &= err == -EINVAL;
89
90 /* return value */
91 err = bpf_get_func_ret(ctx, &ret);
92 test3_result &= err == 0 && ret == 0;
93
94 /* change return value, it's checked in fexit_test program */
95 return 1234;
96 }
97
98 __u64 test4_result = 0;
99 SEC("fexit/bpf_modify_return_test")
BPF_PROG(fexit_test,int _a,int * _b,int _ret)100 int BPF_PROG(fexit_test, int _a, int *_b, int _ret)
101 {
102 __u64 cnt = bpf_get_func_arg_cnt(ctx);
103 __u64 a = 0, b = 0, z = 0, ret = 0;
104 __s64 err;
105
106 test4_result = cnt == 2;
107
108 /* valid arguments */
109 err = bpf_get_func_arg(ctx, 0, &a);
110 test4_result &= err == 0 && ((int) a == 1);
111
112 err = bpf_get_func_arg(ctx, 1, &b);
113 test4_result &= err == 0 && ((int *) b == _b);
114
115 /* not valid argument */
116 err = bpf_get_func_arg(ctx, 2, &z);
117 test4_result &= err == -EINVAL;
118
119 /* return value */
120 err = bpf_get_func_ret(ctx, &ret);
121 test4_result &= err == 0 && ret == 1234;
122 return 0;
123 }
124
125 __u64 test5_result = 0;
126 SEC("tp_btf/bpf_testmod_fentry_test1_tp")
BPF_PROG(tp_test1)127 int BPF_PROG(tp_test1)
128 {
129 __u64 cnt = bpf_get_func_arg_cnt(ctx);
130 __u64 a = 0, z = 0;
131 __s64 err;
132
133 test5_result = cnt == 1;
134
135 err = bpf_get_func_arg(ctx, 0, &a);
136 test5_result &= err == 0 && ((int) a == 1);
137
138 /* not valid argument */
139 err = bpf_get_func_arg(ctx, 1, &z);
140 test5_result &= err == -EINVAL;
141
142 return 0;
143 }
144
145 __u64 test6_result = 0;
146 SEC("tp_btf/bpf_testmod_fentry_test2_tp")
BPF_PROG(tp_test2)147 int BPF_PROG(tp_test2)
148 {
149 __u64 cnt = bpf_get_func_arg_cnt(ctx);
150 __u64 a = 0, b = 0, z = 0;
151 __s64 err;
152
153 test6_result = cnt == 2;
154
155 /* valid arguments */
156 err = bpf_get_func_arg(ctx, 0, &a);
157 test6_result &= err == 0 && (int) a == 2;
158
159 err = bpf_get_func_arg(ctx, 1, &b);
160 test6_result &= err == 0 && b == 3;
161
162 /* not valid argument */
163 err = bpf_get_func_arg(ctx, 2, &z);
164 test6_result &= err == -EINVAL;
165
166 return 0;
167 }
168
169 __u64 test7_result = 0;
170 #if defined(bpf_target_x86) || defined(bpf_target_arm64) || defined(bpf_target_riscv)
171 SEC("fsession/bpf_fentry_test1")
BPF_PROG(test7)172 int BPF_PROG(test7)
173 {
174 __u64 cnt = bpf_get_func_arg_cnt(ctx);
175 __u64 a = 0, z = 0, ret = 0;
176 __s64 err;
177
178 test7_result = cnt == 1;
179
180 /* valid arguments */
181 err = bpf_get_func_arg(ctx, 0, &a);
182 test7_result &= err == 0 && ((int) a == 1);
183
184 /* not valid argument */
185 err = bpf_get_func_arg(ctx, 1, &z);
186 test7_result &= err == -EINVAL;
187
188 if (bpf_session_is_return(ctx)) {
189 err = bpf_get_func_ret(ctx, &ret);
190 test7_result &= err == 0 && ret == 2;
191 } else {
192 err = bpf_get_func_ret(ctx, &ret);
193 test7_result &= err == 0 && ret == 0;
194 }
195
196 return 0;
197 }
198 #else
199 SEC("fentry/bpf_fentry_test1")
BPF_PROG(test7)200 int BPF_PROG(test7)
201 {
202 test7_result = 1;
203 return 0;
204 }
205 #endif
206