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 u32 (*target_nest
)(u32 value
, u32 (*nest
)(u32
));
21 static unsigned long target_ip
;
22 static unsigned long target2_ip
;
23 static unsigned long target_nest_ip
;
24 static int entry_return_value
;
26 static noinline u32
fprobe_selftest_target(u32 value
)
28 return (value
/ div_factor
);
31 static noinline u32
fprobe_selftest_target2(u32 value
)
33 return (value
/ div_factor
) + 1;
36 static noinline u32
fprobe_selftest_nest_target(u32 value
, u32 (*nest
)(u32
))
38 return nest(value
+ 2);
41 static notrace
int fp_entry_handler(struct fprobe
*fp
, unsigned long ip
,
43 struct pt_regs
*regs
, void *data
)
45 KUNIT_EXPECT_FALSE(current_test
, preemptible());
46 /* This can be called on the fprobe_selftest_target and the fprobe_selftest_target2 */
48 KUNIT_EXPECT_EQ(current_test
, ip
, target2_ip
);
49 entry_val
= (rand1
/ div_factor
);
50 if (fp
->entry_data_size
) {
51 KUNIT_EXPECT_NOT_NULL(current_test
, data
);
53 *(u32
*)data
= entry_val
;
55 KUNIT_EXPECT_NULL(current_test
, data
);
57 return entry_return_value
;
60 static notrace
void fp_exit_handler(struct fprobe
*fp
, unsigned long ip
,
62 struct pt_regs
*regs
, void *data
)
64 unsigned long ret
= regs_return_value(regs
);
66 KUNIT_EXPECT_FALSE(current_test
, preemptible());
67 if (ip
!= target_ip
) {
68 KUNIT_EXPECT_EQ(current_test
, ip
, target2_ip
);
69 KUNIT_EXPECT_EQ(current_test
, ret
, (rand1
/ div_factor
) + 1);
71 KUNIT_EXPECT_EQ(current_test
, ret
, (rand1
/ div_factor
));
72 KUNIT_EXPECT_EQ(current_test
, entry_val
, (rand1
/ div_factor
));
73 exit_val
= entry_val
+ div_factor
;
74 if (fp
->entry_data_size
) {
75 KUNIT_EXPECT_NOT_NULL(current_test
, data
);
77 KUNIT_EXPECT_EQ(current_test
, *(u32
*)data
, entry_val
);
79 KUNIT_EXPECT_NULL(current_test
, data
);
82 static notrace
int nest_entry_handler(struct fprobe
*fp
, unsigned long ip
,
84 struct pt_regs
*regs
, void *data
)
86 KUNIT_EXPECT_FALSE(current_test
, preemptible());
90 static notrace
void nest_exit_handler(struct fprobe
*fp
, unsigned long ip
,
92 struct pt_regs
*regs
, void *data
)
94 KUNIT_EXPECT_FALSE(current_test
, preemptible());
95 KUNIT_EXPECT_EQ(current_test
, ip
, target_nest_ip
);
98 /* Test entry only (no rethook) */
99 static void test_fprobe_entry(struct kunit
*test
)
101 struct fprobe fp_entry
= {
102 .entry_handler
= fp_entry_handler
,
107 /* Before register, unregister should be failed. */
108 KUNIT_EXPECT_NE(test
, 0, unregister_fprobe(&fp_entry
));
109 KUNIT_EXPECT_EQ(test
, 0, register_fprobe(&fp_entry
, "fprobe_selftest_target*", NULL
));
114 KUNIT_EXPECT_NE(test
, 0, entry_val
);
115 KUNIT_EXPECT_EQ(test
, 0, exit_val
);
120 KUNIT_EXPECT_NE(test
, 0, entry_val
);
121 KUNIT_EXPECT_EQ(test
, 0, exit_val
);
123 KUNIT_EXPECT_EQ(test
, 0, unregister_fprobe(&fp_entry
));
126 static void test_fprobe(struct kunit
*test
)
129 .entry_handler
= fp_entry_handler
,
130 .exit_handler
= fp_exit_handler
,
134 KUNIT_EXPECT_EQ(test
, 0, register_fprobe(&fp
, "fprobe_selftest_target*", NULL
));
139 KUNIT_EXPECT_NE(test
, 0, entry_val
);
140 KUNIT_EXPECT_EQ(test
, entry_val
+ div_factor
, exit_val
);
145 KUNIT_EXPECT_NE(test
, 0, entry_val
);
146 KUNIT_EXPECT_EQ(test
, entry_val
+ div_factor
, exit_val
);
148 KUNIT_EXPECT_EQ(test
, 0, unregister_fprobe(&fp
));
151 static void test_fprobe_syms(struct kunit
*test
)
153 static const char *syms
[] = {"fprobe_selftest_target", "fprobe_selftest_target2"};
155 .entry_handler
= fp_entry_handler
,
156 .exit_handler
= fp_exit_handler
,
160 KUNIT_EXPECT_EQ(test
, 0, register_fprobe_syms(&fp
, syms
, 2));
165 KUNIT_EXPECT_NE(test
, 0, entry_val
);
166 KUNIT_EXPECT_EQ(test
, entry_val
+ div_factor
, exit_val
);
171 KUNIT_EXPECT_NE(test
, 0, entry_val
);
172 KUNIT_EXPECT_EQ(test
, entry_val
+ div_factor
, exit_val
);
174 KUNIT_EXPECT_EQ(test
, 0, unregister_fprobe(&fp
));
177 /* Test private entry_data */
178 static void test_fprobe_data(struct kunit
*test
)
181 .entry_handler
= fp_entry_handler
,
182 .exit_handler
= fp_exit_handler
,
183 .entry_data_size
= sizeof(u32
),
187 KUNIT_EXPECT_EQ(test
, 0, register_fprobe(&fp
, "fprobe_selftest_target", NULL
));
191 KUNIT_EXPECT_EQ(test
, 0, unregister_fprobe(&fp
));
194 /* Test nr_maxactive */
195 static void test_fprobe_nest(struct kunit
*test
)
197 static const char *syms
[] = {"fprobe_selftest_target", "fprobe_selftest_nest_target"};
199 .entry_handler
= nest_entry_handler
,
200 .exit_handler
= nest_exit_handler
,
205 KUNIT_EXPECT_EQ(test
, 0, register_fprobe_syms(&fp
, syms
, 2));
207 target_nest(rand1
, target
);
208 KUNIT_EXPECT_EQ(test
, 1, fp
.nmissed
);
210 KUNIT_EXPECT_EQ(test
, 0, unregister_fprobe(&fp
));
213 static void test_fprobe_skip(struct kunit
*test
)
216 .entry_handler
= fp_entry_handler
,
217 .exit_handler
= fp_exit_handler
,
221 KUNIT_EXPECT_EQ(test
, 0, register_fprobe(&fp
, "fprobe_selftest_target", NULL
));
223 entry_return_value
= 1;
227 KUNIT_EXPECT_NE(test
, 0, entry_val
);
228 KUNIT_EXPECT_EQ(test
, 0, exit_val
);
229 KUNIT_EXPECT_EQ(test
, 0, fp
.nmissed
);
230 entry_return_value
= 0;
232 KUNIT_EXPECT_EQ(test
, 0, unregister_fprobe(&fp
));
235 static unsigned long get_ftrace_location(void *func
)
237 unsigned long size
, addr
= (unsigned long)func
;
239 if (!kallsyms_lookup_size_offset(addr
, &size
, NULL
) || !size
)
242 return ftrace_location_range(addr
, addr
+ size
- 1);
245 static int fprobe_test_init(struct kunit
*test
)
247 rand1
= get_random_u32_above(div_factor
);
248 target
= fprobe_selftest_target
;
249 target2
= fprobe_selftest_target2
;
250 target_nest
= fprobe_selftest_nest_target
;
251 target_ip
= get_ftrace_location(target
);
252 target2_ip
= get_ftrace_location(target2
);
253 target_nest_ip
= get_ftrace_location(target_nest
);
258 static struct kunit_case fprobe_testcases
[] = {
259 KUNIT_CASE(test_fprobe_entry
),
260 KUNIT_CASE(test_fprobe
),
261 KUNIT_CASE(test_fprobe_syms
),
262 KUNIT_CASE(test_fprobe_data
),
263 KUNIT_CASE(test_fprobe_nest
),
264 KUNIT_CASE(test_fprobe_skip
),
268 static struct kunit_suite fprobe_test_suite
= {
269 .name
= "fprobe_test",
270 .init
= fprobe_test_init
,
271 .test_cases
= fprobe_testcases
,
274 kunit_test_suites(&fprobe_test_suite
);