File tree Expand file tree Collapse file tree 3 files changed +32
-0
lines changed
Expand file tree Collapse file tree 3 files changed +32
-0
lines changed Original file line number Diff line number Diff line change 2323#define REG_L __REG_SEL(ld, lw)
2424#define REG_S __REG_SEL(sd, sw)
2525#define REG_SC __REG_SEL(sc.d, sc.w)
26+ #define REG_AMOSWAP_AQ __REG_SEL(amoswap.d.aq, amoswap.w.aq)
2627#define REG_ASM __REG_SEL(.dword, .word)
2728#define SZREG __REG_SEL(8, 4)
2829#define LGREG __REG_SEL(3, 2)
Original file line number Diff line number Diff line change @@ -404,6 +404,19 @@ handle_syscall_trace_exit:
404404
405405#ifdef CONFIG_VMAP_STACK
406406handle_kernel_stack_overflow:
407+ /*
408+ * Takes the psuedo-spinlock for the shadow stack, in case multiple
409+ * harts are concurrently overflowing their kernel stacks. We could
410+ * store any value here, but since we're overflowing the kernel stack
411+ * already we only have SP to use as a scratch register. So we just
412+ * swap in the address of the spinlock, as that's definately non-zero.
413+ *
414+ * Pairs with a store_release in handle_bad_stack().
415+ */
416+ 1 : la sp , spin_shadow_stack
417+ REG_AMOSWAP_AQ sp , sp , (sp )
418+ bnez sp , 1b
419+
407420 la sp , shadow_stack
408421 addi sp , sp , SHADOW_OVERFLOW_STACK_SIZE
409422
Original file line number Diff line number Diff line change @@ -221,11 +221,29 @@ asmlinkage unsigned long get_overflow_stack(void)
221221 OVERFLOW_STACK_SIZE ;
222222}
223223
224+ /*
225+ * A pseudo spinlock to protect the shadow stack from being used by multiple
226+ * harts concurrently. This isn't a real spinlock because the lock side must
227+ * be taken without a valid stack and only a single register, it's only taken
228+ * while in the process of panicing anyway so the performance and error
229+ * checking a proper spinlock gives us doesn't matter.
230+ */
231+ unsigned long spin_shadow_stack ;
232+
224233asmlinkage void handle_bad_stack (struct pt_regs * regs )
225234{
226235 unsigned long tsk_stk = (unsigned long )current -> stack ;
227236 unsigned long ovf_stk = (unsigned long )this_cpu_ptr (overflow_stack );
228237
238+ /*
239+ * We're done with the shadow stack by this point, as we're on the
240+ * overflow stack. Tell any other concurrent overflowing harts that
241+ * they can proceed with panicing by releasing the pseudo-spinlock.
242+ *
243+ * This pairs with an amoswap.aq in handle_kernel_stack_overflow.
244+ */
245+ smp_store_release (& spin_shadow_stack , 0 );
246+
229247 console_verbose ();
230248
231249 pr_emerg ("Insufficient stack space to handle exception!\n" );
You can’t perform that action at this time.
0 commit comments