Received: by 2002:a05:6a10:9848:0:0:0:0 with SMTP id x8csp1637866pxf; Fri, 19 Mar 2021 11:43:00 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzcW8hPn7USS/fDZuYwRJHtdq8tbbDRa2EoH18dT2INi7zW5QJ23hse3PQWCrxYQwRbldjE X-Received: by 2002:a05:6402:646:: with SMTP id u6mr11468556edx.250.1616179379880; Fri, 19 Mar 2021 11:42:59 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1616179379; cv=none; d=google.com; s=arc-20160816; b=0wxbIwZPDHj8PrRrlkkKsO3tuTH2+to8uFCVFwh8VbK55bIhbZfd48bihl0YhGKlDB R1s9iVGNew6q+xA2lsWu0UNuYwaSQdVOzUZvMBoz4QTjXAkXOliAsav3aMCVfwsqcr66 dEGf2gAwz3WTlYRDSf3m9Q+RClXJhtnGnVbOzj3fhCr7RLyNozv/JYi4NM6eu8YuCxqZ ZEnLkI/QGX4nkU+zUr+GHykyVFYMSMbL9sG/l7/yqV2Sfnal5V02SMaSAR6V2g0aD1EK GdI3Mepnep1e3E7zgv1p2dkgFSQe58U6goheWjeSJGD9ttaJOQ/C4oWuXvx+JbGDNNi+ K2Ug== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:message-id:date:subject:cc:to:from; bh=Z3jYc7esYleg3lYjWeEJHXdIhgVA/HZ9cOXxwFUUF+8=; b=kS4loHWNcl+Ld0sTX5PSPhaiFeQc9VlufJ3/1HzosFO9XfuWYJ2Yhbph+L92NH5R86 PiDspRfNi6JeyeQqoZLRzM9zpis4Mc+HeX7eMyPDB+LkOE4P0sbRBBWH9EUgOgQkZOF+ r8G3yQVq+jbMnscs0H0IOGudzBN2mZG8i3hHBGxLy+J7pKt50zzP1woU8xTv06wH/LVn 3Xvhx9naZ6JShlAAZToIHg76VZ+2Jxv+R3bYP5v6MJzvUxDOzBH0/+OH1WB8dRr79XkR 4eJBb0Ivx3ZwZSLphofdoNrh6ahoV5auHEgyan3/Rq+/B9Jyk/IijDiSKHB3EgOZrAhu GlXQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id cd22si4494692ejb.384.2021.03.19.11.42.37; Fri, 19 Mar 2021 11:42:59 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230422AbhCSSlh (ORCPT + 99 others); Fri, 19 Mar 2021 14:41:37 -0400 Received: from foss.arm.com ([217.140.110.172]:60894 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230226AbhCSSlV (ORCPT ); Fri, 19 Mar 2021 14:41:21 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 67D5A31B; Fri, 19 Mar 2021 11:41:21 -0700 (PDT) Received: from lakrids.cambridge.arm.com (usa-sjc-imap-foss1.foss.arm.com [10.121.207.14]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 4BEFE3F792; Fri, 19 Mar 2021 11:41:20 -0700 (PDT) From: Mark Rutland To: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: Mark Rutland , Catalin Marinas , Chen Jun , Marco Elver , Mark Brown , Will Deacon Subject: [PATCH] arm64: stacktrace: don't trace arch_stack_walk() Date: Fri, 19 Mar 2021 18:41:06 +0000 Message-Id: <20210319184106.5688-1-mark.rutland@arm.com> X-Mailer: git-send-email 2.11.0 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org We recently converted arm64 to use arch_stack_walk() in commit: 5fc57df2f6fd ("arm64: stacktrace: Convert to ARCH_STACKWALK") The core stacktrace code expects that (when tracing the current task) arch_stack_walk() starts a trace at its caller, and does not include itself in the trace. However, arm64's arch_stack_walk() includes itself, and so traces include one more entry than callers expect. The core stacktrace code which calls arch_stack_walk() tries to skip a number of entries to prevent itself appearing in a trace, and the additional entry prevents skipping one of the core stacktrace functions, leaving this in the trace unexpectedly. We can fix this by having arm64's arch_stack_walk() begin the trace with its caller. The first value returned by the trace will be __builtin_return_address(0), i.e. the caller of arch_stack_walk(). The first frame record to be unwound will be __builtin_frame_address(1), i.e. the caller's frame record. To prevent surprises, arch_stack_walk() is also marked noinline. While __builtin_frame_address(1) is not safe in portable code, local GCC developers have confirmed that it is safe on arm64. To find the caller's frame record, the builtin can safely dereference the current function's frame record or (in theory) could stash the original FP into another GPR at function entry time, neither of which are problematic. Prior to this patch, the tracing code would unexpectedly show up in traces of the current task, e.g. | # cat /proc/self/stack | [<0>] stack_trace_save_tsk+0x98/0x100 | [<0>] proc_pid_stack+0xb4/0x130 | [<0>] proc_single_show+0x60/0x110 | [<0>] seq_read_iter+0x230/0x4d0 | [<0>] seq_read+0xdc/0x130 | [<0>] vfs_read+0xac/0x1e0 | [<0>] ksys_read+0x6c/0xfc | [<0>] __arm64_sys_read+0x20/0x30 | [<0>] el0_svc_common.constprop.0+0x60/0x120 | [<0>] do_el0_svc+0x24/0x90 | [<0>] el0_svc+0x2c/0x54 | [<0>] el0_sync_handler+0x1a4/0x1b0 | [<0>] el0_sync+0x170/0x180 After this patch, the tracing code will not show up in such traces: | # cat /proc/self/stack | [<0>] proc_pid_stack+0xb4/0x130 | [<0>] proc_single_show+0x60/0x110 | [<0>] seq_read_iter+0x230/0x4d0 | [<0>] seq_read+0xdc/0x130 | [<0>] vfs_read+0xac/0x1e0 | [<0>] ksys_read+0x6c/0xfc | [<0>] __arm64_sys_read+0x20/0x30 | [<0>] el0_svc_common.constprop.0+0x60/0x120 | [<0>] do_el0_svc+0x24/0x90 | [<0>] el0_svc+0x2c/0x54 | [<0>] el0_sync_handler+0x1a4/0x1b0 | [<0>] el0_sync+0x170/0x180 Erring on the side of caution, I've given this a spin with a bunch of toolchains, verifying the output of /proc/self/stack and checking that the assembly looked sound. For GCC (where we require version 5.1.0 or later) I tested with the kernel.org crosstool binares for versions 5.5.0, 6.4.0, 6.5.0, 7.3.0, 7.5.0, 8.1.0, 8.3.0, 8.4.0, 9.2.0, and 10.1.0. For clang (where we require version 10.0.1 or later) I tested with the llvm.org binary releases of 11.0.0, and 11.0.1. Fixes: 5fc57df2f6fd ("arm64: stacktrace: Convert to ARCH_STACKWALK") Signed-off-by: Mark Rutland Cc: Catalin Marinas Cc: Chen Jun Cc: Marco Elver Cc: Mark Brown Cc: Will Deacon --- arch/arm64/kernel/stacktrace.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c index ad20981dfda4..d55bdfb7789c 100644 --- a/arch/arm64/kernel/stacktrace.c +++ b/arch/arm64/kernel/stacktrace.c @@ -194,8 +194,9 @@ void show_stack(struct task_struct *tsk, unsigned long *sp, const char *loglvl) #ifdef CONFIG_STACKTRACE -void arch_stack_walk(stack_trace_consume_fn consume_entry, void *cookie, - struct task_struct *task, struct pt_regs *regs) +noinline void arch_stack_walk(stack_trace_consume_fn consume_entry, + void *cookie, struct task_struct *task, + struct pt_regs *regs) { struct stackframe frame; @@ -203,8 +204,8 @@ void arch_stack_walk(stack_trace_consume_fn consume_entry, void *cookie, start_backtrace(&frame, regs->regs[29], regs->pc); else if (task == current) start_backtrace(&frame, - (unsigned long)__builtin_frame_address(0), - (unsigned long)arch_stack_walk); + (unsigned long)__builtin_frame_address(1), + (unsigned long)__builtin_return_address(0)); else start_backtrace(&frame, thread_saved_fp(task), thread_saved_pc(task)); -- 2.11.0