From patchwork Wed Oct 19 08:34:36 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greg KH X-Patchwork-Id: 4961 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:4ac7:0:0:0:0:0 with SMTP id y7csp226622wrs; Wed, 19 Oct 2022 02:46:25 -0700 (PDT) X-Google-Smtp-Source: AMsMyM6kw6UvCmfu2tQFx8kllI5DHHYgxhaVDHEDV6OAP3E3oKoXthpSm/WiaFm/iH6lTxuclAYU X-Received: by 2002:a05:6a00:1d26:b0:54e:8c81:9f64 with SMTP id a38-20020a056a001d2600b0054e8c819f64mr7802688pfx.58.1666172784843; Wed, 19 Oct 2022 02:46:24 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1666172784; cv=none; d=google.com; s=arc-20160816; b=eIcWPQRuses+u3BOl5V/J5iD9jFISg8iuN9FhxtkLxTVXjmYvrc+UKDW5Rjq7nV+FK QJiw+0mFW4MUAVjrTV4MkUI0T4OgPX2pK1xJoDqLwd7bsXE31O6p9KJxuBVtBx1wRoPV nlMu/MD9bybG5DqiPmYKGXF/jo10IOMuBf/0W0F13Kq3/X5r88LOQYzpanqz5PGIzq3E LQEKZ0YqM8iNrgI/LQYKl2TRBDK6sP4H/wfp4jz1xQMUpXugpGZ5m3dnGoq+SBmM6x+K Qe39qdysJzPFUo8KCBVw6zMM7pi2GIG5DH3PUl1hK/09iB94rhmslu9ERisrUAbvM3cK KAWw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=bH4dHZzbIwvguSxePi0OwlXmu34A5nrw9qglcwJmnB4=; b=A9Sckg3sRoKfmpxbKXxy/rD9q20QeoP5rHeDUmPHSQNzr5vGqfLmRV37h9g35A5b+a MxKSP6H0aAC/X6POx+9QNTj3GPLXXDXqlIQE8lK3kzOaCu3olnkei7eogq4EUDM9VBoC VSNd/yYKLOlAnl5TXZX4Bf8Wa0no4WAgx/qTHa/Ol9n7MPm54ywYq7BfLgIEwqkgru2c 9THLAnFAOCxJGl3AllBkg3nsrX5/LCIsalYmhK/4DeFHzxWduYzH38Jmr/UiHe9Q9tzD Aj9WAWTomV50HfRoPzbaLroom9TzuhGmKntxPI7Y+IYar/02UEN5d4hKI+qMMsFRM5T9 C1fw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=RM78CWkp; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id a7-20020a170902710700b00182ecf96250si15482570pll.550.2022.10.19.02.46.07; Wed, 19 Oct 2022 02:46:24 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=RM78CWkp; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233971AbiJSJne (ORCPT + 99 others); Wed, 19 Oct 2022 05:43:34 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33184 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234458AbiJSJk2 (ORCPT ); Wed, 19 Oct 2022 05:40:28 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4BF09F0191; Wed, 19 Oct 2022 02:16:45 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 6037C61777; Wed, 19 Oct 2022 09:14:40 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 714F4C433B5; Wed, 19 Oct 2022 09:14:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1666170879; bh=eHV1aJFxZYib1ONBCUtCKxxKWY0nN7MLKb5IBx+tpRE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RM78CWkpXU/CmRjYjFdhaX6nS/nMiAbVyY6CcrZo+ZD5fyVSqfiB4+CuXzPR8ZNIi jQPUuDcgomP47rr1C3suvZjq+Bj+qYDHtaUBqGP5BiD0rQ1MneXV2Lz+nsmBf3cjPv IjPo2hO/1ztW6WPjJaF317lzphIKqUHVxjWyQ4hA= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Li Huafei , Linus Waleij , "Russell King (Oracle)" , Sasha Levin Subject: [PATCH 6.0 789/862] ARM: 9233/1: stacktrace: Skip frame pointer boundary check for call_with_stack() Date: Wed, 19 Oct 2022 10:34:36 +0200 Message-Id: <20221019083324.769545934@linuxfoundation.org> X-Mailer: git-send-email 2.38.0 In-Reply-To: <20221019083249.951566199@linuxfoundation.org> References: <20221019083249.951566199@linuxfoundation.org> User-Agent: quilt/0.67 MIME-Version: 1.0 X-Spam-Status: No, score=-7.4 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1747108794018982329?= X-GMAIL-MSGID: =?utf-8?q?1747108794018982329?= From: Li Huafei [ Upstream commit 5854e4d8530e6ed4c2532a71a6b0474e199d44dd ] When using the frame pointer unwinder, it was found that the stack trace output of stack_trace_save() is incomplete if the stack contains call_with_stack(): [0x7f00002c] dump_stack_task+0x2c/0x90 [hrtimer] [0x7f0000a0] hrtimer_hander+0x10/0x18 [hrtimer] [0x801a67f0] __hrtimer_run_queues+0x1b0/0x3b4 [0x801a7350] hrtimer_run_queues+0xc4/0xd8 [0x801a597c] update_process_times+0x3c/0x88 [0x801b5a98] tick_periodic+0x50/0xd8 [0x801b5bf4] tick_handle_periodic+0x24/0x84 [0x8010ffc4] twd_handler+0x38/0x48 [0x8017d220] handle_percpu_devid_irq+0xa8/0x244 [0x80176e9c] generic_handle_domain_irq+0x2c/0x3c [0x8052e3a8] gic_handle_irq+0x7c/0x90 [0x808ab15c] generic_handle_arch_irq+0x60/0x80 [0x8051191c] call_with_stack+0x1c/0x20 For the frame pointer unwinder, unwind_frame() checks stackframe::fp by stackframe::sp. Since call_with_stack() switches the SP from one stack to another, stackframe::fp and stackframe: :sp will point to different stacks, so we can no longer check stackframe::fp by stackframe::sp. Skip checking stackframe::fp at this point to avoid this problem. Signed-off-by: Li Huafei Reviewed-by: Linus Waleij Signed-off-by: Russell King (Oracle) Signed-off-by: Sasha Levin --- arch/arm/kernel/stacktrace.c | 40 ++++++++++++++++++++++++++++------ arch/arm/lib/call_with_stack.S | 2 ++ 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c index d0fa2037460a..af87040b0353 100644 --- a/arch/arm/kernel/stacktrace.c +++ b/arch/arm/kernel/stacktrace.c @@ -9,6 +9,8 @@ #include #include +#include "reboot.h" + #if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND) /* * Unwind the current stack frame and store the new register values in the @@ -39,29 +41,53 @@ * Note that with framepointer enabled, even the leaf functions have the same * prologue and epilogue, therefore we can ignore the LR value in this case. */ -int notrace unwind_frame(struct stackframe *frame) + +extern unsigned long call_with_stack_end; + +static int frame_pointer_check(struct stackframe *frame) { unsigned long high, low; unsigned long fp = frame->fp; + unsigned long pc = frame->pc; + + /* + * call_with_stack() is the only place we allow SP to jump from one + * stack to another, with FP and SP pointing to different stacks, + * skipping the FP boundary check at this point. + */ + if (pc >= (unsigned long)&call_with_stack && + pc < (unsigned long)&call_with_stack_end) + return 0; /* only go to a higher address on the stack */ low = frame->sp; high = ALIGN(low, THREAD_SIZE); -#ifdef CONFIG_CC_IS_CLANG /* check current frame pointer is within bounds */ +#ifdef CONFIG_CC_IS_CLANG if (fp < low + 4 || fp > high - 4) return -EINVAL; - - frame->sp = frame->fp; - frame->fp = READ_ONCE_NOCHECK(*(unsigned long *)(fp)); - frame->pc = READ_ONCE_NOCHECK(*(unsigned long *)(fp + 4)); #else - /* check current frame pointer is within bounds */ if (fp < low + 12 || fp > high - 4) return -EINVAL; +#endif + + return 0; +} + +int notrace unwind_frame(struct stackframe *frame) +{ + unsigned long fp = frame->fp; + + if (frame_pointer_check(frame)) + return -EINVAL; /* restore the registers from the stack frame */ +#ifdef CONFIG_CC_IS_CLANG + frame->sp = frame->fp; + frame->fp = READ_ONCE_NOCHECK(*(unsigned long *)(fp)); + frame->pc = READ_ONCE_NOCHECK(*(unsigned long *)(fp + 4)); +#else frame->fp = READ_ONCE_NOCHECK(*(unsigned long *)(fp - 12)); frame->sp = READ_ONCE_NOCHECK(*(unsigned long *)(fp - 8)); frame->pc = READ_ONCE_NOCHECK(*(unsigned long *)(fp - 4)); diff --git a/arch/arm/lib/call_with_stack.S b/arch/arm/lib/call_with_stack.S index 0a268a6c513c..5030d4e8d126 100644 --- a/arch/arm/lib/call_with_stack.S +++ b/arch/arm/lib/call_with_stack.S @@ -46,4 +46,6 @@ UNWIND( .setfp fpreg, sp ) pop {fpreg, pc} UNWIND( .fnend ) #endif + .globl call_with_stack_end +call_with_stack_end: ENDPROC(call_with_stack)