Commit 1fcd09fd authored by Masami Hiramatsu (Google)'s avatar Masami Hiramatsu (Google)
Browse files

test_kprobes: Add recursed kprobe test case

Add a recursed kprobe test case to the KUnit test module for kprobes.
This will probe a function which is called from the pre_handler and
post_handler itself. If the kprobe is correctly implemented, the recursed
kprobe handlers will be skipped and the number of skipped kprobe will
be counted on kprobe::nmissed.

Link: https://lore.kernel.org/all/167414238758.2301956.258548940194352895.stgit@devnote3/



Signed-off-by: default avatarMasami Hiramatsu (Google) <mhiramat@kernel.org>
parent 8478cca1
Loading
Loading
Loading
Loading
+37 −2
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@

static u32 rand1, preh_val, posth_val;
static u32 (*target)(u32 value);
static u32 (*recursed_target)(u32 value);
static u32 (*target2)(u32 value);
static struct kunit *current_test;

@@ -27,18 +28,27 @@ static noinline u32 kprobe_target(u32 value)
	return (value / div_factor);
}

static noinline u32 kprobe_recursed_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);

	preh_val = recursed_target(rand1);
	return 0;
}

static void kp_post_handler(struct kprobe *p, struct pt_regs *regs,
		unsigned long flags)
{
	u32 expval = recursed_target(rand1);

	KUNIT_EXPECT_FALSE(current_test, preemptible());
	KUNIT_EXPECT_EQ(current_test, preh_val, (rand1 / div_factor));
	KUNIT_EXPECT_EQ(current_test, preh_val, expval);

	posth_val = preh_val + div_factor;
}

@@ -136,6 +146,29 @@ static void test_kprobes(struct kunit *test)
	unregister_kprobes(kps, 2);
}

static struct kprobe kp_missed = {
	.symbol_name = "kprobe_recursed_target",
	.pre_handler = kp_pre_handler,
	.post_handler = kp_post_handler,
};

static void test_kprobe_missed(struct kunit *test)
{
	current_test = test;
	preh_val = 0;
	posth_val = 0;

	KUNIT_EXPECT_EQ(test, 0, register_kprobe(&kp_missed));

	recursed_target(rand1);

	KUNIT_EXPECT_EQ(test, 2, kp_missed.nmissed);
	KUNIT_EXPECT_NE(test, 0, preh_val);
	KUNIT_EXPECT_NE(test, 0, posth_val);

	unregister_kprobe(&kp_missed);
}

#ifdef CONFIG_KRETPROBES
static u32 krph_val;

@@ -336,6 +369,7 @@ static int kprobes_test_init(struct kunit *test)
{
	target = kprobe_target;
	target2 = kprobe_target2;
	recursed_target = kprobe_recursed_target;
	stacktrace_target = kprobe_stacktrace_target;
	internal_target = kprobe_stacktrace_internal_target;
	stacktrace_driver = kprobe_stacktrace_driver;
@@ -346,6 +380,7 @@ static int kprobes_test_init(struct kunit *test)
static struct kunit_case kprobes_testcases[] = {
	KUNIT_CASE(test_kprobe),
	KUNIT_CASE(test_kprobes),
	KUNIT_CASE(test_kprobe_missed),
#ifdef CONFIG_KRETPROBES
	KUNIT_CASE(test_kretprobe),
	KUNIT_CASE(test_kretprobes),