Message ID | 20221019154727.2395-1-jszhang@kernel.org |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:4ac7:0:0:0:0:0 with SMTP id y7csp409523wrs; Wed, 19 Oct 2022 09:10:08 -0700 (PDT) X-Google-Smtp-Source: AMsMyM6yNgCf2YMrzoLg7J51VgoxwFLE5fUy/s1bCoi3UbbpDjbWJxJZXi9jPAZrG6Puw7il4rnw X-Received: by 2002:a17:902:f08c:b0:183:9296:8b65 with SMTP id p12-20020a170902f08c00b0018392968b65mr9540689pla.59.1666195807851; Wed, 19 Oct 2022 09:10:07 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1666195807; cv=none; d=google.com; s=arc-20160816; b=sXIh5ox971Y2djnzybU6bpPQElNmDEol/jOYncXBJOulsmqSL12MzPEz3VhuhHOnOT jrTP5EGOYd1XGhjVzw7zY2Jzu5n8HbizKsAS3DRYdqMxmU9QwfWQVKel9DT84ZO2qjS8 JCOkGxk+e+nRD+UNgNREihahTGOwuxcIJdhlge2n0rFpDnyWjlZALo/dReLvfWmbCYZP VQ/Wu9tG1N+WJPsO8nArbhiaa5OfMo8ZtpaI4QkocA91fJ/bStzKeNEaKb10T9zxqQ3U SwIdg0rnpholnFGqZQyOdLM41OndibRAy9K9iTMblMwwq8Qc8dwBM8se2px7hlhA3NeJ MePg== 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 :message-id:date:subject:cc:to:from:dkim-signature; bh=p6KWbj9I8bNY3vn/X42lwrZTpKWdgIenHyphn6Aqyto=; b=RnNU+SzGkIShZE9ee2jxPyD0T70OBnj+c/6D22/VwofkyCzpzMUNIOWYee1rVIhDlI 5DSB1t4lpFbzKK8cfEaVSSIwWB1zdk8PYb23d7b55c2zCw0yVk7wS47OoCEBbI0LLpPV p6sY11Chqi3e/XCOa67Y0iFvGuyp+uefFRm1pjTzNp7g2T8SVCfoL8hcTBDymYskdqpm DrZLkCRdUIeXdnIBOxm28GRLIQHYJM7uk8dnhkeNHL8r7dEdvphexOFvjlj6BJpihq66 ZApMDQe8Odl+bmaDbdOCCRq54D14qggZi6+CQv2ShS1aZ0OEj/JwQamS8jI+tnYI/JOi ftiQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=LXQ3DBXy; 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=kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id v1-20020a1709028d8100b001755c347071si16527349plo.451.2022.10.19.09.09.53; Wed, 19 Oct 2022 09:10:07 -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=@kernel.org header.s=k20201202 header.b=LXQ3DBXy; 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=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230175AbiJSP7b (ORCPT <rfc822;samuel.l.nystrom@gmail.com> + 99 others); Wed, 19 Oct 2022 11:59:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49110 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231934AbiJSP6e (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Wed, 19 Oct 2022 11:58:34 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 746B21CCCE0 for <linux-kernel@vger.kernel.org>; Wed, 19 Oct 2022 08:57:24 -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 ams.source.kernel.org (Postfix) with ESMTPS id 2653BB824FA for <linux-kernel@vger.kernel.org>; Wed, 19 Oct 2022 15:57:06 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6EF9FC433C1; Wed, 19 Oct 2022 15:57:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1666195024; bh=tl/t0JSFx6B/W7U7U+lCNfIdDELRIvrRpnIkdxf7UO8=; h=From:To:Cc:Subject:Date:From; b=LXQ3DBXykd8cxJe+nDeTMuzZh2SioIauX440gB0kLifBqT436A3SwZ8AqZAu0d5Ks QaH7PcJ7Zc5hE1yZ2imldpdk31TSsBPmyqtqIUmi/FDTM7tlChYsG3UdkuAm43zcOZ RAvDnZZCtCzMzQWa2vGzAFjZlg84MC1gKhu9nK2YdtXDm2qiYt7ZuDVhgD6so4+eab ItBZ4nypwK6bA1YqZxImaHz4C5ugTj8o4tT4JXmFk+xq+iKF2uoHw9fPykRoMDNju8 p4Ah1KhNSiZSfM7VwAmm6T8F5k5PTyhH7sfIJdBw4ZMGoCPp3RMnU1QXuOVwaKr0tn j/GdetFOTgQsA== From: Jisheng Zhang <jszhang@kernel.org> To: Paul Walmsley <paul.walmsley@sifive.com>, Palmer Dabbelt <palmer@dabbelt.com>, Albert Ou <aou@eecs.berkeley.edu> Cc: linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org, Guo Ren <guoren@kernel.org> Subject: [PATCH] riscv: fix race when vmap stack overflow Date: Wed, 19 Oct 2022 23:47:27 +0800 Message-Id: <20221019154727.2395-1-jszhang@kernel.org> X-Mailer: git-send-email 2.37.2 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1747132935666076411?= X-GMAIL-MSGID: =?utf-8?q?1747132935666076411?= |
Series |
riscv: fix race when vmap stack overflow
|
|
Commit Message
Jisheng Zhang
Oct. 19, 2022, 3:47 p.m. UTC
Currently, when detecting vmap stack overflow, riscv firstly switches
to the so called shadow stack, then use this shadow stack to call the
get_overflow_stack() to get the overflow stack. However, there's
a race here if two or more harts use the same shadow stack at the same
time.
To solve this race, we introduce spin_shadow_stack atomic var, which
will make the shadow stack usage serialized.
Fixes: 31da94c25aea ("riscv: add VMAP_STACK overflow detection")
Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
Suggested-by: Guo Ren <guoren@kernel.org>
---
arch/riscv/kernel/entry.S | 4 ++++
arch/riscv/kernel/traps.c | 4 ++++
2 files changed, 8 insertions(+)
Comments
Reviewed-by: Guo Ren <guoren@kernel.org> On Wed, Oct 19, 2022 at 11:57 PM Jisheng Zhang <jszhang@kernel.org> wrote: > > Currently, when detecting vmap stack overflow, riscv firstly switches > to the so called shadow stack, then use this shadow stack to call the > get_overflow_stack() to get the overflow stack. However, there's > a race here if two or more harts use the same shadow stack at the same > time. > > To solve this race, we introduce spin_shadow_stack atomic var, which > will make the shadow stack usage serialized. > > Fixes: 31da94c25aea ("riscv: add VMAP_STACK overflow detection") > Signed-off-by: Jisheng Zhang <jszhang@kernel.org> > Suggested-by: Guo Ren <guoren@kernel.org> > --- > arch/riscv/kernel/entry.S | 4 ++++ > arch/riscv/kernel/traps.c | 4 ++++ > 2 files changed, 8 insertions(+) > > diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S > index b9eda3fcbd6d..7b924b16792b 100644 > --- a/arch/riscv/kernel/entry.S > +++ b/arch/riscv/kernel/entry.S > @@ -404,6 +404,10 @@ handle_syscall_trace_exit: > > #ifdef CONFIG_VMAP_STACK > handle_kernel_stack_overflow: > +1: la sp, spin_shadow_stack > + amoswap.w sp, sp, (sp) > + bnez sp, 1b > + > la sp, shadow_stack > addi sp, sp, SHADOW_OVERFLOW_STACK_SIZE > > diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c > index f3e96d60a2ff..88a54947dffb 100644 > --- a/arch/riscv/kernel/traps.c > +++ b/arch/riscv/kernel/traps.c > @@ -221,11 +221,15 @@ asmlinkage unsigned long get_overflow_stack(void) > OVERFLOW_STACK_SIZE; > } > > +atomic_t spin_shadow_stack; > + > asmlinkage void handle_bad_stack(struct pt_regs *regs) > { > unsigned long tsk_stk = (unsigned long)current->stack; > unsigned long ovf_stk = (unsigned long)this_cpu_ptr(overflow_stack); > > + atomic_set_release(&spin_shadow_stack, 0); > + > console_verbose(); > > pr_emerg("Insufficient stack space to handle exception!\n"); > -- > 2.37.2 >
On Wed, Oct 19, 2022 at 11:57 PM Jisheng Zhang <jszhang@kernel.org> wrote: > > Currently, when detecting vmap stack overflow, riscv firstly switches > to the so called shadow stack, then use this shadow stack to call the > get_overflow_stack() to get the overflow stack. However, there's > a race here if two or more harts use the same shadow stack at the same > time. > > To solve this race, we introduce spin_shadow_stack atomic var, which > will make the shadow stack usage serialized. > > Fixes: 31da94c25aea ("riscv: add VMAP_STACK overflow detection") > Signed-off-by: Jisheng Zhang <jszhang@kernel.org> > Suggested-by: Guo Ren <guoren@kernel.org> > --- > arch/riscv/kernel/entry.S | 4 ++++ > arch/riscv/kernel/traps.c | 4 ++++ > 2 files changed, 8 insertions(+) > > diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S > index b9eda3fcbd6d..7b924b16792b 100644 > --- a/arch/riscv/kernel/entry.S > +++ b/arch/riscv/kernel/entry.S > @@ -404,6 +404,10 @@ handle_syscall_trace_exit: > > #ifdef CONFIG_VMAP_STACK > handle_kernel_stack_overflow: > +1: la sp, spin_shadow_stack > + amoswap.w sp, sp, (sp) If CONFIG_64BIT=y, it would be broken. Because we only hold 32bit of the sp, and the next loop would get the wrong sp value of &spin_shadow_stack. Here is the correction. ----- diff --git a/arch/riscv/include/asm/asm.h b/arch/riscv/include/asm/asm.h index 1b471ff73178..acf563072b8b 100644 --- a/arch/riscv/include/asm/asm.h +++ b/arch/riscv/include/asm/asm.h @@ -23,6 +23,7 @@ #define REG_L __REG_SEL(ld, lw) #define REG_S __REG_SEL(sd, sw) #define REG_SC __REG_SEL(sc.d, sc.w) +#define REG_AMOSWAP __REG_SEL(amoswap.d, amoswap.w) #define REG_ASM __REG_SEL(.dword, .word) #define SZREG __REG_SEL(8, 4) #define LGREG __REG_SEL(3, 2) diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S index b9eda3fcbd6d..ea6b78dac739 100644 --- a/arch/riscv/kernel/entry.S +++ b/arch/riscv/kernel/entry.S @@ -404,6 +404,10 @@ handle_syscall_trace_exit: #ifdef CONFIG_VMAP_STACK handle_kernel_stack_overflow: +1: la sp, spin_shadow_stack + /* Reuse the address as the spin value, so they must be all XLEN's width. */ + REG_AMOSWAP sp, sp, (sp) + bnez sp, 1b + la sp, shadow_stack addi sp, sp, SHADOW_OVERFLOW_STACK_SIZE diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c index f3e96d60a2ff..9e6cc0d63833 100644 --- a/arch/riscv/kernel/traps.c +++ b/arch/riscv/kernel/traps.c @@ -221,11 +221,15 @@ asmlinkage unsigned long get_overflow_stack(void) OVERFLOW_STACK_SIZE; } +unsigned long spin_shadow_stack = 0; + asmlinkage void handle_bad_stack(struct pt_regs *regs) { unsigned long tsk_stk = (unsigned long)current->stack; unsigned long ovf_stk = (unsigned long)this_cpu_ptr(overflow_stack); + smp_store_release(&spin_shadow_stack, 0); + console_verbose(); pr_emerg("Insufficient stack space to handle exception!\n"); > + bnez sp, 1b > + > la sp, shadow_stack > addi sp, sp, SHADOW_OVERFLOW_STACK_SIZE > > diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c > index f3e96d60a2ff..88a54947dffb 100644 > --- a/arch/riscv/kernel/traps.c > +++ b/arch/riscv/kernel/traps.c > @@ -221,11 +221,15 @@ asmlinkage unsigned long get_overflow_stack(void) > OVERFLOW_STACK_SIZE; > } > > +atomic_t spin_shadow_stack; > + > asmlinkage void handle_bad_stack(struct pt_regs *regs) > { > unsigned long tsk_stk = (unsigned long)current->stack; > unsigned long ovf_stk = (unsigned long)this_cpu_ptr(overflow_stack); > > + atomic_set_release(&spin_shadow_stack, 0); > + > console_verbose(); > > pr_emerg("Insufficient stack space to handle exception!\n"); > -- > 2.37.2 > -- Best Regards Guo Ren
On Thu, Oct 20, 2022 at 10:16:47AM +0800, Guo Ren wrote: > On Wed, Oct 19, 2022 at 11:57 PM Jisheng Zhang <jszhang@kernel.org> wrote: > > > > Currently, when detecting vmap stack overflow, riscv firstly switches > > to the so called shadow stack, then use this shadow stack to call the > > get_overflow_stack() to get the overflow stack. However, there's > > a race here if two or more harts use the same shadow stack at the same > > time. > > > > To solve this race, we introduce spin_shadow_stack atomic var, which > > will make the shadow stack usage serialized. > > > > Fixes: 31da94c25aea ("riscv: add VMAP_STACK overflow detection") > > Signed-off-by: Jisheng Zhang <jszhang@kernel.org> > > Suggested-by: Guo Ren <guoren@kernel.org> > > --- > > arch/riscv/kernel/entry.S | 4 ++++ > > arch/riscv/kernel/traps.c | 4 ++++ > > 2 files changed, 8 insertions(+) > > > > diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S > > index b9eda3fcbd6d..7b924b16792b 100644 > > --- a/arch/riscv/kernel/entry.S > > +++ b/arch/riscv/kernel/entry.S > > @@ -404,6 +404,10 @@ handle_syscall_trace_exit: > > > > #ifdef CONFIG_VMAP_STACK > > handle_kernel_stack_overflow: > > +1: la sp, spin_shadow_stack > > + amoswap.w sp, sp, (sp) > If CONFIG_64BIT=y, it would be broken. Because we only hold 32bit of > the sp, and the next loop would get the wrong sp value of > &spin_shadow_stack. Hi Guo, Don't worry about it. the spin_shadow_stack is just a flag used for "spin", if hart is allowed to used the shadow_stack, we load its address in next instruction by "la sp, shadow_stack". But I agree with use unsigned int instead of atomic_t, and use smp_store_release directly. V2 has been sent out, could you please review it? Thanks
Hi Jisheng, On Wed, Oct 19, 2022 at 11:47:27PM +0800, Jisheng Zhang wrote: > Currently, when detecting vmap stack overflow, riscv firstly switches > to the so called shadow stack, then use this shadow stack to call the > get_overflow_stack() to get the overflow stack. However, there's > a race here if two or more harts use the same shadow stack at the same > time. > > To solve this race, we introduce spin_shadow_stack atomic var, which > will make the shadow stack usage serialized. > > Fixes: 31da94c25aea ("riscv: add VMAP_STACK overflow detection") > Signed-off-by: Jisheng Zhang <jszhang@kernel.org> > Suggested-by: Guo Ren <guoren@kernel.org> > --- > arch/riscv/kernel/entry.S | 4 ++++ > arch/riscv/kernel/traps.c | 4 ++++ > 2 files changed, 8 insertions(+) > > diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S > index b9eda3fcbd6d..7b924b16792b 100644 > --- a/arch/riscv/kernel/entry.S > +++ b/arch/riscv/kernel/entry.S > @@ -404,6 +404,10 @@ handle_syscall_trace_exit: > > #ifdef CONFIG_VMAP_STACK > handle_kernel_stack_overflow: > +1: la sp, spin_shadow_stack > + amoswap.w sp, sp, (sp) > + bnez sp, 1b > + > la sp, shadow_stack > addi sp, sp, SHADOW_OVERFLOW_STACK_SIZE > > diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c > index f3e96d60a2ff..88a54947dffb 100644 > --- a/arch/riscv/kernel/traps.c > +++ b/arch/riscv/kernel/traps.c > @@ -221,11 +221,15 @@ asmlinkage unsigned long get_overflow_stack(void) > OVERFLOW_STACK_SIZE; > } > > +atomic_t spin_shadow_stack; > + > asmlinkage void handle_bad_stack(struct pt_regs *regs) > { > unsigned long tsk_stk = (unsigned long)current->stack; > unsigned long ovf_stk = (unsigned long)this_cpu_ptr(overflow_stack); > > + atomic_set_release(&spin_shadow_stack, 0); > + Have not really looked the details: should there be a matching acquire? Andrea > console_verbose(); > > pr_emerg("Insufficient stack space to handle exception!\n"); > -- > 2.37.2 >
On Thu, Oct 20, 2022 at 10:47 PM Jisheng Zhang <jszhang@kernel.org> wrote: > > On Thu, Oct 20, 2022 at 10:16:47AM +0800, Guo Ren wrote: > > On Wed, Oct 19, 2022 at 11:57 PM Jisheng Zhang <jszhang@kernel.org> wrote: > > > > > > Currently, when detecting vmap stack overflow, riscv firstly switches > > > to the so called shadow stack, then use this shadow stack to call the > > > get_overflow_stack() to get the overflow stack. However, there's > > > a race here if two or more harts use the same shadow stack at the same > > > time. > > > > > > To solve this race, we introduce spin_shadow_stack atomic var, which > > > will make the shadow stack usage serialized. > > > > > > Fixes: 31da94c25aea ("riscv: add VMAP_STACK overflow detection") > > > Signed-off-by: Jisheng Zhang <jszhang@kernel.org> > > > Suggested-by: Guo Ren <guoren@kernel.org> > > > --- > > > arch/riscv/kernel/entry.S | 4 ++++ > > > arch/riscv/kernel/traps.c | 4 ++++ > > > 2 files changed, 8 insertions(+) > > > > > > diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S > > > index b9eda3fcbd6d..7b924b16792b 100644 > > > --- a/arch/riscv/kernel/entry.S > > > +++ b/arch/riscv/kernel/entry.S > > > @@ -404,6 +404,10 @@ handle_syscall_trace_exit: > > > > > > #ifdef CONFIG_VMAP_STACK > > > handle_kernel_stack_overflow: > > > +1: la sp, spin_shadow_stack > > > + amoswap.w sp, sp, (sp) > > If CONFIG_64BIT=y, it would be broken. Because we only hold 32bit of > > the sp, and the next loop would get the wrong sp value of > > &spin_shadow_stack. > > Hi Guo, > > Don't worry about it. the spin_shadow_stack is just a flag used for > "spin", if hart is allowed to used the shadow_stack, we load its > address in next instruction by "la sp, shadow_stack". Haha, yes, my brain is at fault :) > But I agree with use unsigned int instead of atomic_t, and use > smp_store_release directly. V2 has been sent out, could you please > review it? Okay > > Thanks
On Fri, Oct 21, 2022 at 7:26 AM Andrea Parri <parri.andrea@gmail.com> wrote: > > Hi Jisheng, > > On Wed, Oct 19, 2022 at 11:47:27PM +0800, Jisheng Zhang wrote: > > Currently, when detecting vmap stack overflow, riscv firstly switches > > to the so called shadow stack, then use this shadow stack to call the > > get_overflow_stack() to get the overflow stack. However, there's > > a race here if two or more harts use the same shadow stack at the same > > time. > > > > To solve this race, we introduce spin_shadow_stack atomic var, which > > will make the shadow stack usage serialized. > > > > Fixes: 31da94c25aea ("riscv: add VMAP_STACK overflow detection") > > Signed-off-by: Jisheng Zhang <jszhang@kernel.org> > > Suggested-by: Guo Ren <guoren@kernel.org> > > --- > > arch/riscv/kernel/entry.S | 4 ++++ > > arch/riscv/kernel/traps.c | 4 ++++ > > 2 files changed, 8 insertions(+) > > > > diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S > > index b9eda3fcbd6d..7b924b16792b 100644 > > --- a/arch/riscv/kernel/entry.S > > +++ b/arch/riscv/kernel/entry.S > > @@ -404,6 +404,10 @@ handle_syscall_trace_exit: > > > > #ifdef CONFIG_VMAP_STACK > > handle_kernel_stack_overflow: > > +1: la sp, spin_shadow_stack > > + amoswap.w sp, sp, (sp) > > + bnez sp, 1b > > + > > la sp, shadow_stack > > addi sp, sp, SHADOW_OVERFLOW_STACK_SIZE > > > > diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c > > index f3e96d60a2ff..88a54947dffb 100644 > > --- a/arch/riscv/kernel/traps.c > > +++ b/arch/riscv/kernel/traps.c > > @@ -221,11 +221,15 @@ asmlinkage unsigned long get_overflow_stack(void) > > OVERFLOW_STACK_SIZE; > > } > > > > +atomic_t spin_shadow_stack; > > + > > asmlinkage void handle_bad_stack(struct pt_regs *regs) > > { > > unsigned long tsk_stk = (unsigned long)current->stack; > > unsigned long ovf_stk = (unsigned long)this_cpu_ptr(overflow_stack); > > > > + atomic_set_release(&spin_shadow_stack, 0); > > + > > Have not really looked the details: should there be a matching acquire? I use atomic_set_release here, because I need earlier memory operations finished to make sure the sp is ready then set the spin flag. The following memory operations order is not important, because we just care about sp value. Also, we use relax amoswap before, because sp has naturelly dependency. But giving them RCsc is okay here, because we don't care about performance here. eg: handle_kernel_stack_overflow: +1: la sp, spin_shadow_stack + amoswap.w.aqrl sp, sp, (sp) + bnez sp, 1b + .... + smp_store_release(&spin_shadow_stack, 0); + smp_mb(); > > Andrea > > > > console_verbose(); > > > > pr_emerg("Insufficient stack space to handle exception!\n"); > > -- > > 2.37.2 > > -- Best Regards Guo Ren
> > > + atomic_set_release(&spin_shadow_stack, 0); > > > > Have not really looked the details: should there be a matching acquire? > > I use atomic_set_release here, because I need earlier memory > operations finished to make sure the sp is ready then set the spin > flag. > > The following memory operations order is not important, because we > just care about sp value. > > Also, we use relax amoswap before, because sp has naturelly > dependency. But giving them RCsc is okay here, because we don't care > about performance here. Thanks for the clarification. I'm not really suggesting to add unneeded synchronization, even more so in local/private constructs as in this case. It just felt odd to see the release without a pairing acquire, so I asked. ;-) Thanks, Andrea > eg: > handle_kernel_stack_overflow: > +1: la sp, spin_shadow_stack > + amoswap.w.aqrl sp, sp, (sp) > + bnez sp, 1b > + > .... > + smp_store_release(&spin_shadow_stack, 0); > + smp_mb();
Hi Tong, > > > I use atomic_set_release here, because I need earlier memory > > > operations finished to make sure the sp is ready then set the spin > > > flag. > Consider this implementation:) > > smp_store_mb(&spin_shadow_stack, 0); smp_store_mb() has "WRITE_ONCE(); smp_mb()" semantics; so it doesn't guarantee that the store to spin_shadow_stack is ordered after program -order earlier memory accesses. Andrea
On Fri, Oct 21, 2022 at 4:36 PM Andrea Parri <parri.andrea@gmail.com> wrote: > > > > > + atomic_set_release(&spin_shadow_stack, 0); > > > > > > Have not really looked the details: should there be a matching acquire? > > > > I use atomic_set_release here, because I need earlier memory > > operations finished to make sure the sp is ready then set the spin > > flag. > > > > The following memory operations order is not important, because we > > just care about sp value. > > > > Also, we use relax amoswap before, because sp has naturelly > > dependency. But giving them RCsc is okay here, because we don't care > > about performance here. > > Thanks for the clarification. > > I'm not really suggesting to add unneeded synchronization, even more > so in local/private constructs as in this case. It just felt odd to > see the release without a pairing acquire, so I asked. ;-) Okay, let's keep: handle_kernel_stack_overflow: +1: la sp, spin_shadow_stack + amoswap.w sp, sp, (sp) + bnez sp, 1b + .... + smp_store_release(&spin_shadow_stack, 0); > > Thanks, > Andrea > > > > eg: > > handle_kernel_stack_overflow: > > +1: la sp, spin_shadow_stack > > + amoswap.w.aqrl sp, sp, (sp) > > + bnez sp, 1b > > + > > .... > > + smp_store_release(&spin_shadow_stack, 0); > > + smp_mb();
On Fri, Oct 21, 2022 at 9:46 PM Tong Tiangen <tongtiangen@huawei.com> wrote: > > > > 在 2022/10/21 21:22, Andrea Parri 写道: > > Hi Tong, > > > >>>> I use atomic_set_release here, because I need earlier memory > >>>> operations finished to make sure the sp is ready then set the spin > >>>> flag. > > > >> Consider this implementation:) > >> > >> smp_store_mb(&spin_shadow_stack, 0); > > > > smp_store_mb() has "WRITE_ONCE(); smp_mb()" semantics; so it doesn't > > guarantee that the store to spin_shadow_stack is ordered after program > > -order earlier memory accesses. > > > > Andrea > > . > > Hi Andrea: > > IIUC, the earlier memory access amoswap.aqrl, here .aqrl guarantee it. > But anyway, consider we don't care about performance here, using > smp_store_release()(add barrier()) surely right. We use smp_store_release() is for: //load per-cpu overflow stack REG_L sp, -8(sp) Not amoswap. Actually, amoswap.aqrl guarantees nothing because all instructions depend on the sp register. > > Thanks, > Tong.
diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S index b9eda3fcbd6d..7b924b16792b 100644 --- a/arch/riscv/kernel/entry.S +++ b/arch/riscv/kernel/entry.S @@ -404,6 +404,10 @@ handle_syscall_trace_exit: #ifdef CONFIG_VMAP_STACK handle_kernel_stack_overflow: +1: la sp, spin_shadow_stack + amoswap.w sp, sp, (sp) + bnez sp, 1b + la sp, shadow_stack addi sp, sp, SHADOW_OVERFLOW_STACK_SIZE diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c index f3e96d60a2ff..88a54947dffb 100644 --- a/arch/riscv/kernel/traps.c +++ b/arch/riscv/kernel/traps.c @@ -221,11 +221,15 @@ asmlinkage unsigned long get_overflow_stack(void) OVERFLOW_STACK_SIZE; } +atomic_t spin_shadow_stack; + asmlinkage void handle_bad_stack(struct pt_regs *regs) { unsigned long tsk_stk = (unsigned long)current->stack; unsigned long ovf_stk = (unsigned long)this_cpu_ptr(overflow_stack); + atomic_set_release(&spin_shadow_stack, 0); + console_verbose(); pr_emerg("Insufficient stack space to handle exception!\n");