xref: /linux/tools/testing/selftests/bpf/progs/get_func_args_test.c (revision 23b0f90ba871f096474e1c27c3d14f455189d2d9)
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")
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")
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")
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")
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")
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")
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)
171 SEC("fsession/bpf_fentry_test1")
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")
200 int BPF_PROG(test7)
201 {
202 	test7_result = 1;
203 	return 0;
204 }
205 #endif
206