Re: [PATCH] riscv: fix race when vmap stack overflow

From: Guo Ren
Date: Thu Oct 20 2022 - 21:11:47 EST


On Fri, Oct 21, 2022 at 7:26 AM Andrea Parri <parri.andrea@xxxxxxxxx> 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@xxxxxxxxxx>
> > Suggested-by: Guo Ren <guoren@xxxxxxxxxx>
> > ---
> > 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