Skip to content

Commit 8ce71d2

Browse files
brooniectmarinas
authored andcommitted
arm64/traps: Handle GCS exceptions
A new exception code is defined for GCS specific faults other than standard load/store faults, for example GCS token validation failures, add handling for this. These faults are reported to userspace as segfaults with code SEGV_CPERR (protection error), mirroring the reporting for x86 shadow stack errors. GCS faults due to memory load/store operations generate data aborts with a flag set, these will be handled separately as part of the data abort handling. Since we do not currently enable GCS for EL1 we should not get any faults there but while we're at it we wire things up there, treating any GCS fault as fatal. Reviewed-by: Thiago Jung Bauermann <[email protected]> Reviewed-by: Catalin Marinas <[email protected]> Signed-off-by: Mark Brown <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Catalin Marinas <[email protected]>
1 parent eefc987 commit 8ce71d2

File tree

4 files changed

+63
-1
lines changed

4 files changed

+63
-1
lines changed

arch/arm64/include/asm/esr.h

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@
5151
#define ESR_ELx_EC_FP_EXC32 UL(0x28)
5252
/* Unallocated EC: 0x29 - 0x2B */
5353
#define ESR_ELx_EC_FP_EXC64 UL(0x2C)
54-
/* Unallocated EC: 0x2D - 0x2E */
54+
#define ESR_ELx_EC_GCS UL(0x2D)
55+
/* Unallocated EC: 0x2E */
5556
#define ESR_ELx_EC_SERROR UL(0x2F)
5657
#define ESR_ELx_EC_BREAKPT_LOW UL(0x30)
5758
#define ESR_ELx_EC_BREAKPT_CUR UL(0x31)
@@ -386,6 +387,31 @@
386387
#define ESR_ELx_MOPS_ISS_SRCREG(esr) (((esr) & (UL(0x1f) << 5)) >> 5)
387388
#define ESR_ELx_MOPS_ISS_SIZEREG(esr) (((esr) & (UL(0x1f) << 0)) >> 0)
388389

390+
/* ISS field definitions for GCS */
391+
#define ESR_ELx_ExType_SHIFT (20)
392+
#define ESR_ELx_ExType_MASK GENMASK(23, 20)
393+
#define ESR_ELx_Raddr_SHIFT (10)
394+
#define ESR_ELx_Raddr_MASK GENMASK(14, 10)
395+
#define ESR_ELx_Rn_SHIFT (5)
396+
#define ESR_ELx_Rn_MASK GENMASK(9, 5)
397+
#define ESR_ELx_Rvalue_SHIFT 5
398+
#define ESR_ELx_Rvalue_MASK GENMASK(9, 5)
399+
#define ESR_ELx_IT_SHIFT (0)
400+
#define ESR_ELx_IT_MASK GENMASK(4, 0)
401+
402+
#define ESR_ELx_ExType_DATA_CHECK 0
403+
#define ESR_ELx_ExType_EXLOCK 1
404+
#define ESR_ELx_ExType_STR 2
405+
406+
#define ESR_ELx_IT_RET 0
407+
#define ESR_ELx_IT_GCSPOPM 1
408+
#define ESR_ELx_IT_RET_KEYA 2
409+
#define ESR_ELx_IT_RET_KEYB 3
410+
#define ESR_ELx_IT_GCSSS1 4
411+
#define ESR_ELx_IT_GCSSS2 5
412+
#define ESR_ELx_IT_GCSPOPCX 6
413+
#define ESR_ELx_IT_GCSPOPX 7
414+
389415
#ifndef __ASSEMBLY__
390416
#include <asm/types.h>
391417

arch/arm64/include/asm/exception.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ void do_el0_undef(struct pt_regs *regs, unsigned long esr);
5757
void do_el1_undef(struct pt_regs *regs, unsigned long esr);
5858
void do_el0_bti(struct pt_regs *regs);
5959
void do_el1_bti(struct pt_regs *regs, unsigned long esr);
60+
void do_el0_gcs(struct pt_regs *regs, unsigned long esr);
61+
void do_el1_gcs(struct pt_regs *regs, unsigned long esr);
6062
void do_debug_exception(unsigned long addr_if_watchpoint, unsigned long esr,
6163
struct pt_regs *regs);
6264
void do_fpsimd_acc(unsigned long esr, struct pt_regs *regs);

