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