1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * test_fprobe.c - simple sanity test for fprobe 4 */ 5 6 #include <linux/kernel.h> 7 #include <linux/fprobe.h> 8 #include <linux/random.h> 9 #include <kunit/test.h> 10 11 #define div_factor 3 12 13 static struct kunit *current_test; 14 15 static u32 rand1, entry_only_val, entry_val, exit_val; 16 static u32 entry_only_count, entry_count, exit_count; 17 18 /* Use indirect calls to avoid inlining the target functions */ 19 static u32 (*target)(u32 value); 20 static u32 (*target2)(u32 value); 21 static unsigned long target_ip; 22 static unsigned long target2_ip; 23 static int entry_return_value; 24 25 static noinline u32 fprobe_selftest_target(u32 value) 26 { 27 return (value / div_factor); 28 } 29 30 static noinline u32 fprobe_selftest_target2(u32 value) 31 { 32 return (value / div_factor) + 1; 33 } 34 35 static notrace int fp_entry_handler(struct fprobe *fp, unsigned long ip, 36 unsigned long ret_ip, 37 struct ftrace_regs *fregs, void *data) 38 { 39 KUNIT_EXPECT_FALSE(current_test, preemptible()); 40 /* This can be called on the fprobe_selftest_target and the fprobe_selftest_target2 */ 41 if (ip != target_ip) 42 KUNIT_EXPECT_EQ(current_test, ip, target2_ip); 43 entry_val = (rand1 / div_factor); 44 if (fp->entry_data_size) { 45 KUNIT_EXPECT_NOT_NULL(current_test, data); 46 if (data) 47 *(u32 *)data = entry_val; 48 } else 49 KUNIT_EXPECT_NULL(current_test, data); 50 51 return entry_return_value; 52 } 53 54 static notrace void fp_exit_handler(struct fprobe *fp, unsigned long ip, 55 unsigned long ret_ip, 56 struct ftrace_regs *fregs, void *data) 57 { 58 unsigned long ret = ftrace_regs_get_return_value(fregs); 59 60 KUNIT_EXPECT_FALSE(current_test, preemptible()); 61 if (ip != target_ip) { 62 KUNIT_EXPECT_EQ(current_test, ip, target2_ip); 63 KUNIT_EXPECT_EQ(current_test, ret, (rand1 / div_factor) + 1); 64 } else 65 KUNIT_EXPECT_EQ(current_test, ret, (rand1 / div_factor)); 66 KUNIT_EXPECT_EQ(current_test, entry_val, (rand1 / div_factor)); 67 exit_val = entry_val + div_factor; 68 if (fp->entry_data_size) { 69 KUNIT_EXPECT_NOT_NULL(current_test, data); 70 if (data) 71 KUNIT_EXPECT_EQ(current_test, *(u32 *)data, entry_val); 72 } else 73 KUNIT_EXPECT_NULL(current_test, data); 74 } 75 76 /* Test entry only (no rethook) */ 77 static void test_fprobe_entry(struct kunit *test) 78 { 79 struct fprobe fp_entry = { 80 .entry_handler = fp_entry_handler, 81 }; 82 83 current_test = test; 84 85 /* Before register, unregister should be failed. */ 86 KUNIT_EXPECT_NE(test, 0, unregister_fprobe(&fp_entry)); 87 KUNIT_EXPECT_EQ(test, 0, register_fprobe(&fp_entry, "fprobe_selftest_target*", NULL)); 88 89 entry_val = 0; 90 exit_val = 0; 91 target(rand1); 92 KUNIT_EXPECT_NE(test, 0, entry_val); 93 KUNIT_EXPECT_EQ(test, 0, exit_val); 94 95 entry_val = 0; 96 exit_val = 0; 97 target2(rand1); 98 KUNIT_EXPECT_NE(test, 0, entry_val); 99 KUNIT_EXPECT_EQ(test, 0, exit_val); 100 101 KUNIT_EXPECT_EQ(test, 0, unregister_fprobe(&fp_entry)); 102 } 103 104 static void test_fprobe(struct kunit *test) 105 { 106 struct fprobe fp = { 107 .entry_handler = fp_entry_handler, 108 .exit_handler = fp_exit_handler, 109 }; 110 111 current_test = test; 112 KUNIT_EXPECT_EQ(test, 0, register_fprobe(&fp, "fprobe_selftest_target*", NULL)); 113 114 entry_val = 0; 115 exit_val = 0; 116 target(rand1); 117 KUNIT_EXPECT_NE(test, 0, entry_val); 118 KUNIT_EXPECT_EQ(test, entry_val + div_factor, exit_val); 119 120 entry_val = 0; 121 exit_val = 0; 122 target2(rand1); 123 KUNIT_EXPECT_NE(test, 0, entry_val); 124 KUNIT_EXPECT_EQ(test, entry_val + div_factor, exit_val); 125 126 KUNIT_EXPECT_EQ(test, 0, unregister_fprobe(&fp)); 127 } 128 129 static void test_fprobe_syms(struct kunit *test) 130 { 131 static const char *syms[] = {"fprobe_selftest_target", "fprobe_selftest_target2"}; 132 struct fprobe fp = { 133 .entry_handler = fp_entry_handler, 134 .exit_handler = fp_exit_handler, 135 }; 136 137 current_test = test; 138 KUNIT_EXPECT_EQ(test, 0, register_fprobe_syms(&fp, syms, 2)); 139 140 entry_val = 0; 141 exit_val = 0; 142 target(rand1); 143 KUNIT_EXPECT_NE(test, 0, entry_val); 144 KUNIT_EXPECT_EQ(test, entry_val + div_factor, exit_val); 145 146 entry_val = 0; 147 exit_val = 0; 148 target2(rand1); 149 KUNIT_EXPECT_NE(test, 0, entry_val); 150 KUNIT_EXPECT_EQ(test, entry_val + div_factor, exit_val); 151 152 KUNIT_EXPECT_EQ(test, 0, unregister_fprobe(&fp)); 153 } 154 155 /* Test private entry_data */ 156 static void test_fprobe_data(struct kunit *test) 157 { 158 struct fprobe fp = { 159 .entry_handler = fp_entry_handler, 160 .exit_handler = fp_exit_handler, 161 .entry_data_size = sizeof(u32), 162 }; 163 164 current_test = test; 165 KUNIT_EXPECT_EQ(test, 0, register_fprobe(&fp, "fprobe_selftest_target", NULL)); 166 167 target(rand1); 168 169 KUNIT_EXPECT_EQ(test, 0, unregister_fprobe(&fp)); 170 } 171 172 static void test_fprobe_skip(struct kunit *test) 173 { 174 struct fprobe fp = { 175 .entry_handler = fp_entry_handler, 176 .exit_handler = fp_exit_handler, 177 }; 178 179 current_test = test; 180 KUNIT_EXPECT_EQ(test, 0, register_fprobe(&fp, "fprobe_selftest_target", NULL)); 181 182 entry_return_value = 1; 183 entry_val = 0; 184 exit_val = 0; 185 target(rand1); 186 KUNIT_EXPECT_NE(test, 0, entry_val); 187 KUNIT_EXPECT_EQ(test, 0, exit_val); 188 KUNIT_EXPECT_EQ(test, 0, fp.nmissed); 189 entry_return_value = 0; 190 191 KUNIT_EXPECT_EQ(test, 0, unregister_fprobe(&fp)); 192 } 193 194 /* Handler for fprobe entry only case */ 195 static notrace int entry_only_handler(struct fprobe *fp, unsigned long ip, 196 unsigned long ret_ip, 197 struct ftrace_regs *fregs, void *data) 198 { 199 KUNIT_EXPECT_FALSE(current_test, preemptible()); 200 KUNIT_EXPECT_EQ(current_test, ip, target_ip); 201 202 entry_only_count++; 203 entry_only_val = (rand1 / div_factor); 204 205 return 0; 206 } 207 208 static notrace int fprobe_entry_multi_handler(struct fprobe *fp, unsigned long ip, 209 unsigned long ret_ip, 210 struct ftrace_regs *fregs, 211 void *data) 212 { 213 KUNIT_EXPECT_FALSE(current_test, preemptible()); 214 KUNIT_EXPECT_EQ(current_test, ip, target_ip); 215 216 entry_count++; 217 entry_val = (rand1 / div_factor); 218 219 return 0; 220 } 221 222 static notrace void fprobe_exit_multi_handler(struct fprobe *fp, unsigned long ip, 223 unsigned long ret_ip, 224 struct ftrace_regs *fregs, 225 void *data) 226 { 227 unsigned long ret = ftrace_regs_get_return_value(fregs); 228 229 KUNIT_EXPECT_FALSE(current_test, preemptible()); 230 KUNIT_EXPECT_EQ(current_test, ip, target_ip); 231 KUNIT_EXPECT_EQ(current_test, ret, (rand1 / div_factor)); 232 233 exit_count++; 234 exit_val = ret; 235 } 236 237 static void check_fprobe_multi(struct kunit *test) 238 { 239 entry_only_count = entry_count = exit_count = 0; 240 entry_only_val = entry_val = exit_val = 0; 241 242 target(rand1); 243 244 /* Verify all handlers were called */ 245 KUNIT_EXPECT_EQ(test, 1, entry_only_count); 246 KUNIT_EXPECT_EQ(test, 1, entry_count); 247 KUNIT_EXPECT_EQ(test, 1, exit_count); 248 249 /* Verify values are correct */ 250 KUNIT_EXPECT_EQ(test, (rand1 / div_factor), entry_only_val); 251 KUNIT_EXPECT_EQ(test, (rand1 / div_factor), entry_val); 252 KUNIT_EXPECT_EQ(test, (rand1 / div_factor), exit_val); 253 } 254 255 /* Test multiple fprobes hooking the same target function */ 256 static void test_fprobe_multi(struct kunit *test) 257 { 258 struct fprobe fp1 = { 259 .entry_handler = fprobe_entry_multi_handler, 260 .exit_handler = fprobe_exit_multi_handler, 261 }; 262 struct fprobe fp2 = { 263 .entry_handler = entry_only_handler, 264 }; 265 266 current_test = test; 267 268 /* Test Case 1: Register in order 1 -> 2 */ 269 KUNIT_EXPECT_EQ(test, 0, register_fprobe(&fp1, "fprobe_selftest_target", NULL)); 270 KUNIT_EXPECT_EQ(test, 0, register_fprobe(&fp2, "fprobe_selftest_target", NULL)); 271 272 check_fprobe_multi(test); 273 274 /* Unregister all */ 275 KUNIT_EXPECT_EQ(test, 0, unregister_fprobe(&fp1)); 276 KUNIT_EXPECT_EQ(test, 0, unregister_fprobe(&fp2)); 277 278 /* Test Case 2: Register in order 2 -> 1 */ 279 KUNIT_EXPECT_EQ(test, 0, register_fprobe(&fp2, "fprobe_selftest_target", NULL)); 280 KUNIT_EXPECT_EQ(test, 0, register_fprobe(&fp1, "fprobe_selftest_target", NULL)); 281 282 check_fprobe_multi(test); 283 284 /* Unregister all */ 285 KUNIT_EXPECT_EQ(test, 0, unregister_fprobe(&fp1)); 286 KUNIT_EXPECT_EQ(test, 0, unregister_fprobe(&fp2)); 287 } 288 289 static unsigned long get_ftrace_location(void *func) 290 { 291 unsigned long size, addr = (unsigned long)func; 292 293 if (!kallsyms_lookup_size_offset(addr, &size, NULL) || !size) 294 return 0; 295 296 return ftrace_location_range(addr, addr + size - 1); 297 } 298 299 static int fprobe_test_init(struct kunit *test) 300 { 301 rand1 = get_random_u32_above(div_factor); 302 target = fprobe_selftest_target; 303 target2 = fprobe_selftest_target2; 304 target_ip = get_ftrace_location(target); 305 target2_ip = get_ftrace_location(target2); 306 307 return 0; 308 } 309 310 static struct kunit_case fprobe_testcases[] = { 311 KUNIT_CASE(test_fprobe_entry), 312 KUNIT_CASE(test_fprobe), 313 KUNIT_CASE(test_fprobe_syms), 314 KUNIT_CASE(test_fprobe_data), 315 KUNIT_CASE(test_fprobe_skip), 316 KUNIT_CASE(test_fprobe_multi), 317 {} 318 }; 319 320 static struct kunit_suite fprobe_test_suite = { 321 .name = "fprobe_test", 322 .init = fprobe_test_init, 323 .test_cases = fprobe_testcases, 324 }; 325 326 kunit_test_suites(&fprobe_test_suite); 327 328