1// SPDX-License-Identifier: GPL-2.0
2#include <linux/bpf.h>
3#include <bpf/bpf_helpers.h>
4#include <bpf/bpf_tracing.h>
5#include <errno.h>
6
7char _license[] SEC("license") = "GPL";
8
9__u64 test1_result = 0;
10SEC("fentry/bpf_fentry_test1")
11int 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;
43SEC("fexit/bpf_fentry_test2")
44int 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;
70SEC("fmod_ret/bpf_modify_return_test")
71int 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;
99SEC("fexit/bpf_modify_return_test")
100int 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