123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371 |
- #include <linux/kernel.h>
- #include <linux/kprobes.h>
- #include <linux/random.h>
- #include <kunit/test.h>
- #define div_factor 3
- static u32 rand1, preh_val, posth_val;
- static u32 (*target)(u32 value);
- static u32 (*target2)(u32 value);
- static struct kunit *current_test;
- static unsigned long (*internal_target)(void);
- static unsigned long (*stacktrace_target)(void);
- static unsigned long (*stacktrace_driver)(void);
- static unsigned long target_return_address[2];
- static noinline u32 kprobe_target(u32 value)
- {
- return (value / div_factor);
- }
- static int kp_pre_handler(struct kprobe *p, struct pt_regs *regs)
- {
- KUNIT_EXPECT_FALSE(current_test, preemptible());
- preh_val = (rand1 / div_factor);
- return 0;
- }
- static void kp_post_handler(struct kprobe *p, struct pt_regs *regs,
- unsigned long flags)
- {
- KUNIT_EXPECT_FALSE(current_test, preemptible());
- KUNIT_EXPECT_EQ(current_test, preh_val, (rand1 / div_factor));
- posth_val = preh_val + div_factor;
- }
- static struct kprobe kp = {
- .symbol_name = "kprobe_target",
- .pre_handler = kp_pre_handler,
- .post_handler = kp_post_handler
- };
- static void test_kprobe(struct kunit *test)
- {
- current_test = test;
- KUNIT_EXPECT_EQ(test, 0, register_kprobe(&kp));
- target(rand1);
- unregister_kprobe(&kp);
- KUNIT_EXPECT_NE(test, 0, preh_val);
- KUNIT_EXPECT_NE(test, 0, posth_val);
- }
- static noinline u32 kprobe_target2(u32 value)
- {
- return (value / div_factor) + 1;
- }
- static noinline unsigned long kprobe_stacktrace_internal_target(void)
- {
- if (!target_return_address[0])
- target_return_address[0] = (unsigned long)__builtin_return_address(0);
- return target_return_address[0];
- }
- static noinline unsigned long kprobe_stacktrace_target(void)
- {
- if (!target_return_address[1])
- target_return_address[1] = (unsigned long)__builtin_return_address(0);
- if (internal_target)
- internal_target();
- return target_return_address[1];
- }
- static noinline unsigned long kprobe_stacktrace_driver(void)
- {
- if (stacktrace_target)
- stacktrace_target();
-
- return (unsigned long)__builtin_return_address(0);
- }
- static int kp_pre_handler2(struct kprobe *p, struct pt_regs *regs)
- {
- preh_val = (rand1 / div_factor) + 1;
- return 0;
- }
- static void kp_post_handler2(struct kprobe *p, struct pt_regs *regs,
- unsigned long flags)
- {
- KUNIT_EXPECT_EQ(current_test, preh_val, (rand1 / div_factor) + 1);
- posth_val = preh_val + div_factor;
- }
- static struct kprobe kp2 = {
- .symbol_name = "kprobe_target2",
- .pre_handler = kp_pre_handler2,
- .post_handler = kp_post_handler2
- };
- static void test_kprobes(struct kunit *test)
- {
- struct kprobe *kps[2] = {&kp, &kp2};
- current_test = test;
-
- kp.addr = NULL;
- kp.flags = 0;
- KUNIT_EXPECT_EQ(test, 0, register_kprobes(kps, 2));
- preh_val = 0;
- posth_val = 0;
- target(rand1);
- KUNIT_EXPECT_NE(test, 0, preh_val);
- KUNIT_EXPECT_NE(test, 0, posth_val);
- preh_val = 0;
- posth_val = 0;
- target2(rand1);
- KUNIT_EXPECT_NE(test, 0, preh_val);
- KUNIT_EXPECT_NE(test, 0, posth_val);
- unregister_kprobes(kps, 2);
- }
- #ifdef CONFIG_KRETPROBES
- static u32 krph_val;
- static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
- {
- KUNIT_EXPECT_FALSE(current_test, preemptible());
- krph_val = (rand1 / div_factor);
- return 0;
- }
- static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
- {
- unsigned long ret = regs_return_value(regs);
- KUNIT_EXPECT_FALSE(current_test, preemptible());
- KUNIT_EXPECT_EQ(current_test, ret, rand1 / div_factor);
- KUNIT_EXPECT_NE(current_test, krph_val, 0);
- krph_val = rand1;
- return 0;
- }
- static struct kretprobe rp = {
- .handler = return_handler,
- .entry_handler = entry_handler,
- .kp.symbol_name = "kprobe_target"
- };
- static void test_kretprobe(struct kunit *test)
- {
- current_test = test;
- KUNIT_EXPECT_EQ(test, 0, register_kretprobe(&rp));
- target(rand1);
- unregister_kretprobe(&rp);
- KUNIT_EXPECT_EQ(test, krph_val, rand1);
- }
- static int return_handler2(struct kretprobe_instance *ri, struct pt_regs *regs)
- {
- unsigned long ret = regs_return_value(regs);
- KUNIT_EXPECT_EQ(current_test, ret, (rand1 / div_factor) + 1);
- KUNIT_EXPECT_NE(current_test, krph_val, 0);
- krph_val = rand1;
- return 0;
- }
- static struct kretprobe rp2 = {
- .handler = return_handler2,
- .entry_handler = entry_handler,
- .kp.symbol_name = "kprobe_target2"
- };
- static void test_kretprobes(struct kunit *test)
- {
- struct kretprobe *rps[2] = {&rp, &rp2};
- current_test = test;
-
- rp.kp.addr = NULL;
- rp.kp.flags = 0;
- KUNIT_EXPECT_EQ(test, 0, register_kretprobes(rps, 2));
- krph_val = 0;
- target(rand1);
- KUNIT_EXPECT_EQ(test, krph_val, rand1);
- krph_val = 0;
- target2(rand1);
- KUNIT_EXPECT_EQ(test, krph_val, rand1);
- unregister_kretprobes(rps, 2);
- }
- #ifdef CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE
- #define STACK_BUF_SIZE 16
- static unsigned long stack_buf[STACK_BUF_SIZE];
- static int stacktrace_return_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
- {
- unsigned long retval = regs_return_value(regs);
- int i, ret;
- KUNIT_EXPECT_FALSE(current_test, preemptible());
- KUNIT_EXPECT_EQ(current_test, retval, target_return_address[1]);
-
- ret = stack_trace_save(stack_buf, STACK_BUF_SIZE, 0);
- KUNIT_EXPECT_NE(current_test, ret, 0);
- for (i = 0; i < ret; i++) {
- if (stack_buf[i] == target_return_address[1])
- break;
- }
- KUNIT_EXPECT_NE(current_test, i, ret);
- #if !IS_MODULE(CONFIG_KPROBES_SANITY_TEST)
-
- ret = stack_trace_save_regs(regs, stack_buf, STACK_BUF_SIZE, 0);
- KUNIT_EXPECT_NE(current_test, ret, 0);
- KUNIT_EXPECT_EQ(current_test, stack_buf[0], target_return_address[1]);
- #endif
- return 0;
- }
- static struct kretprobe rp3 = {
- .handler = stacktrace_return_handler,
- .kp.symbol_name = "kprobe_stacktrace_target"
- };
- static void test_stacktrace_on_kretprobe(struct kunit *test)
- {
- unsigned long myretaddr = (unsigned long)__builtin_return_address(0);
- current_test = test;
- rp3.kp.addr = NULL;
- rp3.kp.flags = 0;
-
- KUNIT_ASSERT_NE(test, myretaddr, stacktrace_driver());
- KUNIT_ASSERT_EQ(test, 0, register_kretprobe(&rp3));
- KUNIT_ASSERT_NE(test, myretaddr, stacktrace_driver());
- unregister_kretprobe(&rp3);
- }
- static int stacktrace_internal_return_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
- {
- unsigned long retval = regs_return_value(regs);
- int i, ret;
- KUNIT_EXPECT_FALSE(current_test, preemptible());
- KUNIT_EXPECT_EQ(current_test, retval, target_return_address[0]);
-
- ret = stack_trace_save(stack_buf, STACK_BUF_SIZE, 0);
- KUNIT_EXPECT_NE(current_test, ret, 0);
- for (i = 0; i < ret - 1; i++) {
- if (stack_buf[i] == target_return_address[0]) {
- KUNIT_EXPECT_EQ(current_test, stack_buf[i + 1], target_return_address[1]);
- break;
- }
- }
- KUNIT_EXPECT_NE(current_test, i, ret);
- #if !IS_MODULE(CONFIG_KPROBES_SANITY_TEST)
-
- ret = stack_trace_save_regs(regs, stack_buf, STACK_BUF_SIZE, 0);
- KUNIT_EXPECT_NE(current_test, ret, 0);
- KUNIT_EXPECT_EQ(current_test, stack_buf[0], target_return_address[0]);
- KUNIT_EXPECT_EQ(current_test, stack_buf[1], target_return_address[1]);
- #endif
- return 0;
- }
- static struct kretprobe rp4 = {
- .handler = stacktrace_internal_return_handler,
- .kp.symbol_name = "kprobe_stacktrace_internal_target"
- };
- static void test_stacktrace_on_nested_kretprobe(struct kunit *test)
- {
- unsigned long myretaddr = (unsigned long)__builtin_return_address(0);
- struct kretprobe *rps[2] = {&rp3, &rp4};
- current_test = test;
- rp3.kp.addr = NULL;
- rp3.kp.flags = 0;
-
- KUNIT_ASSERT_EQ(test, 0, register_kretprobes(rps, 2));
- KUNIT_ASSERT_NE(test, myretaddr, stacktrace_driver());
- unregister_kretprobes(rps, 2);
- }
- #endif
- #endif
- static int kprobes_test_init(struct kunit *test)
- {
- target = kprobe_target;
- target2 = kprobe_target2;
- stacktrace_target = kprobe_stacktrace_target;
- internal_target = kprobe_stacktrace_internal_target;
- stacktrace_driver = kprobe_stacktrace_driver;
- do {
- rand1 = get_random_u32();
- } while (rand1 <= div_factor);
- return 0;
- }
- static struct kunit_case kprobes_testcases[] = {
- KUNIT_CASE(test_kprobe),
- KUNIT_CASE(test_kprobes),
- #ifdef CONFIG_KRETPROBES
- KUNIT_CASE(test_kretprobe),
- KUNIT_CASE(test_kretprobes),
- #ifdef CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE
- KUNIT_CASE(test_stacktrace_on_kretprobe),
- KUNIT_CASE(test_stacktrace_on_nested_kretprobe),
- #endif
- #endif
- {}
- };
- static struct kunit_suite kprobes_test_suite = {
- .name = "kprobes_test",
- .init = kprobes_test_init,
- .test_cases = kprobes_testcases,
- };
- kunit_test_suites(&kprobes_test_suite);
- MODULE_LICENSE("GPL");
|