1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * test_fprobe.c - simple sanity test for fprobe
6 #include <linux/kernel.h>
7 #include <linux/fprobe.h>
8 #include <linux/random.h>
9 #include <kunit/test.h>
13 static struct kunit
*current_test
;
15 static u32 rand1
, entry_val
, exit_val
;
17 /* Use indirect calls to avoid inlining the target functions */
18 static u32 (*target
)(u32 value
);
19 static u32 (*target2
)(u32 value
);
20 static unsigned long target_ip
;
21 static unsigned long target2_ip
;
23 static noinline u32
fprobe_selftest_target(u32 value
)
25 return (value
/ div_factor
);
28 static noinline u32
fprobe_selftest_target2(u32 value
)
30 return (value
/ div_factor
) + 1;
33 static notrace
void fp_entry_handler(struct fprobe
*fp
, unsigned long ip
, struct pt_regs
*regs
)
35 KUNIT_EXPECT_FALSE(current_test
, preemptible());
36 /* This can be called on the fprobe_selftest_target and the fprobe_selftest_target2 */
38 KUNIT_EXPECT_EQ(current_test
, ip
, target2_ip
);
39 entry_val
= (rand1
/ div_factor
);
42 static notrace
void fp_exit_handler(struct fprobe
*fp
, unsigned long ip
, struct pt_regs
*regs
)
44 unsigned long ret
= regs_return_value(regs
);
46 KUNIT_EXPECT_FALSE(current_test
, preemptible());
47 if (ip
!= target_ip
) {
48 KUNIT_EXPECT_EQ(current_test
, ip
, target2_ip
);
49 KUNIT_EXPECT_EQ(current_test
, ret
, (rand1
/ div_factor
) + 1);
51 KUNIT_EXPECT_EQ(current_test
, ret
, (rand1
/ div_factor
));
52 KUNIT_EXPECT_EQ(current_test
, entry_val
, (rand1
/ div_factor
));
53 exit_val
= entry_val
+ div_factor
;
56 /* Test entry only (no rethook) */
57 static void test_fprobe_entry(struct kunit
*test
)
59 struct fprobe fp_entry
= {
60 .entry_handler
= fp_entry_handler
,
65 /* Before register, unregister should be failed. */
66 KUNIT_EXPECT_NE(test
, 0, unregister_fprobe(&fp_entry
));
67 KUNIT_EXPECT_EQ(test
, 0, register_fprobe(&fp_entry
, "fprobe_selftest_target*", NULL
));
72 KUNIT_EXPECT_NE(test
, 0, entry_val
);
73 KUNIT_EXPECT_EQ(test
, 0, exit_val
);
78 KUNIT_EXPECT_NE(test
, 0, entry_val
);
79 KUNIT_EXPECT_EQ(test
, 0, exit_val
);
81 KUNIT_EXPECT_EQ(test
, 0, unregister_fprobe(&fp_entry
));
84 static void test_fprobe(struct kunit
*test
)
87 .entry_handler
= fp_entry_handler
,
88 .exit_handler
= fp_exit_handler
,
92 KUNIT_EXPECT_EQ(test
, 0, register_fprobe(&fp
, "fprobe_selftest_target*", NULL
));
97 KUNIT_EXPECT_NE(test
, 0, entry_val
);
98 KUNIT_EXPECT_EQ(test
, entry_val
+ div_factor
, exit_val
);
103 KUNIT_EXPECT_NE(test
, 0, entry_val
);
104 KUNIT_EXPECT_EQ(test
, entry_val
+ div_factor
, exit_val
);
106 KUNIT_EXPECT_EQ(test
, 0, unregister_fprobe(&fp
));
109 static void test_fprobe_syms(struct kunit
*test
)
111 static const char *syms
[] = {"fprobe_selftest_target", "fprobe_selftest_target2"};
113 .entry_handler
= fp_entry_handler
,
114 .exit_handler
= fp_exit_handler
,
118 KUNIT_EXPECT_EQ(test
, 0, register_fprobe_syms(&fp
, syms
, 2));
123 KUNIT_EXPECT_NE(test
, 0, entry_val
);
124 KUNIT_EXPECT_EQ(test
, entry_val
+ div_factor
, exit_val
);
129 KUNIT_EXPECT_NE(test
, 0, entry_val
);
130 KUNIT_EXPECT_EQ(test
, entry_val
+ div_factor
, exit_val
);
132 KUNIT_EXPECT_EQ(test
, 0, unregister_fprobe(&fp
));
135 static unsigned long get_ftrace_location(void *func
)
137 unsigned long size
, addr
= (unsigned long)func
;
139 if (!kallsyms_lookup_size_offset(addr
, &size
, NULL
) || !size
)
142 return ftrace_location_range(addr
, addr
+ size
- 1);
145 static int fprobe_test_init(struct kunit
*test
)
147 rand1
= get_random_u32_above(div_factor
);
148 target
= fprobe_selftest_target
;
149 target2
= fprobe_selftest_target2
;
150 target_ip
= get_ftrace_location(target
);
151 target2_ip
= get_ftrace_location(target2
);
156 static struct kunit_case fprobe_testcases
[] = {
157 KUNIT_CASE(test_fprobe_entry
),
158 KUNIT_CASE(test_fprobe
),
159 KUNIT_CASE(test_fprobe_syms
),
163 static struct kunit_suite fprobe_test_suite
= {
164 .name
= "fprobe_test",
165 .init
= fprobe_test_init
,
166 .test_cases
= fprobe_testcases
,
169 kunit_test_suites(&fprobe_test_suite
);
171 MODULE_LICENSE("GPL");