cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

test_kprobes.c (9609B)


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