From patchwork Fri Oct 15 12:50:53 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Masami Hiramatsu (Google)" X-Patchwork-Id: 12561443 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 64B9BC433F5 for ; Fri, 15 Oct 2021 12:54:16 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 2A7C56101E for ; Fri, 15 Oct 2021 12:54:16 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 2A7C56101E Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=kernel.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=Rsw+dWgfXQrrnJUkoGwdZtB+qAOg/B2kmnT3gO5uRng=; b=s7aRt18sx8iEH2 tPvVz3TzDqjofcWZzzf//vPDbRH3l0Mbifrb767EoIecFrRGt9nUFwwdoeyVmA0yb44BQWM32BYc+ Fns5wO/qcJyFTkpeZcT9qugIz1lVhOt0KQAc1y5vK7fMh5ogiRpOY5g7wvdlSYigg/HrWaoIJPcRA 2VMARkVqMZYcp8h3bicSjzsgRfEidHV/FAg6FIykd0yIy+8OkkZZzL7TX3Gv/eKtObGoa0EJipnS5 Wa7bGq4GTMi37OzAskcZ7raH59+LRCQlIQwBOUxDknsHk/uiJsm/GSoUg1/OSl0EOgrTm/JzDH5uS 1Gz15q1apdLIS6Yz2ckw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mbMhY-00723i-7S; Fri, 15 Oct 2021 12:52:44 +0000 Received: from mail.kernel.org ([198.145.29.99]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mbMfp-0070vE-3V for linux-arm-kernel@lists.infradead.org; Fri, 15 Oct 2021 12:50:59 +0000 Received: by mail.kernel.org (Postfix) with ESMTPSA id 328FD6101E; Fri, 15 Oct 2021 12:50:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1634302256; bh=tRkVbK/6cQv7N8/Uy5dG+605bsqyOjfX1ZZl/I4J2Kk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=jY4tcRerZcmo4iG7lk3Dog54mqXVPkEoUy2/P9Kyo9CK25u8ogdjRbEvjorKfkRk6 qV3IxvtG8r+lRQb1SGArLvZjFTG+DAvCrIRua373HpFcKdcI9PfvO1nY42oSBJktFd hU8mtPJ9744xFhVZpQO6qaJYYfXfrIvdQmf/wPfCl5ul3VgnZWlFmd09guz3uTWWKM /B7IGOMJThGcoBaS9djVrD5tnGv7/Hs/SS9CU3kTaFTVVS+QOShq1hVQPHwhO9syVT YmEJOiMvqm4uhcZxIrCTfjcVKlixR72yU0kZZzPBpQrs0WY8Z6+G1PlZqzBb+YVHSK rYoqRgLuosksw== From: Masami Hiramatsu To: Steven Rostedt Cc: "Naveen N . Rao" , Ananth N Mavinakayanahalli , Ingo Molnar , linux-kernel@vger.kernel.org, mhiramat@kernel.org, Sven Schnelle , Catalin Marinas , Will Deacon , Russell King , Nathan Chancellor , Nick Desaulniers , linux-arm-kernel@lists.infradead.org Subject: [PATCH 01/10] kprobes: convert tests to kunit Date: Fri, 15 Oct 2021 21:50:53 +0900 Message-Id: <163430225340.459050.2034206177102956567.stgit@devnote2> X-Mailer: git-send-email 2.25.1 In-Reply-To: <163430224341.459050.2369208860773018092.stgit@devnote2> References: <163430224341.459050.2369208860773018092.stgit@devnote2> User-Agent: StGit/0.19 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211015_055057_275720_680477CA X-CRM114-Status: GOOD ( 22.50 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Sven Schnelle This converts the kprobes testcases to use the kunit framework. It adds a dependency on CONFIG_KUNIT, and the output will change to TAP: TAP version 14 1..1 # Subtest: kprobes_test 1..4 random: crng init done ok 1 - test_kprobe ok 2 - test_kprobes ok 3 - test_kretprobe ok 4 - test_kretprobes ok 1 - kprobes_test Note that the kprobes testcases are no longer run immediately after kprobes initialization, but as a late initcall when kunit is initialized. kprobes itself is initialized with an early initcall, so the order is still correct. Signed-off-by: Sven Schnelle Acked-by: Masami Hiramatsu Signed-off-by: Masami Hiramatsu --- kernel/kprobes.c | 3 - kernel/test_kprobes.c | 222 +++++++++++++------------------------------------ lib/Kconfig.debug | 3 - 3 files changed, 61 insertions(+), 167 deletions(-) diff --git a/kernel/kprobes.c b/kernel/kprobes.c index b62af9fc3607..4676627cb066 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -2581,9 +2581,6 @@ static int __init init_kprobes(void) err = register_module_notifier(&kprobe_module_nb); kprobes_initialized = (err == 0); - - if (!err) - init_test_probes(); return err; } early_initcall(init_kprobes); diff --git a/kernel/test_kprobes.c b/kernel/test_kprobes.c index 76c997fdbc9d..e78f18144145 100644 --- a/kernel/test_kprobes.c +++ b/kernel/test_kprobes.c @@ -5,18 +5,17 @@ * Copyright IBM Corp. 2008 */ -#define pr_fmt(fmt) "Kprobe smoke test: " fmt - #include #include #include +#include #define div_factor 3 static u32 rand1, preh_val, posth_val; -static int errors, handler_errors, num_tests; static u32 (*target)(u32 value); static u32 (*target2)(u32 value); +static struct kunit *current_test; static noinline u32 kprobe_target(u32 value) { @@ -25,10 +24,7 @@ static noinline u32 kprobe_target(u32 value) static int kp_pre_handler(struct kprobe *p, struct pt_regs *regs) { - if (preemptible()) { - handler_errors++; - pr_err("pre-handler is preemptible\n"); - } + KUNIT_EXPECT_FALSE(current_test, preemptible()); preh_val = (rand1 / div_factor); return 0; } @@ -36,14 +32,8 @@ static int kp_pre_handler(struct kprobe *p, struct pt_regs *regs) static void kp_post_handler(struct kprobe *p, struct pt_regs *regs, unsigned long flags) { - if (preemptible()) { - handler_errors++; - pr_err("post-handler is preemptible\n"); - } - if (preh_val != (rand1 / div_factor)) { - handler_errors++; - pr_err("incorrect value in post_handler\n"); - } + KUNIT_EXPECT_FALSE(current_test, preemptible()); + KUNIT_EXPECT_EQ(current_test, preh_val, (rand1 / div_factor)); posth_val = preh_val + div_factor; } @@ -53,30 +43,14 @@ static struct kprobe kp = { .post_handler = kp_post_handler }; -static int test_kprobe(void) +static void test_kprobe(struct kunit *test) { - int ret; - - ret = register_kprobe(&kp); - if (ret < 0) { - pr_err("register_kprobe returned %d\n", ret); - return ret; - } - - ret = target(rand1); + current_test = test; + KUNIT_EXPECT_EQ(test, 0, register_kprobe(&kp)); + target(rand1); unregister_kprobe(&kp); - - if (preh_val == 0) { - pr_err("kprobe pre_handler not called\n"); - handler_errors++; - } - - if (posth_val == 0) { - pr_err("kprobe post_handler not called\n"); - handler_errors++; - } - - return 0; + KUNIT_EXPECT_NE(test, 0, preh_val); + KUNIT_EXPECT_NE(test, 0, posth_val); } static noinline u32 kprobe_target2(u32 value) @@ -93,10 +67,7 @@ static int kp_pre_handler2(struct kprobe *p, struct pt_regs *regs) static void kp_post_handler2(struct kprobe *p, struct pt_regs *regs, unsigned long flags) { - if (preh_val != (rand1 / div_factor) + 1) { - handler_errors++; - pr_err("incorrect value in post_handler2\n"); - } + KUNIT_EXPECT_EQ(current_test, preh_val, (rand1 / div_factor) + 1); posth_val = preh_val + div_factor; } @@ -106,51 +77,31 @@ static struct kprobe kp2 = { .post_handler = kp_post_handler2 }; -static int test_kprobes(void) +static void test_kprobes(struct kunit *test) { - int ret; struct kprobe *kps[2] = {&kp, &kp2}; + current_test = test; + /* addr and flags should be cleard for reusing kprobe. */ kp.addr = NULL; kp.flags = 0; - ret = register_kprobes(kps, 2); - if (ret < 0) { - pr_err("register_kprobes returned %d\n", ret); - return ret; - } + KUNIT_EXPECT_EQ(test, 0, register_kprobes(kps, 2)); preh_val = 0; posth_val = 0; - ret = target(rand1); + target(rand1); - if (preh_val == 0) { - pr_err("kprobe pre_handler not called\n"); - handler_errors++; - } - - if (posth_val == 0) { - pr_err("kprobe post_handler not called\n"); - handler_errors++; - } + KUNIT_EXPECT_NE(test, 0, preh_val); + KUNIT_EXPECT_NE(test, 0, posth_val); preh_val = 0; posth_val = 0; - ret = target2(rand1); - - if (preh_val == 0) { - pr_err("kprobe pre_handler2 not called\n"); - handler_errors++; - } - - if (posth_val == 0) { - pr_err("kprobe post_handler2 not called\n"); - handler_errors++; - } + target2(rand1); + KUNIT_EXPECT_NE(test, 0, preh_val); + KUNIT_EXPECT_NE(test, 0, posth_val); unregister_kprobes(kps, 2); - return 0; - } #ifdef CONFIG_KRETPROBES @@ -158,10 +109,7 @@ static u32 krph_val; static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs) { - if (preemptible()) { - handler_errors++; - pr_err("kretprobe entry handler is preemptible\n"); - } + KUNIT_EXPECT_FALSE(current_test, preemptible()); krph_val = (rand1 / div_factor); return 0; } @@ -170,19 +118,9 @@ static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs) { unsigned long ret = regs_return_value(regs); - if (preemptible()) { - handler_errors++; - pr_err("kretprobe return handler is preemptible\n"); - } - if (ret != (rand1 / div_factor)) { - handler_errors++; - pr_err("incorrect value in kretprobe handler\n"); - } - if (krph_val == 0) { - handler_errors++; - pr_err("call to kretprobe entry handler failed\n"); - } - + 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; } @@ -193,39 +131,21 @@ static struct kretprobe rp = { .kp.symbol_name = "kprobe_target" }; -static int test_kretprobe(void) +static void test_kretprobe(struct kunit *test) { - int ret; - - ret = register_kretprobe(&rp); - if (ret < 0) { - pr_err("register_kretprobe returned %d\n", ret); - return ret; - } - - ret = target(rand1); + current_test = test; + KUNIT_EXPECT_EQ(test, 0, register_kretprobe(&rp)); + target(rand1); unregister_kretprobe(&rp); - if (krph_val != rand1) { - pr_err("kretprobe handler not called\n"); - handler_errors++; - } - - return 0; + 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); - if (ret != (rand1 / div_factor) + 1) { - handler_errors++; - pr_err("incorrect value in kretprobe handler2\n"); - } - if (krph_val == 0) { - handler_errors++; - pr_err("call to kretprobe entry handler failed\n"); - } - + KUNIT_EXPECT_EQ(current_test, ret, (rand1 / div_factor) + 1); + KUNIT_EXPECT_NE(current_test, krph_val, 0); krph_val = rand1; return 0; } @@ -236,78 +156,54 @@ static struct kretprobe rp2 = { .kp.symbol_name = "kprobe_target2" }; -static int test_kretprobes(void) +static void test_kretprobes(struct kunit *test) { - int ret; struct kretprobe *rps[2] = {&rp, &rp2}; + current_test = test; /* addr and flags should be cleard for reusing kprobe. */ rp.kp.addr = NULL; rp.kp.flags = 0; - ret = register_kretprobes(rps, 2); - if (ret < 0) { - pr_err("register_kretprobe returned %d\n", ret); - return ret; - } + KUNIT_EXPECT_EQ(test, 0, register_kretprobes(rps, 2)); krph_val = 0; - ret = target(rand1); - if (krph_val != rand1) { - pr_err("kretprobe handler not called\n"); - handler_errors++; - } + target(rand1); + KUNIT_EXPECT_EQ(test, krph_val, rand1); krph_val = 0; - ret = target2(rand1); - if (krph_val != rand1) { - pr_err("kretprobe handler2 not called\n"); - handler_errors++; - } + target2(rand1); + KUNIT_EXPECT_EQ(test, krph_val, rand1); unregister_kretprobes(rps, 2); - return 0; } #endif /* CONFIG_KRETPROBES */ -int init_test_probes(void) +static int kprobes_test_init(struct kunit *test) { - int ret; - target = kprobe_target; target2 = kprobe_target2; do { rand1 = prandom_u32(); } while (rand1 <= div_factor); + return 0; +} - pr_info("started\n"); - num_tests++; - ret = test_kprobe(); - if (ret < 0) - errors++; - - num_tests++; - ret = test_kprobes(); - if (ret < 0) - errors++; - +static struct kunit_case kprobes_testcases[] = { + KUNIT_CASE(test_kprobe), + KUNIT_CASE(test_kprobes), #ifdef CONFIG_KRETPROBES - num_tests++; - ret = test_kretprobe(); - if (ret < 0) - errors++; - - num_tests++; - ret = test_kretprobes(); - if (ret < 0) - errors++; -#endif /* CONFIG_KRETPROBES */ + KUNIT_CASE(test_kretprobe), + KUNIT_CASE(test_kretprobes), +#endif + {} +}; - if (errors) - pr_err("BUG: %d out of %d tests failed\n", errors, num_tests); - else if (handler_errors) - pr_err("BUG: %d error(s) running handlers\n", handler_errors); - else - pr_info("passed successfully\n"); +static struct kunit_suite kprobes_test_suite = { + .name = "kprobes_test", + .init = kprobes_test_init, + .test_cases = kprobes_testcases, +}; - return 0; -} +kunit_test_suites(&kprobes_test_suite); + +MODULE_LICENSE("GPL"); diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 2a9b6dcdac4f..6ceb11a43e4c 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -2080,9 +2080,10 @@ config TEST_DIV64 If unsure, say N. config KPROBES_SANITY_TEST - bool "Kprobes sanity tests" + tristate "Kprobes sanity tests" depends on DEBUG_KERNEL depends on KPROBES + depends on KUNIT help This option provides for testing basic kprobes functionality on boot. Samples of kprobe and kretprobe are inserted and From patchwork Fri Oct 15 12:51:02 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Masami Hiramatsu (Google)" X-Patchwork-Id: 12561445 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 74092C433F5 for ; Fri, 15 Oct 2021 12:55:10 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 3EB116101E for ; Fri, 15 Oct 2021 12:55:10 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 3EB116101E Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=kernel.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=ZlRtBAVK6tgLJbanmr3HE7E8rqB5kOJMgKbw3pwZLJU=; b=pk1QMVcVpRgnvP m6TAISGQwFKCnrZSYnL4dpkAofL0srMAyn/kmekusDBnhuqSfKXRRh+dChsF9GhRVRIiXbmrpLYBa mRs5RAEjDa2WGoq7IYRvdgQ39TB5PMnyI4sDn2J7PbMgPtNG49tTTrk2Wnnz0qkpE6jhiW/BU+uFa U36R2p7Zs+L9+NtJvJv+dZkhkcvdz7TC1XZTGlkdvR5A3R7ODyKmprUdF2AfF945UqqtZIvAaGIV4 Htmq2mRRgD/cpiJ3g/+FfUTuK2E6m0BiHGnbvPRhfnob1h31SGMZm4fdQ56nes6nr8zJIjnnv63Wn YSB8Zo8kTe943sa+jABQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mbMiC-0072Tn-BV; Fri, 15 Oct 2021 12:53:24 +0000 Received: from mail.kernel.org ([198.145.29.99]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mbMfx-00710E-Dv for linux-arm-kernel@lists.infradead.org; Fri, 15 Oct 2021 12:51:07 +0000 Received: by mail.kernel.org (Postfix) with ESMTPSA id 79F0D60ED4; Fri, 15 Oct 2021 12:51:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1634302265; bh=niYdGlhnIOnlqO9uKbzVe3OozoWdJl8BUi/pR8B1qg4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ZH8JpWOr8Z1W1spY7vq9mKn4c82ctEym+xYt16Nx2bxK5wkxDdchbWrPIv9KVkc1g +xPlX3gfI1pF+wdZ/Av8SlvuFsuKK3xxytgvImMJzjU0h/trcbrN0BLX6ToJiN32Wp aaRa6BRX77F2gUIZ+xouGT4awOWApCzH40HM2EgLcwq/6rrVccPTCLD3JnmUjEYLpL wALgOXfI7w6EIryaFYRnjxqa9rrpM7gADXiNpzB0Kq76bPp1KlVCF0WV8+Z+DmbUxw oydcbXCLrJTI1VIvaRYzCnFnStjM03dweWb4NUyJ7x5VYKna2wyqYKsKpkvX82oPlm ch3UXH7iruvEg== From: Masami Hiramatsu To: Steven Rostedt Cc: "Naveen N . Rao" , Ananth N Mavinakayanahalli , Ingo Molnar , linux-kernel@vger.kernel.org, mhiramat@kernel.org, Sven Schnelle , Catalin Marinas , Will Deacon , Russell King , Nathan Chancellor , Nick Desaulniers , linux-arm-kernel@lists.infradead.org Subject: [PATCH 02/10] kprobes: Add a test case for stacktrace from kretprobe handler Date: Fri, 15 Oct 2021 21:51:02 +0900 Message-Id: <163430226192.459050.1792956015201221263.stgit@devnote2> X-Mailer: git-send-email 2.25.1 In-Reply-To: <163430224341.459050.2369208860773018092.stgit@devnote2> References: <163430224341.459050.2369208860773018092.stgit@devnote2> User-Agent: StGit/0.19 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211015_055105_557038_DBA1D627 X-CRM114-Status: GOOD ( 24.15 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add a test case for stacktrace from kretprobe handler and nested kretprobe handlers. This test checks both of stack trace inside kretprobe handler and stack trace from pt_regs. Those stack trace must include actual function return address instead of kretprobe trampoline. The nested kretprobe stacktrace test checks whether the unwinder can correctly unwind the call frame on the stack which has been modified by the kretprobe. Since the stacktrace on kretprobe is correctly fixed only on x86, this introduces a meta kconfig ARCH_CORRECT_STACKTRACE_ON_KRETPROBE which tells user that the stacktrace on kretprobe is correct or not. The test results will be shown like below; TAP version 14 1..1 # Subtest: kprobes_test 1..6 ok 1 - test_kprobe ok 2 - test_kprobes ok 3 - test_kretprobe ok 4 - test_kretprobes ok 5 - test_stacktrace_on_kretprobe ok 6 - test_stacktrace_on_nested_kretprobe # kprobes_test: pass:6 fail:0 skip:0 total:6 # Totals: pass:6 fail:0 skip:0 total:6 ok 1 - kprobes_test Signed-off-by: Masami Hiramatsu --- arch/Kconfig | 8 ++ arch/x86/Kconfig | 1 kernel/test_kprobes.c | 158 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 167 insertions(+) diff --git a/arch/Kconfig b/arch/Kconfig index 8df1c7102643..8378f83b462c 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -191,6 +191,14 @@ config HAVE_OPTPROBES config HAVE_KPROBES_ON_FTRACE bool +config ARCH_CORRECT_STACKTRACE_ON_KRETPROBE + bool + help + Since kretprobes modifies return address on the stack, the + stacktrace may see the kretprobe trampoline address instead + of correct one. If the architecture stacktrace code and + unwinder can adjust such entries, select this configuration. + config HAVE_FUNCTION_ERROR_INJECTION bool diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index ab83c22d274e..2049364b3981 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -61,6 +61,7 @@ config X86 select ACPI_SYSTEM_POWER_STATES_SUPPORT if ACPI select ARCH_32BIT_OFF_T if X86_32 select ARCH_CLOCKSOURCE_INIT + select ARCH_CORRECT_STACKTRACE_ON_KRETPROBE select ARCH_ENABLE_HUGEPAGE_MIGRATION if X86_64 && HUGETLB_PAGE && MIGRATION select ARCH_ENABLE_MEMORY_HOTPLUG if X86_64 || (X86_32 && HIGHMEM) select ARCH_ENABLE_MEMORY_HOTREMOVE if MEMORY_HOTPLUG diff --git a/kernel/test_kprobes.c b/kernel/test_kprobes.c index e78f18144145..a902be1f4a96 100644 --- a/kernel/test_kprobes.c +++ b/kernel/test_kprobes.c @@ -17,6 +17,11 @@ 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); @@ -58,6 +63,33 @@ 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(); + + /* This is for preventing inlining the function */ + 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; @@ -175,12 +207,134 @@ static void test_kretprobes(struct kunit *test) 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]); + + /* + * Test stacktrace inside the kretprobe handler, this will involves + * kretprobe trampoline, but must include correct return address + * of the target function. + */ + 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); + + /* + * Test stacktrace from pt_regs at the return address. Thus the stack + * trace must start from the target return address. + */ + 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]); + + 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; + + /* + * Run the stacktrace_driver() to record correct return address in + * stacktrace_target() and ensure stacktrace_driver() call is not + * inlined by checking the return address of stacktrace_driver() + * and the return address of this function is different. + */ + 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]); + + /* + * Test stacktrace inside the kretprobe handler for nested case. + * The unwinder will find the kretprobe_trampoline address on the + * return address, and kretprobe must solve that. + */ + 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); + + /* Ditto for the regs version. */ + 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]); + + 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_NE(test, myretaddr, stacktrace_driver()); + + KUNIT_ASSERT_EQ(test, 0, register_kretprobes(rps, 2)); + KUNIT_ASSERT_NE(test, myretaddr, stacktrace_driver()); + unregister_kretprobes(rps, 2); +} +#endif /* CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE */ + #endif /* CONFIG_KRETPROBES */ 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 = prandom_u32(); @@ -194,6 +348,10 @@ static struct kunit_case kprobes_testcases[] = { #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 {} }; From patchwork Fri Oct 15 12:51:10 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Masami Hiramatsu (Google)" X-Patchwork-Id: 12561447 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5D72FC433EF for ; Fri, 15 Oct 2021 12:55:19 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 1D9CD6101E for ; Fri, 15 Oct 2021 12:55:19 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 1D9CD6101E Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=kernel.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=EZvVzOU6/Uz1jmWaRKsTxkkB87XSvSKIiky/j3SLqLs=; b=LvXrX1OtRWUSY0 qkpSDZoCeNe+36PNW22rnXQBK7RDYnHpnD9KsLT8PaxEWETLtNwF2/xVjR7xUMDQ72i31quMmueAy 8Bif2LU56b+xyhWAhsQVKauKrEvQMKESs6j6sQABbfK7eTlqh9Zz032xhylc31px3oAWAuZyH2rW5 zuO4n9llXNs0nZRTqQmRdSk195QMX2GWVxu2XKk5JPwej0ViRJNY6NBNxNCXduaVtihVLwbnJ4T6o Zd0r7J6IzzN7gsK82WEX1AV4IJ/Q0Oa6DMvz5le22ptCyo9B5J0qHU5f9Bpn1vEM83b4Zu4Jt70Jm rdad9Iydd2JBFjVnu1Lg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mbMif-0072iw-QD; Fri, 15 Oct 2021 12:53:54 +0000 Received: from mail.kernel.org ([198.145.29.99]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mbMg6-00716v-I1 for linux-arm-kernel@lists.infradead.org; Fri, 15 Oct 2021 12:51:15 +0000 Received: by mail.kernel.org (Postfix) with ESMTPSA id 13FCB6108E; Fri, 15 Oct 2021 12:51:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1634302274; bh=/6Ses4iOpFuwfQyjHXNpCu4Cpb2y9TUHV8jz9fN04Nw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ZD+YgR37fo5+Ms9i8CZvcGHzzgUehgFm0vKsvUk1RE75cth5o0EyuST2r56ToabsW mlp1cIoYacIoxrMTUkEeWQHCUtejHJBB4/7fIM/qQatgyIX574bYOs9az/dBlojMWB kskLLFI0FBRpXdG7ip2KifRdzrOtH1+jiKRqTEEaaBkJc3WUF15Y7V8C1zQ4hzfLQo 1xuaZkmbLDjidVIJxjsz3kqq/TeZr91Og5U1XZr25KXpp3C63uwegFEPf9Vzx823yj 4MW/G68+B6g7k4VEKGN5tBnfU1K6tP9awnsOsE06Yv0eqlBBfs6ZVNlbm9H5q8tZNg +B9nghvGGPKMQ== From: Masami Hiramatsu To: Steven Rostedt Cc: "Naveen N . Rao" , Ananth N Mavinakayanahalli , Ingo Molnar , linux-kernel@vger.kernel.org, mhiramat@kernel.org, Sven Schnelle , Catalin Marinas , Will Deacon , Russell King , Nathan Chancellor , Nick Desaulniers , linux-arm-kernel@lists.infradead.org Subject: [PATCH 03/10] x86/unwind: Compile kretprobe fixup code only if CONFIG_KRETPROBES=y Date: Fri, 15 Oct 2021 21:51:10 +0900 Message-Id: <163430227030.459050.12754362425825951410.stgit@devnote2> X-Mailer: git-send-email 2.25.1 In-Reply-To: <163430224341.459050.2369208860773018092.stgit@devnote2> References: <163430224341.459050.2369208860773018092.stgit@devnote2> User-Agent: StGit/0.19 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211015_055114_648877_BC362EC8 X-CRM114-Status: UNSURE ( 8.75 ) X-CRM114-Notice: Please train this message. X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Compile kretprobe related stacktrace entry recovery code and unwind_state::kr_cur field only when CONFIG_KRETPROBES=y. Signed-off-by: Masami Hiramatsu --- arch/x86/include/asm/unwind.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/x86/include/asm/unwind.h b/arch/x86/include/asm/unwind.h index fca2e783e3ce..2a1f8734416d 100644 --- a/arch/x86/include/asm/unwind.h +++ b/arch/x86/include/asm/unwind.h @@ -16,7 +16,9 @@ struct unwind_state { unsigned long stack_mask; struct task_struct *task; int graph_idx; +#ifdef CONFIG_KRETPROBES struct llist_node *kr_cur; +#endif bool error; #if defined(CONFIG_UNWINDER_ORC) bool signal, full_regs; @@ -105,9 +107,13 @@ static inline unsigned long unwind_recover_kretprobe(struct unwind_state *state, unsigned long addr, unsigned long *addr_p) { +#ifdef CONFIG_KRETPROBES return is_kretprobe_trampoline(addr) ? kretprobe_find_ret_addr(state->task, addr_p, &state->kr_cur) : addr; +#else + return addr; +#endif } /* Recover the return address modified by kretprobe and ftrace_graph. */ From patchwork Fri Oct 15 12:51:19 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Masami Hiramatsu (Google)" X-Patchwork-Id: 12561449 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 71F8BC433F5 for ; Fri, 15 Oct 2021 12:56:24 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 3076A60F56 for ; Fri, 15 Oct 2021 12:56:24 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 3076A60F56 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=kernel.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=McJNLkIySxMjXiQI+CnK6wF0N7fLq5vASRWNlu0Gnx0=; b=GOocO5gWjCj9+B c6XDBGu1cR6AwfozCOCh7OTPcNfyeO+JH479Dj46gkWovqj1LL9Q3CQVo9MVuzNeLLTaRnQl7qdFB ZuZLJAbaEFBSTYmMRS6vD4357b4qCoCqanmV9yrY8sKINfOttdfdvf5cvrQg45ud5ndLf36FQEB29 RNPbIZ8Dn4fkg/54MPTQngQh1NnP8vl4RVZ039TfmxribFzBO85z0oNeKHGgqKTQCvRV9sQsDyxCl EcsIt7qS3IzJKa9t+HsE11qdOz7eZctSd1fCXcwzPQpg4AoR78KEPh0HVtTUET5nzUKDXVW0xYvZ+ u467jz7MKTsPMQb2ACjQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mbMjB-0072xL-A2; Fri, 15 Oct 2021 12:54:26 +0000 Received: from mail.kernel.org ([198.145.29.99]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mbMgG-0071Bt-3Y for linux-arm-kernel@lists.infradead.org; Fri, 15 Oct 2021 12:51:25 +0000 Received: by mail.kernel.org (Postfix) with ESMTPSA id 4DF116101E; Fri, 15 Oct 2021 12:51:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1634302283; bh=EmhCA26E8wn4zdfBxKo6rHymp3Y5IgKibhi1RWKA/b4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=pAPPkNGFdFCe5qUiVmxBp7YRi8CoeGwrGAqJ37ZOojicAKBUvLg0ddaMH96u8lzSN DPFDCctw8fwrLeuMtP7Gu23bKNhH1A4Z3W2TgEEfTjhOeAl7uitfFPmSQu1DrdnQLH kIOV1YBR7On3Wh8XyesbQve4ACDwIvQdfSTX451gLNaNzP2cXMHpySAUU++LGu2ny/ tu1GCVhsnLo0r56zFGjK2JCbMlHX2dx2klko36zYxOnrWQpdf5ZBK4Y80q3s96/0TF Ri1o5J15QcCpOzTeqvFsp7od/YvOOnT/VQXLrCELBrM9kPFMgNsr5g2zWilQ/YrVQM RqvZnMwNzYRbA== From: Masami Hiramatsu To: Steven Rostedt Cc: "Naveen N . Rao" , Ananth N Mavinakayanahalli , Ingo Molnar , linux-kernel@vger.kernel.org, mhiramat@kernel.org, Sven Schnelle , Catalin Marinas , Will Deacon , Russell King , Nathan Chancellor , Nick Desaulniers , linux-arm-kernel@lists.infradead.org Subject: [PATCH 04/10] arm64: kprobes: Record frame pointer with kretprobe instance Date: Fri, 15 Oct 2021 21:51:19 +0900 Message-Id: <163430227946.459050.807047989088672925.stgit@devnote2> X-Mailer: git-send-email 2.25.1 In-Reply-To: <163430224341.459050.2369208860773018092.stgit@devnote2> References: <163430224341.459050.2369208860773018092.stgit@devnote2> User-Agent: StGit/0.19 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211015_055124_209292_09CBB861 X-CRM114-Status: GOOD ( 12.88 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Record the frame pointer instead of stack address with kretprobe instance as the identifier on the instance list. Since arm64 always enable CONFIG_FRAME_POINTER, we can use the actual frame pointer (x29). This will allow the stacktrace code to find the original return address from the FP alone. Signed-off-by: Masami Hiramatsu Acked-by: Will Deacon Acked-by: Mark Rutland --- Changes in v2: - Update changelog according to Mark's comment. --- arch/arm64/kernel/probes/kprobes.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c index e7ad6da980e8..d9dfa82c1f18 100644 --- a/arch/arm64/kernel/probes/kprobes.c +++ b/arch/arm64/kernel/probes/kprobes.c @@ -401,14 +401,14 @@ int __init arch_populate_kprobe_blacklist(void) void __kprobes __used *trampoline_probe_handler(struct pt_regs *regs) { - return (void *)kretprobe_trampoline_handler(regs, (void *)kernel_stack_pointer(regs)); + return (void *)kretprobe_trampoline_handler(regs, (void *)regs->regs[29]); } void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, struct pt_regs *regs) { ri->ret_addr = (kprobe_opcode_t *)regs->regs[30]; - ri->fp = (void *)kernel_stack_pointer(regs); + ri->fp = (void *)regs->regs[29]; /* replace return addr (x30) with trampoline */ regs->regs[30] = (long)&__kretprobe_trampoline; From patchwork Fri Oct 15 12:51:29 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Masami Hiramatsu (Google)" X-Patchwork-Id: 12561451 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1C2DFC433F5 for ; Fri, 15 Oct 2021 12:56:30 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D691760F56 for ; Fri, 15 Oct 2021 12:56:29 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org D691760F56 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=kernel.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=hj8pcxbL6q1Ra/ojlsbu6a4FHIMvmsks9QS9qiSLMwo=; b=f8e8QNDJjMojI0 ieN4kGUIBBOSY6VHjX26Ffk/ULNEvEwp6VwlUBNOtQi55WpiHvPYHK8hKj7iLEnqE3s7qrqJJLxpV CHEoBGZvtnOUbpm73izmPYTt1nce7Rg4urx+Vbmx1vp92tQfbWeQcsm9bsLYcYZBqhErP6Rv9s13D X++ItjGQiYrhFjKoF+ALqcu8K/pWAsXcbxcXcX0E6ZIq5Z6gJaU/HRiBHMUqtAWjmCo11LYZchntU fcZeqjTU10euDRYjfZgICincJAANwKCx9/HsmA/WPYTFzSustYa86IuM8QdckNj5HnHzIQWx2P5x2 ezwZf42zyFB/5ciSEACQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mbMji-0073Ew-Uu; Fri, 15 Oct 2021 12:54:59 +0000 Received: from mail.kernel.org ([198.145.29.99]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mbMgO-0071HN-E3 for linux-arm-kernel@lists.infradead.org; Fri, 15 Oct 2021 12:51:35 +0000 Received: by mail.kernel.org (Postfix) with ESMTPSA id 863D161090; Fri, 15 Oct 2021 12:51:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1634302292; bh=0rk2OE9N625FCZQR+v+3LZ8V9a5HPzPHQNru9UNWLCU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PTzaLMqDCU1dZD4zb8xwT3cob7cIYib7RNENvAMHhlqU1Avjl02iXp893Ar23k1kb 7HU/G+exNHot3r0UWLogKtbMsKwb6bTOGwMSIZJPq8+6UbU2ciemaAvkd1hCheFLQq NfBWlf2eIjLuAUlHP1rZ6muOPSlteyDFux7MvdeZnbUIo5G/d1t2ZEUeHaqgduMjd6 ugiYtiRCumJUlBlkNv8L8qZbH7K7xwewrBS9500K9QtcV7BmQVW8J0GTZRLyxqgdmg ZbvzyvLdC9ucAsqAmHnpZCw2OgvwiDqmcTaAnDxT0BxuE8RIJmOxYNIFd2aG8FPIMp cyWtlUbnOEMQw== From: Masami Hiramatsu To: Steven Rostedt Cc: "Naveen N . Rao" , Ananth N Mavinakayanahalli , Ingo Molnar , linux-kernel@vger.kernel.org, mhiramat@kernel.org, Sven Schnelle , Catalin Marinas , Will Deacon , Russell King , Nathan Chancellor , Nick Desaulniers , linux-arm-kernel@lists.infradead.org Subject: [PATCH 05/10] arm64: kprobes: Make a frame pointer on __kretprobe_trampoline Date: Fri, 15 Oct 2021 21:51:29 +0900 Message-Id: <163430228904.459050.16973178880543757481.stgit@devnote2> X-Mailer: git-send-email 2.25.1 In-Reply-To: <163430224341.459050.2369208860773018092.stgit@devnote2> References: <163430224341.459050.2369208860773018092.stgit@devnote2> User-Agent: StGit/0.19 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211015_055132_533315_FF0B740A X-CRM114-Status: GOOD ( 11.79 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Make a frame pointer (make the x29 register points the address of pt_regs->regs[29]) on __kretprobe_trampoline. This frame pointer will be used by the stacktracer when it is called from the kretprobe handlers. In this case, the stack tracer will unwind stack to trampoline_probe_handler() and find the next frame pointer in the stack frame of the __kretprobe_trampoline(). Signed-off-by: Masami Hiramatsu Acked-by: Will Deacon --- arch/arm64/kernel/probes/kprobes_trampoline.S | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/kernel/probes/kprobes_trampoline.S b/arch/arm64/kernel/probes/kprobes_trampoline.S index 520ee8711db1..9a6499bed58b 100644 --- a/arch/arm64/kernel/probes/kprobes_trampoline.S +++ b/arch/arm64/kernel/probes/kprobes_trampoline.S @@ -66,6 +66,9 @@ SYM_CODE_START(__kretprobe_trampoline) save_all_base_regs + /* Setup a frame pointer. */ + add x29, sp, #S_FP + mov x0, sp bl trampoline_probe_handler /* @@ -74,6 +77,7 @@ SYM_CODE_START(__kretprobe_trampoline) */ mov lr, x0 + /* The frame pointer (x29) is restored with other registers. */ restore_all_base_regs add sp, sp, #PT_REGS_SIZE From patchwork Fri Oct 15 12:51:37 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Masami Hiramatsu (Google)" X-Patchwork-Id: 12561453 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 63372C433EF for ; Fri, 15 Oct 2021 12:57:59 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 264FF60F93 for ; Fri, 15 Oct 2021 12:57:59 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 264FF60F93 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=kernel.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=8KvtbD/5LLLwSdU96TM/gPH0trpmjvX7MHqeJrShojw=; b=laTB420McX0SDw 2kNCXnufQx0r/1GrwfXE9+mN+7drr59nWMm2hDFeZcGwfWb4jCTnfKOQfRKyKY8ispf3dE2DPm9os BwNXb6+vnIoKOL37hBG5CqAfquUVZmfKOYzMO9lePHy1V/TTX5yUGot8ZcWefLfvwNVa6+SqFmdO9 CHFOP4m//ckMS3uM58E0FFuvidWx/5mfBPjRXbNs9ir0UaKwXiA4cR9JnESwY7tws1O1oO8dq8Ap7 U4/SudjZmBSYZwr7bzNif9KHTexbRrh+1qvz7SEB0ynma9V9i9Mowv56Z320ZciXL/MKEQVR0T7wJ EiYu1rnAqbxMqrSOvijg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mbMkU-0073dD-1u; Fri, 15 Oct 2021 12:55:47 +0000 Received: from mail.kernel.org ([198.145.29.99]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mbMgX-0071Mx-Rh for linux-arm-kernel@lists.infradead.org; Fri, 15 Oct 2021 12:51:43 +0000 Received: by mail.kernel.org (Postfix) with ESMTPSA id C86E760ED4; Fri, 15 Oct 2021 12:51:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1634302300; bh=nvZy1sVKYSK6zZvA82X0Qwm/erFQUaJsuPthlqjB5TY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=XZm6dGWKFv/Q7OSnILPwjpJd1t8TNa2SBlAAQC4U0nri4Rcl2AZXSDhMVT/gSEK/w PoNq5LJCXkRttBGHN05+7Sy+hlfCHER5eou9y0L4yepzQXQqs1VB6sUvsMXVO7I5CU /TfKZTkBrz0xULe1iu8a4qwTTq+v7wlgpl6I41dW/uGDOrD9rzanrgnscUSgjyobTB JmIsrvOZ4xPpNDmTu59f2JIiE4WDmUNr3jZRLHv5S7FNifMwieQe4XyDaBd8pZjI3i TTcOawJlIBZbvrBdsQVFG4KrzMFblMpnOag/bycZxPDFuZ2jsXTVWbQOUN8kltKbGk mFX9Jcks6K/Bg== From: Masami Hiramatsu To: Steven Rostedt Cc: "Naveen N . Rao" , Ananth N Mavinakayanahalli , Ingo Molnar , linux-kernel@vger.kernel.org, mhiramat@kernel.org, Sven Schnelle , Catalin Marinas , Will Deacon , Russell King , Nathan Chancellor , Nick Desaulniers , linux-arm-kernel@lists.infradead.org Subject: [PATCH 06/10] arm64: Recover kretprobe modified return address in stacktrace Date: Fri, 15 Oct 2021 21:51:37 +0900 Message-Id: <163430229733.459050.8624118341048476904.stgit@devnote2> X-Mailer: git-send-email 2.25.1 In-Reply-To: <163430224341.459050.2369208860773018092.stgit@devnote2> References: <163430224341.459050.2369208860773018092.stgit@devnote2> User-Agent: StGit/0.19 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211015_055142_011890_442F4CF4 X-CRM114-Status: GOOD ( 14.81 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Since the kretprobe replaces the function return address with the kretprobe_trampoline on the stack, stack unwinder shows it instead of the correct return address. This checks whether the next return address is the __kretprobe_trampoline(), and if so, try to find the correct return address from the kretprobe instance list. For this purpose this adds 'kr_cur' loop cursor to memorize the current kretprobe instance. With this fix, now arm64 can enable CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE, and pass the kprobe self tests. Signed-off-by: Masami Hiramatsu --- Changes in v2: - Add comment for kr_cur. - Make the kretprobe related code depends on CONFIG_KRETPROBES. - Initialize "kr_cur" directly in start_backtrace() instead of clearing "frame" data structure by memset(). --- arch/arm64/Kconfig | 1 + arch/arm64/include/asm/stacktrace.h | 4 ++++ arch/arm64/kernel/stacktrace.c | 7 +++++++ 3 files changed, 12 insertions(+) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 5c7ae4c3954b..edde5171ffb2 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -11,6 +11,7 @@ config ARM64 select ACPI_PPTT if ACPI select ARCH_HAS_DEBUG_WX select ARCH_BINFMT_ELF_STATE + select ARCH_CORRECT_STACKTRACE_ON_KRETPROBE select ARCH_ENABLE_HUGEPAGE_MIGRATION if HUGETLB_PAGE && MIGRATION select ARCH_ENABLE_MEMORY_HOTPLUG select ARCH_ENABLE_MEMORY_HOTREMOVE diff --git a/arch/arm64/include/asm/stacktrace.h b/arch/arm64/include/asm/stacktrace.h index 8aebc00c1718..a4e046ef4568 100644 --- a/arch/arm64/include/asm/stacktrace.h +++ b/arch/arm64/include/asm/stacktrace.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -59,6 +60,9 @@ struct stackframe { #ifdef CONFIG_FUNCTION_GRAPH_TRACER int graph; #endif +#ifdef CONFIG_KRETPROBES + struct llist_node *kr_cur; +#endif }; extern int unwind_frame(struct task_struct *tsk, struct stackframe *frame); diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c index 8982a2b78acf..c30624fff6ac 100644 --- a/arch/arm64/kernel/stacktrace.c +++ b/arch/arm64/kernel/stacktrace.c @@ -41,6 +41,9 @@ void start_backtrace(struct stackframe *frame, unsigned long fp, #ifdef CONFIG_FUNCTION_GRAPH_TRACER frame->graph = 0; #endif +#ifdef CONFIG_KRETPROBES + frame->kr_cur = NULL; +#endif /* * Prime the first unwind. @@ -129,6 +132,10 @@ int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame) frame->pc = ret_stack->ret; } #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ +#ifdef CONFIG_KRETPROBES + if (is_kretprobe_trampoline(frame->pc)) + frame->pc = kretprobe_find_ret_addr(tsk, (void *)frame->fp, &frame->kr_cur); +#endif frame->pc = ptrauth_strip_insn_pac(frame->pc); From patchwork Fri Oct 15 12:51:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Masami Hiramatsu (Google)" X-Patchwork-Id: 12561455 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id F0C39C433EF for ; Fri, 15 Oct 2021 12:58:26 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B8EF560F9D for ; Fri, 15 Oct 2021 12:58:26 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org B8EF560F9D Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=kernel.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=J8BfmDls14t4heXQnTJB0eRkeSRc2l+KHS7klm80/GA=; b=g2KlUbBh6Wkeyq QmTyCa3ZOu3m0Gg4BB1n8YZZI1E5kAxoqXyn4kQNvHdcOzN7jEQzn4N89HLp+jd4msrtJzohyvKM9 E46Z3nReGN/4hXn8HpSLk6c1XIzioOwug2ZldIRk+lp1JVzjS1srqbczybo62prioHLx/m42Fq2iW hGQJcFbGiC29Ql8X15L0sVGn3himiJkEc1M9R6Wld1FwHQOeFyk2/zgxP1cxxH5UVgsD4E8CrXh3Z pqizAO1LyeUnYJ0N9AidiovRwGcop0R+salfoFPimdU3mY7+6cKa/qmDxzUn1ReW+azSvrqdFI56d yjTl2cMWAMF9fKfbfmHw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mbMlT-00749T-Dc; Fri, 15 Oct 2021 12:56:48 +0000 Received: from mail.kernel.org ([198.145.29.99]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mbMgh-0071Se-9C for linux-arm-kernel@lists.infradead.org; Fri, 15 Oct 2021 12:51:54 +0000 Received: by mail.kernel.org (Postfix) with ESMTPSA id 0A9566101E; Fri, 15 Oct 2021 12:51:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1634302310; bh=WqIiiFEaJiQvJq7Z5CrnA44AmFZAiLP70n+lEDL0ZZw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fkssxWyurZ2i375lw8QBWz3d1mzUc+LIUjYF41fDOpx7aXA0+S8VGjaQrAXnAlerr fjjHanUxZA9YdkTFDJ6efqfUsxu2EbD0W8f8GVR5GL6n+GvT4sk+OZpsM7TJRL5G4C 9dOR2aE3Oe3IZrIyna6XFYQrxod+9/mRRvmKR4/lFuEo6vJFTgh3/GMp9A/3OSgusE GN5Pr+JOWAtwSAsgfR5XUy1Har1bt8OP0CF61T5fVXjTZnLcu+tKSuzU/VDAcyr8B5 y/G2hdSSw82z0y0mpqGN3Q4l8SkkkoC9fp4pmUOAYqup5jbfCCzxRP6cteQHjopp3h QPuaf+ZQXEqHw== From: Masami Hiramatsu To: Steven Rostedt Cc: "Naveen N . Rao" , Ananth N Mavinakayanahalli , Ingo Molnar , linux-kernel@vger.kernel.org, mhiramat@kernel.org, Sven Schnelle , Catalin Marinas , Will Deacon , Russell King , Nathan Chancellor , Nick Desaulniers , linux-arm-kernel@lists.infradead.org Subject: [PATCH 07/10] ARM: clang: Do not rely on lr register for stacktrace Date: Fri, 15 Oct 2021 21:51:46 +0900 Message-Id: <163430230603.459050.13271391202951929788.stgit@devnote2> X-Mailer: git-send-email 2.25.1 In-Reply-To: <163430224341.459050.2369208860773018092.stgit@devnote2> References: <163430224341.459050.2369208860773018092.stgit@devnote2> User-Agent: StGit/0.19 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211015_055151_386634_C1E2DCC1 X-CRM114-Status: GOOD ( 12.65 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Currently the stacktrace on clang compiled arm kernel uses the 'lr' register to find the first frame address from pt_regs. However, that is wrong after calling another function, because the 'lr' register is used by 'bl' instruction and never be recovered. As same as gcc arm kernel, directly use the frame pointer (r11) of the pt_regs to find the first frame address. Note that this fixes kretprobe stacktrace issue only with CONFIG_UNWINDER_FRAME_POINTER=y. For the CONFIG_UNWINDER_ARM, we need another fix. Signed-off-by: Masami Hiramatsu Reviewed-by: Nick Desaulniers --- Changes in v2: - Fix typos in changelog. --- arch/arm/kernel/stacktrace.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c index 76ea4178a55c..db798eac7431 100644 --- a/arch/arm/kernel/stacktrace.c +++ b/arch/arm/kernel/stacktrace.c @@ -54,8 +54,7 @@ int notrace unwind_frame(struct stackframe *frame) frame->sp = frame->fp; frame->fp = *(unsigned long *)(fp); - frame->pc = frame->lr; - frame->lr = *(unsigned long *)(fp + 4); + frame->pc = *(unsigned long *)(fp + 4); #else /* check current frame pointer is within bounds */ if (fp < low + 12 || fp > high - 4) From patchwork Fri Oct 15 12:51:56 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Masami Hiramatsu (Google)" X-Patchwork-Id: 12561457 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 761A5C433EF for ; Fri, 15 Oct 2021 12:59:31 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 43B196108E for ; Fri, 15 Oct 2021 12:59:31 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 43B196108E Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=kernel.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=g2Rf/b9v9OBNj+17yW3v2mKqabtfBYXPtpyHnudhxkw=; b=wgQWsnW1t6edkB LwhQCBVNR/2kzkSoUzABdmswcz842BycA4DzE2cTQzk+xNoo9BlTex6D2iImtali4QLVVDmr8pJcF tDDxFGL5z9qePHVEb2Eag51pUgkc7cCDEIth7plodDaOxTVIquv9o8BdyGRmNfKwIL5q7tfyKEhHm xnNCE8+LJ2Q+VnGgYr84OeDAElnWuO6xd0i0KBq3eEVXPpw0wD8+nF6jmeiWgm1N1eYZdmsZSLUAD Mr1IEBMwE58IUXCpObCi0M34F+7+pfufKLHkv3vl7G6ZWavd4nrj0yKCuEThp8e6lYdHOr6aX07ZP rJiskEF+e7f3C5sku5LQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mbMmU-0074gl-75; Fri, 15 Oct 2021 12:57:51 +0000 Received: from mail.kernel.org ([198.145.29.99]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mbMgp-0071Yt-ON for linux-arm-kernel@lists.infradead.org; Fri, 15 Oct 2021 12:52:01 +0000 Received: by mail.kernel.org (Postfix) with ESMTPSA id A57886108E; Fri, 15 Oct 2021 12:51:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1634302319; bh=lMfZZP/tcQBNE+YtsSJsSIaa1mi/f3aqAfbOhPMBTwU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=VinROdbI2nOQEwbz1Bbr8uLxnMs6z2HkeNogB0M9aJsvxmpPXojOh/Ok3QcltLx4x rosRgtidldui2bVynfYGTcxW9L4QzOVkEilqPPC5v+upmHxl1/xQM7hJXhKa+mTAZv UBVeeaz9sAX6U4dq7C1QaqZYJ4TDOdMJPk2v/1PW8fYOtSgEpW5VoBLjLSRKfzdHXl LGdIWax8OFUtfaWi751ASKQ54ZlXB3oqBilFbaI/vSW/Ygi6ZFTxa4F8/8UQoh2O/4 +telTfkMb0UeeKqxoBMikS+VqSGVz6jX5RJhmujoharUU4lXe+DLeh3MD/lF07giR+ awEpdluZHPIZQ== From: Masami Hiramatsu To: Steven Rostedt Cc: "Naveen N . Rao" , Ananth N Mavinakayanahalli , Ingo Molnar , linux-kernel@vger.kernel.org, mhiramat@kernel.org, Sven Schnelle , Catalin Marinas , Will Deacon , Russell King , Nathan Chancellor , Nick Desaulniers , linux-arm-kernel@lists.infradead.org Subject: [PATCH 08/10] ARM: kprobes: Make a frame pointer on __kretprobe_trampoline Date: Fri, 15 Oct 2021 21:51:56 +0900 Message-Id: <163430231601.459050.8640625926942332950.stgit@devnote2> X-Mailer: git-send-email 2.25.1 In-Reply-To: <163430224341.459050.2369208860773018092.stgit@devnote2> References: <163430224341.459050.2369208860773018092.stgit@devnote2> User-Agent: StGit/0.19 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211015_055159_897229_4A6F5731 X-CRM114-Status: GOOD ( 18.62 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Currently kretprobe on ARM just fills r0-r11 of pt_regs, but that is not enough for the stacktrace. Moreover, from the user kretprobe handler, stacktrace needs a frame pointer on the __kretprobe_trampoline. This adds a frame pointer on __kretprobe_trampoline for both gcc and clang case. Those have different frame pointer so we need different but similar stack on pt_regs. Gcc makes the frame pointer (fp) to point the 'pc' address of the {fp, ip (=sp), lr, pc}, this means {r11, r13, r14, r15}. Thus if we save the r11 (fp) on pt_regs->r12, we can make this set on the end of pt_regs. On the other hand, Clang makes the frame pointer to point the 'fp' address of {fp, lr} on stack. Since the next to the pt_regs->lr is pt_regs->sp, I reused the pair of pt_regs->fp and pt_regs->ip. So this stores the 'lr' on pt_regs->ip and make the fp to point pt_regs->fp. For both cases, saves __kretprobe_trampoline address to pt_regs->lr, so that the stack tracer can identify this frame pointer has been made by the __kretprobe_trampoline. Note that if the CONFIG_FRAME_POINTER is not set, this keeps fp as is. Signed-off-by: Masami Hiramatsu Reviewed-by: Nick Desaulniers --- arch/arm/probes/kprobes/core.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/arch/arm/probes/kprobes/core.c b/arch/arm/probes/kprobes/core.c index 95f23b47ba27..7cbd65a22769 100644 --- a/arch/arm/probes/kprobes/core.c +++ b/arch/arm/probes/kprobes/core.c @@ -368,16 +368,35 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, /* * When a retprobed function returns, trampoline_handler() is called, * calling the kretprobe's handler. We construct a struct pt_regs to - * give a view of registers r0-r11 to the user return-handler. This is - * not a complete pt_regs structure, but that should be plenty sufficient - * for kretprobe handlers which should normally be interested in r0 only - * anyway. + * give a view of registers r0-r11, sp, lr, and pc to the user + * return-handler. This is not a complete pt_regs structure, but that + * should be enough for stacktrace from the return handler with or + * without pt_regs. */ void __naked __kprobes __kretprobe_trampoline(void) { __asm__ __volatile__ ( - "sub sp, sp, #16 \n\t" + "ldr lr, =__kretprobe_trampoline \n\t" + "stmdb sp!, {sp, lr, pc} \n\t" +#ifdef CONFIG_FRAME_POINTER + /* __kretprobe_trampoline makes a framepointer on pt_regs. */ +#ifdef CONFIG_CC_IS_CLANG + /* In clang case, pt_regs->ip = lr. */ + "stmdb sp!, {lr} \n\t" "stmdb sp!, {r0 - r11} \n\t" + /* fp points regs->r11 (fp) */ + "add fp, sp, #44 \n\t" +#else /* !CONFIG_CC_IS_CLANG */ + /* In gcc case, pt_regs->ip = fp. */ + "stmdb sp!, {fp} \n\t" + "stmdb sp!, {r0 - r11} \n\t" + /* fp points regs->r15 (pc) */ + "add fp, sp, #60 \n\t" +#endif /* CONFIG_CC_IS_CLANG */ +#else /* !CONFIG_FRAME_POINTER */ + "sub sp, sp, #4 \n\t" + "stmdb sp!, {r0 - r11} \n\t" +#endif /* CONFIG_FRAME_POINTER */ "mov r0, sp \n\t" "bl trampoline_handler \n\t" "mov lr, r0 \n\t" From patchwork Fri Oct 15 12:52:04 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Masami Hiramatsu (Google)" X-Patchwork-Id: 12561459 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A5916C433F5 for ; Fri, 15 Oct 2021 13:00:23 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 6472C61090 for ; Fri, 15 Oct 2021 13:00:23 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 6472C61090 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=kernel.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=WLwB7PiKbJSi0VzD9RaEH+PTSrU5ZMqjNRIQsVzEuJY=; b=kodXirOSw5Qgk0 9tm+azyZkzd3ogD7Q1M8iIiqM8mKKRniI7r5yqEf/hDhUCb0G8YJKHOJHMCCbzFRvIujCmZYXXyWa 6IXu0Esa11UjIz3GDaai+yuzVJ2W8my6ULjJZBHw13X7qGcqZDP6Ie4BGlYH2oAeKHKEwB1HQ/A7D rAR2S32GGsVzGhVGUt53wsw/32/0ffvaE21x1UvIs1v2D+EjfE2zQq+2BO22x85EyTc93NZ4pflfl E4jic2Z4P5iWx1a93X4MF1OKA5S8Lpx0BQgCUWFF6HcRBJYI4AWb/ECyHBr2gW/ZH1sPjeRZ5+rSC tsUt5D7PigeFFoswgPmw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mbMnL-00754c-1P; Fri, 15 Oct 2021 12:58:43 +0000 Received: from mail.kernel.org ([198.145.29.99]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mbMgz-0071fX-EI for linux-arm-kernel@lists.infradead.org; Fri, 15 Oct 2021 12:52:11 +0000 Received: by mail.kernel.org (Postfix) with ESMTPSA id D0BE360230; Fri, 15 Oct 2021 12:52:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1634302329; bh=6eQhPcwTPWL7PeCf0bKVrZpLNkk5pcOdMHPKs5Ym+g0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=h0HJxPsoPmofnkEevWSCquKWYTveY+4/knPL9GnpoTUYrLgtm9PCbQV3VLBihKAXU 90V8KNHFcWpAQHxPhFNz7FZsPGl9utoCpIIaXmLxz5PTFdc9ddu0BJT4vP4O/2f3xc nSnu1hJbSJSwkHoSfm5UVIN3GiXeNTKY3eXyDSOYeZVGM6Ov3PC3q7FJ8glFFq+OHF V8w+jqXnJ8HMw1d4Pqw191j7fHJSX9O7irtYBNvqAJ0WD7gpugeViu8dP1Thj+wVNy IbMwZtb1Aozkf9idA8lW0Wo6r0AddCvzNo1lLhRgcIAQ2i/Q8vWuSsJkCsp5Cbnx1U AujxEWst0a/aw== From: Masami Hiramatsu To: Steven Rostedt Cc: "Naveen N . Rao" , Ananth N Mavinakayanahalli , Ingo Molnar , linux-kernel@vger.kernel.org, mhiramat@kernel.org, Sven Schnelle , Catalin Marinas , Will Deacon , Russell King , Nathan Chancellor , Nick Desaulniers , linux-arm-kernel@lists.infradead.org Subject: [PATCH 09/10] ARM: Recover kretprobe modified return address in stacktrace Date: Fri, 15 Oct 2021 21:52:04 +0900 Message-Id: <163430232448.459050.59665093997557853.stgit@devnote2> X-Mailer: git-send-email 2.25.1 In-Reply-To: <163430224341.459050.2369208860773018092.stgit@devnote2> References: <163430224341.459050.2369208860773018092.stgit@devnote2> User-Agent: StGit/0.19 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211015_055209_567245_A0389869 X-CRM114-Status: GOOD ( 16.44 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Since the kretprobe replaces the function return address with the kretprobe_trampoline on the stack, arm unwinder shows it instead of the correct return address. This finds the correct return address from the per-task kretprobe_instances list and verify it is in between the caller fp and callee fp. Note that this supports both GCC and clang if CONFIG_FRAME_POINTER=y and CONFIG_ARM_UNWIND=n. For the ARM unwinder, this is still not working correctly. Signed-off-by: Masami Hiramatsu --- Changes in v2: - Compile this code only when CONFIG_KRETPROBES=y --- arch/arm/Kconfig | 1 + arch/arm/include/asm/stacktrace.h | 9 +++++++++ arch/arm/kernel/return_address.c | 4 ++++ arch/arm/kernel/stacktrace.c | 14 ++++++++++++++ 4 files changed, 28 insertions(+) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index fc196421b2ce..bb4f1872967c 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -3,6 +3,7 @@ config ARM bool default y select ARCH_32BIT_OFF_T + select ARCH_CORRECT_STACKTRACE_ON_KRETPROBE if HAVE_KRETPROBES && FRAME_POINTER && !ARM_UNWIND select ARCH_HAS_BINFMT_FLAT select ARCH_HAS_DEBUG_VIRTUAL if MMU select ARCH_HAS_DMA_WRITE_COMBINE if !ARM_DMA_MEM_BUFFERABLE diff --git a/arch/arm/include/asm/stacktrace.h b/arch/arm/include/asm/stacktrace.h index 2d76a2e29f05..8f54f9ad8a9b 100644 --- a/arch/arm/include/asm/stacktrace.h +++ b/arch/arm/include/asm/stacktrace.h @@ -3,6 +3,7 @@ #define __ASM_STACKTRACE_H #include +#include struct stackframe { /* @@ -13,6 +14,10 @@ struct stackframe { unsigned long sp; unsigned long lr; unsigned long pc; +#ifdef CONFIG_KRETPROBES + struct llist_node *kr_cur; + struct task_struct *tsk; +#endif }; static __always_inline @@ -22,6 +27,10 @@ void arm_get_current_stackframe(struct pt_regs *regs, struct stackframe *frame) frame->sp = regs->ARM_sp; frame->lr = regs->ARM_lr; frame->pc = regs->ARM_pc; +#ifdef CONFIG_KRETPROBES + frame->kr_cur = NULL; + frame->tsk = current; +#endif } extern int unwind_frame(struct stackframe *frame); diff --git a/arch/arm/kernel/return_address.c b/arch/arm/kernel/return_address.c index 7b42ac010fdf..00c11579406c 100644 --- a/arch/arm/kernel/return_address.c +++ b/arch/arm/kernel/return_address.c @@ -42,6 +42,10 @@ void *return_address(unsigned int level) frame.sp = current_stack_pointer; frame.lr = (unsigned long)__builtin_return_address(0); frame.pc = (unsigned long)return_address; +#ifdef CONFIG_KRETPROBES + frame.kr_cur = NULL; + frame.tsk = current; +#endif walk_stackframe(&frame, save_return_addr, &data); diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c index db798eac7431..75e905508f27 100644 --- a/arch/arm/kernel/stacktrace.c +++ b/arch/arm/kernel/stacktrace.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only #include +#include #include #include #include @@ -65,6 +66,11 @@ int notrace unwind_frame(struct stackframe *frame) frame->sp = *(unsigned long *)(fp - 8); frame->pc = *(unsigned long *)(fp - 4); #endif +#ifdef CONFIG_KRETPROBES + if (is_kretprobe_trampoline(frame->pc)) + frame->pc = kretprobe_find_ret_addr(frame->tsk, + (void *)frame->fp, &frame->kr_cur); +#endif return 0; } @@ -156,6 +162,10 @@ static noinline void __save_stack_trace(struct task_struct *tsk, frame.lr = (unsigned long)__builtin_return_address(0); frame.pc = (unsigned long)__save_stack_trace; } +#ifdef CONFIG_KRETPROBES + frame.kr_cur = NULL; + frame.tsk = tsk; +#endif walk_stackframe(&frame, save_trace, &data); } @@ -173,6 +183,10 @@ void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace) frame.sp = regs->ARM_sp; frame.lr = regs->ARM_lr; frame.pc = regs->ARM_pc; +#ifdef CONFIG_KRETPROBES + frame.kr_cur = NULL; + frame.tsk = current; +#endif walk_stackframe(&frame, save_trace, &data); } From patchwork Fri Oct 15 12:52:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Masami Hiramatsu (Google)" X-Patchwork-Id: 12561461 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id EA3E0C433F5 for ; Fri, 15 Oct 2021 13:01:58 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B3E9A61090 for ; Fri, 15 Oct 2021 13:01:58 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org B3E9A61090 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=kernel.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=xwQ0yTQeRD3FjSkg9CpcMm8kuJEc5nJAc4iZXnxD9/0=; b=Dcuy1haN0+N9wT TolFa1jkZmFDWHk3MWA6TIZVEdnT44wCshVhlv3GCiplh1yul3OQsn7TMkDhonwlBJPkntO6eO6/o LYM2qk9CQqGGJfLy/pwUskVY4LW4i7/4Lb49o+o9W31Epr6/tZdRZu/CADVAr4z8DrNCze7gH+OAr fgNP/uMqBuIJlbeeIwpuaj3TfIIT8qpaDYC/wLDv23cGuUl8Fgq6gdgnj5yKCP6j2XC6Q51X9d/UQ Nsg3FY+/IpKdniyvG7gNvgU17TIM4SlVp/Xb8dkGZRu5hQaDLg5UsPm5+vE9igrlDCDhqyoHglAEk 8IhAXzf3a5l4LgQbQ0qA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mbMoQ-0075bl-Hu; Fri, 15 Oct 2021 12:59:51 +0000 Received: from mail.kernel.org ([198.145.29.99]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mbMh8-0071nc-4P for linux-arm-kernel@lists.infradead.org; Fri, 15 Oct 2021 12:52:19 +0000 Received: by mail.kernel.org (Postfix) with ESMTPSA id 50A1160ED4; Fri, 15 Oct 2021 12:52:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1634302337; bh=EyoCpAJO1kfofsL3gEQly+uRiLZYa9weOYK4M4P9yI0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=eAwTenk213ykTtTC152Z1rE9becZKfqIURox5GSsXUTQhD8h83iNO+T5nThet9reh QRLUogxGqTC9Dr3s0HsmsidnW9eAQkF4PP6iFymRVXDNj6vreQ87Y5UFuRE5Dbwr47 yP7HJbxtwDjv/Nvxsz05dDwUP+iBHKdbxyfYpcwkO7vgqYI+iLWYPm9umo8u/jSv9t zytO/2EcwDoKtZLtBiSuP4B03ByfGsoOrpWH0vlm9rwKr6jU4oppKH8Hwkm1EmaWYm uGpWLDTyK3sotdAP9mQ2HyunkIeKdOZ/Am6238FRT7OmRS4O/9Xo49TRmCAXAiDoCC ZCxjqLHWdxd+Q== From: Masami Hiramatsu To: Steven Rostedt Cc: "Naveen N . Rao" , Ananth N Mavinakayanahalli , Ingo Molnar , linux-kernel@vger.kernel.org, mhiramat@kernel.org, Sven Schnelle , Catalin Marinas , Will Deacon , Russell King , Nathan Chancellor , Nick Desaulniers , linux-arm-kernel@lists.infradead.org Subject: [PATCH 10/10] [RFC] arm64: kprobes: Detect error of kretprobe return address fixup Date: Fri, 15 Oct 2021 21:52:14 +0900 Message-Id: <163430233451.459050.14342207133770952671.stgit@devnote2> X-Mailer: git-send-email 2.25.1 In-Reply-To: <163430224341.459050.2369208860773018092.stgit@devnote2> References: <163430224341.459050.2369208860773018092.stgit@devnote2> User-Agent: StGit/0.19 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211015_055218_259328_71286F1A X-CRM114-Status: GOOD ( 20.56 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add kretprobe_next_ret_addr() which can detect errors in the given parameter or the kretprobe_instance list, and call it from arm64 stacktrace. This kretprobe_next_ret_addr() will return following errors when it detects; - -EINVAL if @cur is NULL (caller issue) - -ENOENT if there is no next correct return address (either kprobes or caller issue) - -EILSEQ if the next currect return address is there but doesn't match the framepointer (maybe caller issue) Thus the caller must check the error and handle it. On arm64, this tries to handle the errors and show it on the log. Suggested-by: Mark Rutland Signed-off-by: Masami Hiramatsu --- arch/arm64/kernel/stacktrace.c | 10 +++++++- include/linux/kprobes.h | 2 ++ kernel/kprobes.c | 49 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c index c30624fff6ac..e2f9f479da99 100644 --- a/arch/arm64/kernel/stacktrace.c +++ b/arch/arm64/kernel/stacktrace.c @@ -133,8 +133,14 @@ int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame) } #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ #ifdef CONFIG_KRETPROBES - if (is_kretprobe_trampoline(frame->pc)) - frame->pc = kretprobe_find_ret_addr(tsk, (void *)frame->fp, &frame->kr_cur); + if (is_kretprobe_trampoline(frame->pc)) { + void *ret = kretprobe_next_ret_addr(tsk, (void *)frame->fp, &frame->kr_cur); + /* There must be a bug in this unwinder or kretprobe. */ + if (WARN_ON_ONCE(IS_ERR(ret))) + pr_err("Kretprobe_trampoline recovery failed (%d)\n", PTR_ERR(ret)); + else + frame->pc = (unsigned long)ret; + } #endif frame->pc = ptrauth_strip_insn_pac(frame->pc); diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index e974caf39d3e..8133455c3522 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h @@ -516,6 +516,8 @@ static nokprobe_inline bool is_kretprobe_trampoline(unsigned long addr) unsigned long kretprobe_find_ret_addr(struct task_struct *tsk, void *fp, struct llist_node **cur); +kprobe_opcode_t *kretprobe_next_ret_addr(struct task_struct *tsk, void *fp, + struct llist_node **cur); #else static nokprobe_inline bool is_kretprobe_trampoline(unsigned long addr) { diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 4676627cb066..c57168753467 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -1922,6 +1922,55 @@ unsigned long kretprobe_find_ret_addr(struct task_struct *tsk, void *fp, } NOKPROBE_SYMBOL(kretprobe_find_ret_addr); +/** + * kretprobe_next_ret_addr -- Find next correct return address from @cur + * @tsk: Target task + * @fp: A framepointer to verify + * @cur: a storage and the base point of the loop cursor. + * + * Find the next correct return address modified by a kretprobe on @tsk from + * the entry which points *@cur. If it finds the next currect return address + * whose framepointer matches @fp, returns the return address. + * If the next current return address's framepointer doesn't match @fp, this + * returns ERR_PTR(-EILSEQ). If the *@cur is the end of the kretprobe_instance + * list, returns ERR_PTR(-ENOENT). If the @cur is NULL, returns ERR_PTR(-EINVAL). + * The @tsk must be 'current' or a task which is not running. @fp is used for + * verifying the framepointer which recorded with the correct return address + * (kretprobe_instance::fp field.) + * The @cur is a loop cursor for searching the kretprobe return addresses on + * the @tsk. If *@cur is NULL, this returns the top entry of the correct return + * address. + */ +kprobe_opcode_t *kretprobe_next_ret_addr(struct task_struct *tsk, void *fp, + struct llist_node **cur) +{ + struct kretprobe_instance *ri = NULL; + kprobe_opcode_t *ret; + + if (WARN_ON_ONCE(!cur)) + return ERR_PTR(-EINVAL); + + if (*cur) { + /* This returns the next correct return address */ + ret = __kretprobe_find_ret_addr(tsk, cur); + if (!ret) + return ERR_PTR(-ENOENT); + ri = container_of(*cur, struct kretprobe_instance, llist); + return ri->fp == fp ? ret : ERR_PTR(-EILSEQ); + } + + /* If this is the first try, find the FP-matched entry */ + do { + ret = __kretprobe_find_ret_addr(tsk, cur); + if (!ret) + return ERR_PTR(-ENOENT); + ri = container_of(*cur, struct kretprobe_instance, llist); + } while (ri->fp != fp); + + return ret; +} +NOKPROBE_SYMBOL(kretprobe_next_ret_addr); + void __weak arch_kretprobe_fixup_return(struct pt_regs *regs, kprobe_opcode_t *correct_ret_addr) {