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 23
23
#define REG_L __REG_SEL(ld, lw)
24
24
#define REG_S __REG_SEL(sd, sw)
25
25
#define REG_SC __REG_SEL(sc.d, sc.w)
26
+ #define REG_AMOSWAP_AQ __REG_SEL(amoswap.d.aq, amoswap.w.aq)
26
27
#define REG_ASM __REG_SEL(.dword, .word)
27
28
#define SZREG __REG_SEL(8, 4)
28
29
#define LGREG __REG_SEL(3, 2)
Original file line number Diff line number Diff line change @@ -404,6 +404,19 @@ handle_syscall_trace_exit:
404
404
405
405
#ifdef CONFIG_VMAP_STACK
406
406
handle_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
+
407
420
la sp , shadow_stack
408
421
addi sp , sp , SHADOW_OVERFLOW_STACK_SIZE
409
422
Original file line number Diff line number Diff line change @@ -221,11 +221,29 @@ asmlinkage unsigned long get_overflow_stack(void)
221
221
OVERFLOW_STACK_SIZE ;
222
222
}
223
223
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
+
224
233
asmlinkage void handle_bad_stack (struct pt_regs * regs )
225
234
{
226
235
unsigned long tsk_stk = (unsigned long )current -> stack ;
227
236
unsigned long ovf_stk = (unsigned long )this_cpu_ptr (overflow_stack );
228
237
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
+
229
247
console_verbose ();
230
248
231
249
pr_emerg ("Insufficient stack space to handle exception!\n" );
You can’t perform that action at this time.
0 commit comments