xref: /openbmc/linux/lib/test_kprobes.c (revision 1fcd09fd)
1b9e94a7bSTiezhu Yang // SPDX-License-Identifier: GPL-2.0-or-later
2b9e94a7bSTiezhu Yang /*
3b9e94a7bSTiezhu Yang  * test_kprobes.c - simple sanity test for *probes
4b9e94a7bSTiezhu Yang  *
5b9e94a7bSTiezhu Yang  * Copyright IBM Corp. 2008
6b9e94a7bSTiezhu Yang  */
7b9e94a7bSTiezhu Yang 
8b9e94a7bSTiezhu Yang #include <linux/kernel.h>
9b9e94a7bSTiezhu Yang #include <linux/kprobes.h>
10b9e94a7bSTiezhu Yang #include <linux/random.h>
11b9e94a7bSTiezhu Yang #include <kunit/test.h>
12b9e94a7bSTiezhu Yang 
13b9e94a7bSTiezhu Yang #define div_factor 3
14b9e94a7bSTiezhu Yang 
15b9e94a7bSTiezhu Yang static u32 rand1, preh_val, posth_val;
16b9e94a7bSTiezhu Yang static u32 (*target)(u32 value);
17*1fcd09fdSMasami Hiramatsu (Google) static u32 (*recursed_target)(u32 value);
18b9e94a7bSTiezhu Yang static u32 (*target2)(u32 value);
19b9e94a7bSTiezhu Yang static struct kunit *current_test;
20b9e94a7bSTiezhu Yang 
21b9e94a7bSTiezhu Yang static unsigned long (*internal_target)(void);
22b9e94a7bSTiezhu Yang static unsigned long (*stacktrace_target)(void);
23b9e94a7bSTiezhu Yang static unsigned long (*stacktrace_driver)(void);
24b9e94a7bSTiezhu Yang static unsigned long target_return_address[2];
25b9e94a7bSTiezhu Yang 
kprobe_target(u32 value)26b9e94a7bSTiezhu Yang static noinline u32 kprobe_target(u32 value)
27b9e94a7bSTiezhu Yang {
28b9e94a7bSTiezhu Yang 	return (value / div_factor);
29b9e94a7bSTiezhu Yang }
30b9e94a7bSTiezhu Yang 
kprobe_recursed_target(u32 value)31*1fcd09fdSMasami Hiramatsu (Google) static noinline u32 kprobe_recursed_target(u32 value)
32*1fcd09fdSMasami Hiramatsu (Google) {
33*1fcd09fdSMasami Hiramatsu (Google) 	return (value / div_factor);
34*1fcd09fdSMasami Hiramatsu (Google) }
35*1fcd09fdSMasami Hiramatsu (Google) 
kp_pre_handler(struct kprobe * p,struct pt_regs * regs)36b9e94a7bSTiezhu Yang static int kp_pre_handler(struct kprobe *p, struct pt_regs *regs)
37b9e94a7bSTiezhu Yang {
38b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_FALSE(current_test, preemptible());
39*1fcd09fdSMasami Hiramatsu (Google) 
40*1fcd09fdSMasami Hiramatsu (Google) 	preh_val = recursed_target(rand1);
41b9e94a7bSTiezhu Yang 	return 0;
42b9e94a7bSTiezhu Yang }
43b9e94a7bSTiezhu Yang 
kp_post_handler(struct kprobe * p,struct pt_regs * regs,unsigned long flags)44b9e94a7bSTiezhu Yang static void kp_post_handler(struct kprobe *p, struct pt_regs *regs,
45b9e94a7bSTiezhu Yang 		unsigned long flags)
46b9e94a7bSTiezhu Yang {
47*1fcd09fdSMasami Hiramatsu (Google) 	u32 expval = recursed_target(rand1);
48*1fcd09fdSMasami Hiramatsu (Google) 
49b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_FALSE(current_test, preemptible());
50*1fcd09fdSMasami Hiramatsu (Google) 	KUNIT_EXPECT_EQ(current_test, preh_val, expval);
51*1fcd09fdSMasami Hiramatsu (Google) 
52b9e94a7bSTiezhu Yang 	posth_val = preh_val + div_factor;
53b9e94a7bSTiezhu Yang }
54b9e94a7bSTiezhu Yang 
55b9e94a7bSTiezhu Yang static struct kprobe kp = {
56b9e94a7bSTiezhu Yang 	.symbol_name = "kprobe_target",
57b9e94a7bSTiezhu Yang 	.pre_handler = kp_pre_handler,
58b9e94a7bSTiezhu Yang 	.post_handler = kp_post_handler
59b9e94a7bSTiezhu Yang };
60b9e94a7bSTiezhu Yang 
test_kprobe(struct kunit * test)61b9e94a7bSTiezhu Yang static void test_kprobe(struct kunit *test)
62b9e94a7bSTiezhu Yang {
63b9e94a7bSTiezhu Yang 	current_test = test;
64b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_EQ(test, 0, register_kprobe(&kp));
65b9e94a7bSTiezhu Yang 	target(rand1);
66b9e94a7bSTiezhu Yang 	unregister_kprobe(&kp);
67b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_NE(test, 0, preh_val);
68b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_NE(test, 0, posth_val);
69b9e94a7bSTiezhu Yang }
70b9e94a7bSTiezhu Yang 
kprobe_target2(u32 value)71b9e94a7bSTiezhu Yang static noinline u32 kprobe_target2(u32 value)
72b9e94a7bSTiezhu Yang {
73b9e94a7bSTiezhu Yang 	return (value / div_factor) + 1;
74b9e94a7bSTiezhu Yang }
75b9e94a7bSTiezhu Yang 
kprobe_stacktrace_internal_target(void)76b9e94a7bSTiezhu Yang static noinline unsigned long kprobe_stacktrace_internal_target(void)
77b9e94a7bSTiezhu Yang {
78b9e94a7bSTiezhu Yang 	if (!target_return_address[0])
79b9e94a7bSTiezhu Yang 		target_return_address[0] = (unsigned long)__builtin_return_address(0);
80b9e94a7bSTiezhu Yang 	return target_return_address[0];
81b9e94a7bSTiezhu Yang }
82b9e94a7bSTiezhu Yang 
kprobe_stacktrace_target(void)83b9e94a7bSTiezhu Yang static noinline unsigned long kprobe_stacktrace_target(void)
84b9e94a7bSTiezhu Yang {
85b9e94a7bSTiezhu Yang 	if (!target_return_address[1])
86b9e94a7bSTiezhu Yang 		target_return_address[1] = (unsigned long)__builtin_return_address(0);
87b9e94a7bSTiezhu Yang 
88b9e94a7bSTiezhu Yang 	if (internal_target)
89b9e94a7bSTiezhu Yang 		internal_target();
90b9e94a7bSTiezhu Yang 
91b9e94a7bSTiezhu Yang 	return target_return_address[1];
92b9e94a7bSTiezhu Yang }
93b9e94a7bSTiezhu Yang 
kprobe_stacktrace_driver(void)94b9e94a7bSTiezhu Yang static noinline unsigned long kprobe_stacktrace_driver(void)
95b9e94a7bSTiezhu Yang {
96b9e94a7bSTiezhu Yang 	if (stacktrace_target)
97b9e94a7bSTiezhu Yang 		stacktrace_target();
98b9e94a7bSTiezhu Yang 
99b9e94a7bSTiezhu Yang 	/* This is for preventing inlining the function */
100b9e94a7bSTiezhu Yang 	return (unsigned long)__builtin_return_address(0);
101b9e94a7bSTiezhu Yang }
102b9e94a7bSTiezhu Yang 
kp_pre_handler2(struct kprobe * p,struct pt_regs * regs)103b9e94a7bSTiezhu Yang static int kp_pre_handler2(struct kprobe *p, struct pt_regs *regs)
104b9e94a7bSTiezhu Yang {
105b9e94a7bSTiezhu Yang 	preh_val = (rand1 / div_factor) + 1;
106b9e94a7bSTiezhu Yang 	return 0;
107b9e94a7bSTiezhu Yang }
108b9e94a7bSTiezhu Yang 
kp_post_handler2(struct kprobe * p,struct pt_regs * regs,unsigned long flags)109b9e94a7bSTiezhu Yang static void kp_post_handler2(struct kprobe *p, struct pt_regs *regs,
110b9e94a7bSTiezhu Yang 		unsigned long flags)
111b9e94a7bSTiezhu Yang {
112b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_EQ(current_test, preh_val, (rand1 / div_factor) + 1);
113b9e94a7bSTiezhu Yang 	posth_val = preh_val + div_factor;
114b9e94a7bSTiezhu Yang }
115b9e94a7bSTiezhu Yang 
116b9e94a7bSTiezhu Yang static struct kprobe kp2 = {
117b9e94a7bSTiezhu Yang 	.symbol_name = "kprobe_target2",
118b9e94a7bSTiezhu Yang 	.pre_handler = kp_pre_handler2,
119b9e94a7bSTiezhu Yang 	.post_handler = kp_post_handler2
120b9e94a7bSTiezhu Yang };
121b9e94a7bSTiezhu Yang 
test_kprobes(struct kunit * test)122b9e94a7bSTiezhu Yang static void test_kprobes(struct kunit *test)
123b9e94a7bSTiezhu Yang {
124b9e94a7bSTiezhu Yang 	struct kprobe *kps[2] = {&kp, &kp2};
125b9e94a7bSTiezhu Yang 
126b9e94a7bSTiezhu Yang 	current_test = test;
127b9e94a7bSTiezhu Yang 
128b9e94a7bSTiezhu Yang 	/* addr and flags should be cleard for reusing kprobe. */
129b9e94a7bSTiezhu Yang 	kp.addr = NULL;
130b9e94a7bSTiezhu Yang 	kp.flags = 0;
131b9e94a7bSTiezhu Yang 
132b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_EQ(test, 0, register_kprobes(kps, 2));
133b9e94a7bSTiezhu Yang 	preh_val = 0;
134b9e94a7bSTiezhu Yang 	posth_val = 0;
135b9e94a7bSTiezhu Yang 	target(rand1);
136b9e94a7bSTiezhu Yang 
137b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_NE(test, 0, preh_val);
138b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_NE(test, 0, posth_val);
139b9e94a7bSTiezhu Yang 
140b9e94a7bSTiezhu Yang 	preh_val = 0;
141b9e94a7bSTiezhu Yang 	posth_val = 0;
142b9e94a7bSTiezhu Yang 	target2(rand1);
143b9e94a7bSTiezhu Yang 
144b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_NE(test, 0, preh_val);
145b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_NE(test, 0, posth_val);
146b9e94a7bSTiezhu Yang 	unregister_kprobes(kps, 2);
147b9e94a7bSTiezhu Yang }
148b9e94a7bSTiezhu Yang 
149*1fcd09fdSMasami Hiramatsu (Google) static struct kprobe kp_missed = {
150*1fcd09fdSMasami Hiramatsu (Google) 	.symbol_name = "kprobe_recursed_target",
151*1fcd09fdSMasami Hiramatsu (Google) 	.pre_handler = kp_pre_handler,
152*1fcd09fdSMasami Hiramatsu (Google) 	.post_handler = kp_post_handler,
153*1fcd09fdSMasami Hiramatsu (Google) };
154*1fcd09fdSMasami Hiramatsu (Google) 
test_kprobe_missed(struct kunit * test)155*1fcd09fdSMasami Hiramatsu (Google) static void test_kprobe_missed(struct kunit *test)
156*1fcd09fdSMasami Hiramatsu (Google) {
157*1fcd09fdSMasami Hiramatsu (Google) 	current_test = test;
158*1fcd09fdSMasami Hiramatsu (Google) 	preh_val = 0;
159*1fcd09fdSMasami Hiramatsu (Google) 	posth_val = 0;
160*1fcd09fdSMasami Hiramatsu (Google) 
161*1fcd09fdSMasami Hiramatsu (Google) 	KUNIT_EXPECT_EQ(test, 0, register_kprobe(&kp_missed));
162*1fcd09fdSMasami Hiramatsu (Google) 
163*1fcd09fdSMasami Hiramatsu (Google) 	recursed_target(rand1);
164*1fcd09fdSMasami Hiramatsu (Google) 
165*1fcd09fdSMasami Hiramatsu (Google) 	KUNIT_EXPECT_EQ(test, 2, kp_missed.nmissed);
166*1fcd09fdSMasami Hiramatsu (Google) 	KUNIT_EXPECT_NE(test, 0, preh_val);
167*1fcd09fdSMasami Hiramatsu (Google) 	KUNIT_EXPECT_NE(test, 0, posth_val);
168*1fcd09fdSMasami Hiramatsu (Google) 
169*1fcd09fdSMasami Hiramatsu (Google) 	unregister_kprobe(&kp_missed);
170*1fcd09fdSMasami Hiramatsu (Google) }
171*1fcd09fdSMasami Hiramatsu (Google) 
172b9e94a7bSTiezhu Yang #ifdef CONFIG_KRETPROBES
173b9e94a7bSTiezhu Yang static u32 krph_val;
174b9e94a7bSTiezhu Yang 
entry_handler(struct kretprobe_instance * ri,struct pt_regs * regs)175b9e94a7bSTiezhu Yang static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
176b9e94a7bSTiezhu Yang {
177b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_FALSE(current_test, preemptible());
178b9e94a7bSTiezhu Yang 	krph_val = (rand1 / div_factor);
179b9e94a7bSTiezhu Yang 	return 0;
180b9e94a7bSTiezhu Yang }
181b9e94a7bSTiezhu Yang 
return_handler(struct kretprobe_instance * ri,struct pt_regs * regs)182b9e94a7bSTiezhu Yang static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
183b9e94a7bSTiezhu Yang {
184b9e94a7bSTiezhu Yang 	unsigned long ret = regs_return_value(regs);
185b9e94a7bSTiezhu Yang 
186b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_FALSE(current_test, preemptible());
187b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_EQ(current_test, ret, rand1 / div_factor);
188b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_NE(current_test, krph_val, 0);
189b9e94a7bSTiezhu Yang 	krph_val = rand1;
190b9e94a7bSTiezhu Yang 	return 0;
191b9e94a7bSTiezhu Yang }
192b9e94a7bSTiezhu Yang 
193b9e94a7bSTiezhu Yang static struct kretprobe rp = {
194b9e94a7bSTiezhu Yang 	.handler	= return_handler,
195b9e94a7bSTiezhu Yang 	.entry_handler  = entry_handler,
196b9e94a7bSTiezhu Yang 	.kp.symbol_name = "kprobe_target"
197b9e94a7bSTiezhu Yang };
198b9e94a7bSTiezhu Yang 
test_kretprobe(struct kunit * test)199b9e94a7bSTiezhu Yang static void test_kretprobe(struct kunit *test)
200b9e94a7bSTiezhu Yang {
201b9e94a7bSTiezhu Yang 	current_test = test;
202b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_EQ(test, 0, register_kretprobe(&rp));
203b9e94a7bSTiezhu Yang 	target(rand1);
204b9e94a7bSTiezhu Yang 	unregister_kretprobe(&rp);
205b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_EQ(test, krph_val, rand1);
206b9e94a7bSTiezhu Yang }
207b9e94a7bSTiezhu Yang 
return_handler2(struct kretprobe_instance * ri,struct pt_regs * regs)208b9e94a7bSTiezhu Yang static int return_handler2(struct kretprobe_instance *ri, struct pt_regs *regs)
209b9e94a7bSTiezhu Yang {
210b9e94a7bSTiezhu Yang 	unsigned long ret = regs_return_value(regs);
211b9e94a7bSTiezhu Yang 
212b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_EQ(current_test, ret, (rand1 / div_factor) + 1);
213b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_NE(current_test, krph_val, 0);
214b9e94a7bSTiezhu Yang 	krph_val = rand1;
215b9e94a7bSTiezhu Yang 	return 0;
216b9e94a7bSTiezhu Yang }
217b9e94a7bSTiezhu Yang 
218b9e94a7bSTiezhu Yang static struct kretprobe rp2 = {
219b9e94a7bSTiezhu Yang 	.handler	= return_handler2,
220b9e94a7bSTiezhu Yang 	.entry_handler  = entry_handler,
221b9e94a7bSTiezhu Yang 	.kp.symbol_name = "kprobe_target2"
222b9e94a7bSTiezhu Yang };
223b9e94a7bSTiezhu Yang 
test_kretprobes(struct kunit * test)224b9e94a7bSTiezhu Yang static void test_kretprobes(struct kunit *test)
225b9e94a7bSTiezhu Yang {
226b9e94a7bSTiezhu Yang 	struct kretprobe *rps[2] = {&rp, &rp2};
227b9e94a7bSTiezhu Yang 
228b9e94a7bSTiezhu Yang 	current_test = test;
229b9e94a7bSTiezhu Yang 	/* addr and flags should be cleard for reusing kprobe. */
230b9e94a7bSTiezhu Yang 	rp.kp.addr = NULL;
231b9e94a7bSTiezhu Yang 	rp.kp.flags = 0;
232b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_EQ(test, 0, register_kretprobes(rps, 2));
233b9e94a7bSTiezhu Yang 
234b9e94a7bSTiezhu Yang 	krph_val = 0;
235b9e94a7bSTiezhu Yang 	target(rand1);
236b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_EQ(test, krph_val, rand1);
237b9e94a7bSTiezhu Yang 
238b9e94a7bSTiezhu Yang 	krph_val = 0;
239b9e94a7bSTiezhu Yang 	target2(rand1);
240b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_EQ(test, krph_val, rand1);
241b9e94a7bSTiezhu Yang 	unregister_kretprobes(rps, 2);
242b9e94a7bSTiezhu Yang }
243b9e94a7bSTiezhu Yang 
244b9e94a7bSTiezhu Yang #ifdef CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE
245b9e94a7bSTiezhu Yang #define STACK_BUF_SIZE 16
246b9e94a7bSTiezhu Yang static unsigned long stack_buf[STACK_BUF_SIZE];
247b9e94a7bSTiezhu Yang 
stacktrace_return_handler(struct kretprobe_instance * ri,struct pt_regs * regs)248b9e94a7bSTiezhu Yang static int stacktrace_return_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
249b9e94a7bSTiezhu Yang {
250b9e94a7bSTiezhu Yang 	unsigned long retval = regs_return_value(regs);
251b9e94a7bSTiezhu Yang 	int i, ret;
252b9e94a7bSTiezhu Yang 
253b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_FALSE(current_test, preemptible());
254b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_EQ(current_test, retval, target_return_address[1]);
255b9e94a7bSTiezhu Yang 
256b9e94a7bSTiezhu Yang 	/*
257b9e94a7bSTiezhu Yang 	 * Test stacktrace inside the kretprobe handler, this will involves
258b9e94a7bSTiezhu Yang 	 * kretprobe trampoline, but must include correct return address
259b9e94a7bSTiezhu Yang 	 * of the target function.
260b9e94a7bSTiezhu Yang 	 */
261b9e94a7bSTiezhu Yang 	ret = stack_trace_save(stack_buf, STACK_BUF_SIZE, 0);
262b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_NE(current_test, ret, 0);
263b9e94a7bSTiezhu Yang 
264b9e94a7bSTiezhu Yang 	for (i = 0; i < ret; i++) {
265b9e94a7bSTiezhu Yang 		if (stack_buf[i] == target_return_address[1])
266b9e94a7bSTiezhu Yang 			break;
267b9e94a7bSTiezhu Yang 	}
268b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_NE(current_test, i, ret);
269b9e94a7bSTiezhu Yang 
270b9e94a7bSTiezhu Yang #if !IS_MODULE(CONFIG_KPROBES_SANITY_TEST)
271b9e94a7bSTiezhu Yang 	/*
272b9e94a7bSTiezhu Yang 	 * Test stacktrace from pt_regs at the return address. Thus the stack
273b9e94a7bSTiezhu Yang 	 * trace must start from the target return address.
274b9e94a7bSTiezhu Yang 	 */
275b9e94a7bSTiezhu Yang 	ret = stack_trace_save_regs(regs, stack_buf, STACK_BUF_SIZE, 0);
276b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_NE(current_test, ret, 0);
277b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_EQ(current_test, stack_buf[0], target_return_address[1]);
278b9e94a7bSTiezhu Yang #endif
279b9e94a7bSTiezhu Yang 
280b9e94a7bSTiezhu Yang 	return 0;
281b9e94a7bSTiezhu Yang }
282b9e94a7bSTiezhu Yang 
283b9e94a7bSTiezhu Yang static struct kretprobe rp3 = {
284b9e94a7bSTiezhu Yang 	.handler	= stacktrace_return_handler,
285b9e94a7bSTiezhu Yang 	.kp.symbol_name = "kprobe_stacktrace_target"
286b9e94a7bSTiezhu Yang };
287b9e94a7bSTiezhu Yang 
test_stacktrace_on_kretprobe(struct kunit * test)288b9e94a7bSTiezhu Yang static void test_stacktrace_on_kretprobe(struct kunit *test)
289b9e94a7bSTiezhu Yang {
290b9e94a7bSTiezhu Yang 	unsigned long myretaddr = (unsigned long)__builtin_return_address(0);
291b9e94a7bSTiezhu Yang 
292b9e94a7bSTiezhu Yang 	current_test = test;
293b9e94a7bSTiezhu Yang 	rp3.kp.addr = NULL;
294b9e94a7bSTiezhu Yang 	rp3.kp.flags = 0;
295b9e94a7bSTiezhu Yang 
296b9e94a7bSTiezhu Yang 	/*
297b9e94a7bSTiezhu Yang 	 * Run the stacktrace_driver() to record correct return address in
298b9e94a7bSTiezhu Yang 	 * stacktrace_target() and ensure stacktrace_driver() call is not
299b9e94a7bSTiezhu Yang 	 * inlined by checking the return address of stacktrace_driver()
300b9e94a7bSTiezhu Yang 	 * and the return address of this function is different.
301b9e94a7bSTiezhu Yang 	 */
302b9e94a7bSTiezhu Yang 	KUNIT_ASSERT_NE(test, myretaddr, stacktrace_driver());
303b9e94a7bSTiezhu Yang 
304b9e94a7bSTiezhu Yang 	KUNIT_ASSERT_EQ(test, 0, register_kretprobe(&rp3));
305b9e94a7bSTiezhu Yang 	KUNIT_ASSERT_NE(test, myretaddr, stacktrace_driver());
306b9e94a7bSTiezhu Yang 	unregister_kretprobe(&rp3);
307b9e94a7bSTiezhu Yang }
308b9e94a7bSTiezhu Yang 
stacktrace_internal_return_handler(struct kretprobe_instance * ri,struct pt_regs * regs)309b9e94a7bSTiezhu Yang static int stacktrace_internal_return_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
310b9e94a7bSTiezhu Yang {
311b9e94a7bSTiezhu Yang 	unsigned long retval = regs_return_value(regs);
312b9e94a7bSTiezhu Yang 	int i, ret;
313b9e94a7bSTiezhu Yang 
314b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_FALSE(current_test, preemptible());
315b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_EQ(current_test, retval, target_return_address[0]);
316b9e94a7bSTiezhu Yang 
317b9e94a7bSTiezhu Yang 	/*
318b9e94a7bSTiezhu Yang 	 * Test stacktrace inside the kretprobe handler for nested case.
319b9e94a7bSTiezhu Yang 	 * The unwinder will find the kretprobe_trampoline address on the
320b9e94a7bSTiezhu Yang 	 * return address, and kretprobe must solve that.
321b9e94a7bSTiezhu Yang 	 */
322b9e94a7bSTiezhu Yang 	ret = stack_trace_save(stack_buf, STACK_BUF_SIZE, 0);
323b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_NE(current_test, ret, 0);
324b9e94a7bSTiezhu Yang 
325b9e94a7bSTiezhu Yang 	for (i = 0; i < ret - 1; i++) {
326b9e94a7bSTiezhu Yang 		if (stack_buf[i] == target_return_address[0]) {
327b9e94a7bSTiezhu Yang 			KUNIT_EXPECT_EQ(current_test, stack_buf[i + 1], target_return_address[1]);
328b9e94a7bSTiezhu Yang 			break;
329b9e94a7bSTiezhu Yang 		}
330b9e94a7bSTiezhu Yang 	}
331b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_NE(current_test, i, ret);
332b9e94a7bSTiezhu Yang 
333b9e94a7bSTiezhu Yang #if !IS_MODULE(CONFIG_KPROBES_SANITY_TEST)
334b9e94a7bSTiezhu Yang 	/* Ditto for the regs version. */
335b9e94a7bSTiezhu Yang 	ret = stack_trace_save_regs(regs, stack_buf, STACK_BUF_SIZE, 0);
336b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_NE(current_test, ret, 0);
337b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_EQ(current_test, stack_buf[0], target_return_address[0]);
338b9e94a7bSTiezhu Yang 	KUNIT_EXPECT_EQ(current_test, stack_buf[1], target_return_address[1]);
339b9e94a7bSTiezhu Yang #endif
340b9e94a7bSTiezhu Yang 
341b9e94a7bSTiezhu Yang 	return 0;
342b9e94a7bSTiezhu Yang }
343b9e94a7bSTiezhu Yang 
344b9e94a7bSTiezhu Yang static struct kretprobe rp4 = {
345b9e94a7bSTiezhu Yang 	.handler	= stacktrace_internal_return_handler,
346b9e94a7bSTiezhu Yang 	.kp.symbol_name = "kprobe_stacktrace_internal_target"
347b9e94a7bSTiezhu Yang };
348b9e94a7bSTiezhu Yang 
test_stacktrace_on_nested_kretprobe(struct kunit * test)349b9e94a7bSTiezhu Yang static void test_stacktrace_on_nested_kretprobe(struct kunit *test)
350b9e94a7bSTiezhu Yang {
351b9e94a7bSTiezhu Yang 	unsigned long myretaddr = (unsigned long)__builtin_return_address(0);
352b9e94a7bSTiezhu Yang 	struct kretprobe *rps[2] = {&rp3, &rp4};
353b9e94a7bSTiezhu Yang 
354b9e94a7bSTiezhu Yang 	current_test = test;
355b9e94a7bSTiezhu Yang 	rp3.kp.addr = NULL;
356b9e94a7bSTiezhu Yang 	rp3.kp.flags = 0;
357b9e94a7bSTiezhu Yang 
358b9e94a7bSTiezhu Yang 	//KUNIT_ASSERT_NE(test, myretaddr, stacktrace_driver());
359b9e94a7bSTiezhu Yang 
360b9e94a7bSTiezhu Yang 	KUNIT_ASSERT_EQ(test, 0, register_kretprobes(rps, 2));
361b9e94a7bSTiezhu Yang 	KUNIT_ASSERT_NE(test, myretaddr, stacktrace_driver());
362b9e94a7bSTiezhu Yang 	unregister_kretprobes(rps, 2);
363b9e94a7bSTiezhu Yang }
364b9e94a7bSTiezhu Yang #endif /* CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE */
365b9e94a7bSTiezhu Yang 
366b9e94a7bSTiezhu Yang #endif /* CONFIG_KRETPROBES */
367b9e94a7bSTiezhu Yang 
kprobes_test_init(struct kunit * test)368b9e94a7bSTiezhu Yang static int kprobes_test_init(struct kunit *test)
369b9e94a7bSTiezhu Yang {
370b9e94a7bSTiezhu Yang 	target = kprobe_target;
371b9e94a7bSTiezhu Yang 	target2 = kprobe_target2;
372*1fcd09fdSMasami Hiramatsu (Google) 	recursed_target = kprobe_recursed_target;
373b9e94a7bSTiezhu Yang 	stacktrace_target = kprobe_stacktrace_target;
374b9e94a7bSTiezhu Yang 	internal_target = kprobe_stacktrace_internal_target;
375b9e94a7bSTiezhu Yang 	stacktrace_driver = kprobe_stacktrace_driver;
376d247aabdSJason A. Donenfeld 	rand1 = get_random_u32_above(div_factor);
377b9e94a7bSTiezhu Yang 	return 0;
378b9e94a7bSTiezhu Yang }
379b9e94a7bSTiezhu Yang 
380b9e94a7bSTiezhu Yang static struct kunit_case kprobes_testcases[] = {
381b9e94a7bSTiezhu Yang 	KUNIT_CASE(test_kprobe),
382b9e94a7bSTiezhu Yang 	KUNIT_CASE(test_kprobes),
383*1fcd09fdSMasami Hiramatsu (Google) 	KUNIT_CASE(test_kprobe_missed),
384b9e94a7bSTiezhu Yang #ifdef CONFIG_KRETPROBES
385b9e94a7bSTiezhu Yang 	KUNIT_CASE(test_kretprobe),
386b9e94a7bSTiezhu Yang 	KUNIT_CASE(test_kretprobes),
387b9e94a7bSTiezhu Yang #ifdef CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE
388b9e94a7bSTiezhu Yang 	KUNIT_CASE(test_stacktrace_on_kretprobe),
389b9e94a7bSTiezhu Yang 	KUNIT_CASE(test_stacktrace_on_nested_kretprobe),
390b9e94a7bSTiezhu Yang #endif
391b9e94a7bSTiezhu Yang #endif
392b9e94a7bSTiezhu Yang 	{}
393b9e94a7bSTiezhu Yang };
394b9e94a7bSTiezhu Yang 
395b9e94a7bSTiezhu Yang static struct kunit_suite kprobes_test_suite = {
396b9e94a7bSTiezhu Yang 	.name = "kprobes_test",
397b9e94a7bSTiezhu Yang 	.init = kprobes_test_init,
398b9e94a7bSTiezhu Yang 	.test_cases = kprobes_testcases,
399b9e94a7bSTiezhu Yang };
400b9e94a7bSTiezhu Yang 
401b9e94a7bSTiezhu Yang kunit_test_suites(&kprobes_test_suite);
402b9e94a7bSTiezhu Yang 
403b9e94a7bSTiezhu Yang MODULE_LICENSE("GPL");
404