brintos

brintos / linux-shallow public Read only

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