arch/arm64/kernel/entry-common.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,15 @@ static void noinstr el1_bti(struct pt_regs *regs, unsigned long esr)
463463
exit_to_kernel_mode(regs);
464464
}
465465

466+
static void noinstr el1_gcs(struct pt_regs *regs, unsigned long esr)
467+
{
468+
enter_from_kernel_mode(regs);
469+
local_daif_inherit(regs);
470+
do_el1_gcs(regs, esr);
471+
local_daif_mask();
472+
exit_to_kernel_mode(regs);
473+
}
474+
466475
static void noinstr el1_dbg(struct pt_regs *regs, unsigned long esr)
467476
{
468477
unsigned long far = read_sysreg(far_el1);
@@ -505,6 +514,9 @@ asmlinkage void noinstr el1h_64_sync_handler(struct pt_regs *regs)
505514
case ESR_ELx_EC_BTI:
506515
el1_bti(regs, esr);
507516
break;
517+
case ESR_ELx_EC_GCS:
518+
el1_gcs(regs, esr);
519+
break;
508520
case ESR_ELx_EC_BREAKPT_CUR:
509521
case ESR_ELx_EC_SOFTSTP_CUR:
510522
case ESR_ELx_EC_WATCHPT_CUR:
@@ -684,6 +696,14 @@ static void noinstr el0_mops(struct pt_regs *regs, unsigned long esr)
684696
exit_to_user_mode(regs);
685697
}
686698

699+
static void noinstr el0_gcs(struct pt_regs *regs, unsigned long esr)
700+
{
701+
enter_from_user_mode(regs);
702+
local_daif_restore(DAIF_PROCCTX);
703+
do_el0_gcs(regs, esr);
704+
exit_to_user_mode(regs);
705+
}
706+
687707
static void noinstr el0_inv(struct pt_regs *regs, unsigned long esr)
688708
{
689709
enter_from_user_mode(regs);
@@ -766,6 +786,9 @@ asmlinkage void noinstr el0t_64_sync_handler(struct pt_regs *regs)
766786
case ESR_ELx_EC_MOPS:
767787
el0_mops(regs, esr);
768788
break;
789+
case ESR_ELx_EC_GCS:
790+
el0_gcs(regs, esr);
791+
break;
769792
case ESR_ELx_EC_BREAKPT_LOW:
770793
case ESR_ELx_EC_SOFTSTP_LOW:
771794
case ESR_ELx_EC_WATCHPT_LOW:

arch/arm64/kernel/traps.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,16 @@ void do_el1_bti(struct pt_regs *regs, unsigned long esr)
506506
die("Oops - BTI", regs, esr);
507507
}
508508

509+
void do_el0_gcs(struct pt_regs *regs, unsigned long esr)
510+
{
511+
force_signal_inject(SIGSEGV, SEGV_CPERR, regs->pc, 0);
512+
}
513+
514+
void do_el1_gcs(struct pt_regs *regs, unsigned long esr)
515+
{
516+
die("Oops - GCS", regs, esr);
517+
}
518+
509519
void do_el0_fpac(struct pt_regs *regs, unsigned long esr)
510520
{
511521
force_signal_inject(SIGILL, ILL_ILLOPN, regs->pc, esr);
@@ -852,6 +862,7 @@ static const char *esr_class_str[] = {
852862
[ESR_ELx_EC_MOPS] = "MOPS",
853863
[ESR_ELx_EC_FP_EXC32] = "FP (AArch32)",
854864
[ESR_ELx_EC_FP_EXC64] = "FP (AArch64)",
865+
[ESR_ELx_EC_GCS] = "Guarded Control Stack",
855866
[ESR_ELx_EC_SERROR] = "SError",
856867
[ESR_ELx_EC_BREAKPT_LOW] = "Breakpoint (lower EL)",
857868
[ESR_ELx_EC_BREAKPT_CUR] = "Breakpoint (current EL)",

0 commit comments

Comments
 (0)