From patchwork Thu Jun 6 12:54:00 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Rutland X-Patchwork-Id: 10979505 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 89C4876 for ; Thu, 6 Jun 2019 12:54:26 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 790A328899 for ; Thu, 6 Jun 2019 12:54:26 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6D7FF288AC; Thu, 6 Jun 2019 12:54:26 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 09A2D2887D for ; Thu, 6 Jun 2019 12:54:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=3mC5f42dpwf5fDNWM0FIP3jV8Evdm4fm6dI+sE9xdtI=; b=t+R/6M8Io13OYTuE+9rsuXz4iV md/dWlthgWtzJIYHBprryA3pnpwuxYqtoCSkd7wxtH9N+zJYCfwiFzRYgtcnlrlML/exnUx/FC/+h aPS3EyqUwnmaG1/wldE1WYtOCz9+Xs7o8iZGrFDfPLIiyTA1SUQUcwRs0Nktlrp+1/z3QloSeKj57 DF1uqYMX+sz+SlUBQvUBYEidDxVgoT4fmH+4bsq5tVLmVls3GgRCO5ZyF9o5LI7u58fwZ7tzNkerD kWa3+P/4Tc+XK8DiRwyCwaGrfADGcev6xMZ2Xz3uU9mFxl41Ry813YU7iANu7TB73bl3hPIJYjYqW iyAYSlsA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1hYruS-0002gI-5m; Thu, 06 Jun 2019 12:54:24 +0000 Received: from usa-sjc-mx-foss1.foss.arm.com ([217.140.101.70] helo=foss.arm.com) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1hYruO-0002dP-VO for linux-arm-kernel@lists.infradead.org; Thu, 06 Jun 2019 12:54:22 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id A5BB2374; Thu, 6 Jun 2019 05:54:20 -0700 (PDT) Received: from lakrids.cambridge.arm.com (usa-sjc-imap-foss1.foss.arm.com [10.72.51.249]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 257413F5AF; Thu, 6 Jun 2019 05:54:19 -0700 (PDT) From: Mark Rutland To: linux-arm-kernel@lists.infradead.org Subject: [PATCH 1/3] arm64: stacktrace: Constify stacktrace.h functions Date: Thu, 6 Jun 2019 13:54:00 +0100 Message-Id: <20190606125402.10229-2-mark.rutland@arm.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190606125402.10229-1-mark.rutland@arm.com> References: <20190606125402.10229-1-mark.rutland@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190606_055421_018677_65DC25CD X-CRM114-Status: GOOD ( 12.43 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mark.rutland@arm.com, tengfeif@codeaurora.org, catalin.marinas@arm.com, will.deacon@arm.com, james.morse@arm.com, Dave Martin MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP From: Dave Martin on_accessible_stack() and on_task_stack() shouldn't (and don't) modify their task argument, so it can be const. This patch adds the appropriate modifiers. Whitespace violations in the parameter lists are fixed at the same time. No functional change. Signed-off-by: Dave Martin [Mark: fixup const location, whitespace] Signed-off-by: Mark Rutland --- arch/arm64/include/asm/stacktrace.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/arch/arm64/include/asm/stacktrace.h b/arch/arm64/include/asm/stacktrace.h index e86737b7c924..4dd569592e65 100644 --- a/arch/arm64/include/asm/stacktrace.h +++ b/arch/arm64/include/asm/stacktrace.h @@ -75,8 +75,9 @@ static inline bool on_irq_stack(unsigned long sp, return true; } -static inline bool on_task_stack(struct task_struct *tsk, unsigned long sp, - struct stack_info *info) +static inline bool on_task_stack(const struct task_struct *tsk, + unsigned long sp, + struct stack_info *info) { unsigned long low = (unsigned long)task_stack_page(tsk); unsigned long high = low + THREAD_SIZE; @@ -123,9 +124,9 @@ static inline bool on_overflow_stack(unsigned long sp, * We can only safely access per-cpu stacks from current in a non-preemptible * context. */ -static inline bool on_accessible_stack(struct task_struct *tsk, - unsigned long sp, - struct stack_info *info) +static inline bool on_accessible_stack(const struct task_struct *tsk, + unsigned long sp, + struct stack_info *info) { if (on_task_stack(tsk, sp, info)) return true; From patchwork Thu Jun 6 12:54:01 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Rutland X-Patchwork-Id: 10979507 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 92E4A76 for ; Thu, 6 Jun 2019 12:54:42 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7E3D1288B5 for ; Thu, 6 Jun 2019 12:54:42 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 71DB8288AC; Thu, 6 Jun 2019 12:54:42 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 0535B28913 for ; Thu, 6 Jun 2019 12:54:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=68EhdPI+BC11R3gi7pq+yEo3Wq6LRlO5PTTNFpT4F2U=; b=gSIT1OcbRqfuucxVEiqpgJ9E9N 07t00kDLHrq3NU7BMY9M5KNoxjMZetDNKQcvA2w3KGZHPOft2fDhp/aa5HY3Aa4likJRy43gkE4j6 xzK9zqKeI/dkC2IvxB6XsvqjOn2LCnQP+jIoh0c8yfJk3r/uyNlcFNRVKB72wA9ldPybDjfY0nl+9 8sjf4cnuRhjNKgz2mNj/fCFS8221ssl3Rd1OOamV5ntJ9nOBTs6drMxf1MFyHNXc/oxuRX3PIplFj yL83a0ntfOEJoCxoImRI956Gan7SZ6kX7f26N+Qe1nhcwTCnJkS2w/+SR+Tw3oZ3/h+pTzF6UfI89 sshdVJog==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1hYrue-0002ve-DU; Thu, 06 Jun 2019 12:54:36 +0000 Received: from foss.arm.com ([217.140.101.70]) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1hYruS-0002hH-Bm for linux-arm-kernel@lists.infradead.org; Thu, 06 Jun 2019 12:54:29 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id D13D9374; Thu, 6 Jun 2019 05:54:23 -0700 (PDT) Received: from lakrids.cambridge.arm.com (usa-sjc-imap-foss1.foss.arm.com [10.72.51.249]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 56BA93F5AF; Thu, 6 Jun 2019 05:54:22 -0700 (PDT) From: Mark Rutland To: linux-arm-kernel@lists.infradead.org Subject: [PATCH 2/3] arm64: stacktrace: Factor out backtrace initialisation Date: Thu, 6 Jun 2019 13:54:01 +0100 Message-Id: <20190606125402.10229-3-mark.rutland@arm.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190606125402.10229-1-mark.rutland@arm.com> References: <20190606125402.10229-1-mark.rutland@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190606_055424_859416_ABC99EDD X-CRM114-Status: GOOD ( 13.30 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mark.rutland@arm.com, tengfeif@codeaurora.org, catalin.marinas@arm.com, will.deacon@arm.com, james.morse@arm.com, Dave Martin MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP From: Dave Martin Some common code is required by each stacktrace user to initialise struct stackframe before the first call to unwind_frame(). In preparation for adding to the common code, this patch factors it out into a separate function start_backtrace(), and modifies the stacktrace callers appropriately. No functional change. Signed-off-by: Dave Martin Signed-off-by: Mark Rutland --- arch/arm64/include/asm/stacktrace.h | 10 ++++++++++ arch/arm64/kernel/process.c | 6 +----- arch/arm64/kernel/time.c | 6 +----- arch/arm64/kernel/traps.c | 13 ++++++------- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/arch/arm64/include/asm/stacktrace.h b/arch/arm64/include/asm/stacktrace.h index 4dd569592e65..18f90bf1385c 100644 --- a/arch/arm64/include/asm/stacktrace.h +++ b/arch/arm64/include/asm/stacktrace.h @@ -142,4 +142,14 @@ static inline bool on_accessible_stack(const struct task_struct *tsk, return false; } +static inline void start_backtrace(struct stackframe *frame, + unsigned long fp, unsigned long pc) +{ + frame->fp = fp; + frame->pc = pc; +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + frame->graph = 0; +#endif +} + #endif /* __ASM_STACKTRACE_H */ diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index 3767fb21a5b8..122d88fccd13 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -509,11 +509,7 @@ unsigned long get_wchan(struct task_struct *p) if (!stack_page) return 0; - frame.fp = thread_saved_fp(p); - frame.pc = thread_saved_pc(p); -#ifdef CONFIG_FUNCTION_GRAPH_TRACER - frame.graph = 0; -#endif + start_backtrace(&frame, thread_saved_fp(p), thread_saved_pc(p)); do { if (unwind_frame(p, &frame)) goto out; diff --git a/arch/arm64/kernel/time.c b/arch/arm64/kernel/time.c index a777ae90044d..aa3489f3a452 100644 --- a/arch/arm64/kernel/time.c +++ b/arch/arm64/kernel/time.c @@ -49,11 +49,7 @@ unsigned long profile_pc(struct pt_regs *regs) if (!in_lock_functions(regs->pc)) return regs->pc; - frame.fp = regs->regs[29]; - frame.pc = regs->pc; -#ifdef CONFIG_FUNCTION_GRAPH_TRACER - frame.graph = 0; -#endif + start_backtrace(&frame, regs->regs[29], regs->pc); do { int ret = unwind_frame(NULL, &frame); if (ret < 0) diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index ade32046f3fe..8053bbed8776 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -119,18 +119,17 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) return; if (tsk == current) { - frame.fp = (unsigned long)__builtin_frame_address(0); - frame.pc = (unsigned long)dump_backtrace; + start_backtrace(&frame, + (unsigned long)__builtin_frame_address(0), + (unsigned long)dump_backtrace); } else { /* * task blocked in __switch_to */ - frame.fp = thread_saved_fp(tsk); - frame.pc = thread_saved_pc(tsk); + start_backtrace(&frame, + thread_saved_fp(tsk), + thread_saved_pc(tsk)); } -#ifdef CONFIG_FUNCTION_GRAPH_TRACER - frame.graph = 0; -#endif printk("Call trace:\n"); do { From patchwork Thu Jun 6 12:54:02 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Rutland X-Patchwork-Id: 10979509 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 77A9176 for ; Thu, 6 Jun 2019 12:54:53 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 67FC52886C for ; Thu, 6 Jun 2019 12:54:53 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5BF4D208C2; Thu, 6 Jun 2019 12:54:53 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id A99442886C for ; Thu, 6 Jun 2019 12:54:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=Lxf8xxRr58e1BYKyF13CKxxYKNCIrkQW1Xm6ub9ngBY=; b=CCG4jFZeA/ENHrZkozvNKFXWdH J/2ArbMX3D+IDL45hTw80HohuStFP/9a26pwh5YR1HxEyTY92pfuJ3Ic+J/n3MRrgfX2ULyvbsksl BRgnDBENWI6j0zhnkC4xJ7LtHbXBoPHGfrOwOItoTuUv4n8MNwLgJWrs4cuulltDQqoUoLMVFCtNd M7NmYNIitrn85JWoh5VeF0Ys1TH8TimKkcMWLktcPj7tVNszmelz3DrFYgnApUITv0oRIvJN2RnmM woZ1TuFkfbpuVNbckF7apGe7pISVJSvG1K/E3iZFkB4Ax2jMmyZXI3P7iBIWkCRiq32gf7rOIoVzF X6b3B8+A==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1hYruo-00036T-9U; Thu, 06 Jun 2019 12:54:46 +0000 Received: from foss.arm.com ([217.140.101.70]) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1hYruV-0002l7-4K for linux-arm-kernel@lists.infradead.org; Thu, 06 Jun 2019 12:54:34 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id D299315A2; Thu, 6 Jun 2019 05:54:26 -0700 (PDT) Received: from lakrids.cambridge.arm.com (usa-sjc-imap-foss1.foss.arm.com [10.72.51.249]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 7B6433F5AF; Thu, 6 Jun 2019 05:54:25 -0700 (PDT) From: Mark Rutland To: linux-arm-kernel@lists.infradead.org Subject: [PATCH 3/3] arm64: stacktrace: better handle corrupted stacks Date: Thu, 6 Jun 2019 13:54:02 +0100 Message-Id: <20190606125402.10229-4-mark.rutland@arm.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190606125402.10229-1-mark.rutland@arm.com> References: <20190606125402.10229-1-mark.rutland@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190606_055427_776366_2A886F5A X-CRM114-Status: GOOD ( 19.46 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mark.rutland@arm.com, tengfeif@codeaurora.org, catalin.marinas@arm.com, will.deacon@arm.com, james.morse@arm.com, dave.martin@arm.com MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP The arm64 stacktrace code is careful to only dereference frame records in valid stack ranges, ensuring that a corrupted frame record won't result in a faulting access. However, it's still possible for corrupt frame records to result in infinite loops in the stacktrace code, which is also undesirable. This patch ensures that we complete a stacktrace in finite time, by keeping track of which stacks we have already completed unwinding, and verifying that if the next frame record is on the same stack, it is at a higher address. Signed-off-by: Mark Rutland Cc: Catalin Marinas Cc: Dave Martin Cc: James Morse Cc: Tengfei Fan Cc: Will Deacon Signed-off-by: James Morse --- arch/arm64/include/asm/stacktrace.h | 34 ++++++++++++++++++++++++++-------- arch/arm64/kernel/process.c | 2 +- arch/arm64/kernel/stacktrace.c | 16 +++++++++++++++- arch/arm64/kernel/time.c | 2 +- arch/arm64/kernel/traps.c | 4 ++-- 5 files changed, 45 insertions(+), 13 deletions(-) diff --git a/arch/arm64/include/asm/stacktrace.h b/arch/arm64/include/asm/stacktrace.h index 18f90bf1385c..4ebf8a8997b0 100644 --- a/arch/arm64/include/asm/stacktrace.h +++ b/arch/arm64/include/asm/stacktrace.h @@ -19,19 +19,12 @@ #include #include #include +#include #include #include #include -struct stackframe { - unsigned long fp; - unsigned long pc; -#ifdef CONFIG_FUNCTION_GRAPH_TRACER - int graph; -#endif -}; - enum stack_type { STACK_TYPE_UNKNOWN, STACK_TYPE_TASK, @@ -39,6 +32,7 @@ enum stack_type { STACK_TYPE_OVERFLOW, STACK_TYPE_SDEI_NORMAL, STACK_TYPE_SDEI_CRITICAL, + __NR_STACK_TYPES }; struct stack_info { @@ -47,6 +41,16 @@ struct stack_info { enum stack_type type; }; +struct stackframe { + unsigned long fp; + unsigned long pc; +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + int graph; +#endif + DECLARE_BITMAP(stacks_done, __NR_STACK_TYPES); + enum stack_type stack_current; +}; + extern int unwind_frame(struct task_struct *tsk, struct stackframe *frame); extern void walk_stackframe(struct task_struct *tsk, struct stackframe *frame, int (*fn)(struct stackframe *, void *), void *data); @@ -128,6 +132,9 @@ static inline bool on_accessible_stack(const struct task_struct *tsk, unsigned long sp, struct stack_info *info) { + if (info) + info->type = STACK_TYPE_UNKNOWN; + if (on_task_stack(tsk, sp, info)) return true; if (tsk != current || preemptible()) @@ -143,13 +150,24 @@ static inline bool on_accessible_stack(const struct task_struct *tsk, } static inline void start_backtrace(struct stackframe *frame, + struct task_struct *tsk, unsigned long fp, unsigned long pc) { + struct stack_info info; + frame->fp = fp; frame->pc = pc; #ifdef CONFIG_FUNCTION_GRAPH_TRACER frame->graph = 0; #endif + bitmap_zero(frame->stacks_done, __NR_STACK_TYPES); + + /* + * We need to prime stack_current for the first unwind, but we can + * ignore the accessibility until the unwind occurs. + */ + on_accessible_stack(tsk, fp, &info); + frame->stack_current = info.type; } #endif /* __ASM_STACKTRACE_H */ diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index 122d88fccd13..ba9441982573 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -509,7 +509,7 @@ unsigned long get_wchan(struct task_struct *p) if (!stack_page) return 0; - start_backtrace(&frame, thread_saved_fp(p), thread_saved_pc(p)); + start_backtrace(&frame, p, thread_saved_fp(p), thread_saved_pc(p)); do { if (unwind_frame(p, &frame)) goto out; diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c index b00ec7d483d1..1c45b33c7474 100644 --- a/arch/arm64/kernel/stacktrace.c +++ b/arch/arm64/kernel/stacktrace.c @@ -43,6 +43,8 @@ int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame) { unsigned long fp = frame->fp; + bool changed_stack = false; + struct stack_info info; if (fp & 0xf) return -EINVAL; @@ -50,12 +52,24 @@ int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame) if (!tsk) tsk = current; - if (!on_accessible_stack(tsk, fp, NULL)) + if (!on_accessible_stack(tsk, fp, &info)) return -EINVAL; + if (test_bit(info.type, frame->stacks_done)) + return -EINVAL; + + if (frame->stack_current != info.type) { + set_bit(frame->stack_current, frame->stacks_done); + frame->stack_current = info.type; + changed_stack = true; + } + frame->fp = READ_ONCE_NOCHECK(*(unsigned long *)(fp)); frame->pc = READ_ONCE_NOCHECK(*(unsigned long *)(fp + 8)); + if (!changed_stack && frame->fp <= fp) + return -EINVAL; + #ifdef CONFIG_FUNCTION_GRAPH_TRACER if (tsk->ret_stack && (frame->pc == (unsigned long)return_to_handler)) { diff --git a/arch/arm64/kernel/time.c b/arch/arm64/kernel/time.c index aa3489f3a452..83f08c7e9464 100644 --- a/arch/arm64/kernel/time.c +++ b/arch/arm64/kernel/time.c @@ -49,7 +49,7 @@ unsigned long profile_pc(struct pt_regs *regs) if (!in_lock_functions(regs->pc)) return regs->pc; - start_backtrace(&frame, regs->regs[29], regs->pc); + start_backtrace(&frame, current, regs->regs[29], regs->pc); do { int ret = unwind_frame(NULL, &frame); if (ret < 0) diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index 8053bbed8776..3bbe1992259e 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -119,14 +119,14 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) return; if (tsk == current) { - start_backtrace(&frame, + start_backtrace(&frame, tsk, (unsigned long)__builtin_frame_address(0), (unsigned long)dump_backtrace); } else { /* * task blocked in __switch_to */ - start_backtrace(&frame, + start_backtrace(&frame, tsk, thread_saved_fp(tsk), thread_saved_pc(tsk)); }