Skip to content

Commit 16f47bb

Browse files
brooniectmarinas
authored andcommitted
arm64/signal: Expose GCS state in signal frames
Add a context for the GCS state and include it in the signal context when running on a system that supports GCS. We reuse the same flags that the prctl() uses to specify which GCS features are enabled and also provide the current GCS pointer. We do not support enabling GCS via signal return, there is a conflict between specifying GCSPR_EL0 and allocation of a new GCS and this is not an ancticipated use case. We also enforce GCS configuration locking on signal return. Reviewed-by: Catalin Marinas <[email protected]> Reviewed-by: Thiago Jung Bauermann <[email protected]> Acked-by: Yury Khrustalev <[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 eaf62ce commit 16f47bb

File tree

2 files changed

+118
-0
lines changed

2 files changed

+118
-0
lines changed

arch/arm64/include/uapi/asm/sigcontext.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,15 @@ struct zt_context {
183183
__u16 __reserved[3];
184184
};
185185

186+
#define GCS_MAGIC 0x47435300
187+
188+
struct gcs_context {
189+
struct _aarch64_ctx head;
190+
__u64 gcspr;
191+
__u64 features_enabled;
192+
__u64 reserved;
193+
};
194+
186195
#endif /* !__ASSEMBLY__ */
187196

188197
#include <asm/sve_context.h>

arch/arm64/kernel/signal.c

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ struct rt_sigframe_user_layout {
6666

6767
unsigned long fpsimd_offset;
6868
unsigned long esr_offset;
69+
unsigned long gcs_offset;
6970
unsigned long sve_offset;
7071
unsigned long tpidr2_offset;
7172
unsigned long za_offset;
@@ -198,6 +199,8 @@ struct user_ctxs {
198199
u32 fpmr_size;
199200
struct poe_context __user *poe;
200201
u32 poe_size;
202+
struct gcs_context __user *gcs;
203+
u32 gcs_size;
201204
};
202205

203206
static int preserve_fpsimd_context(struct fpsimd_context __user *ctx)
@@ -643,6 +646,82 @@ extern int restore_zt_context(struct user_ctxs *user);
643646

644647
#endif /* ! CONFIG_ARM64_SME */
645648

649+
#ifdef CONFIG_ARM64_GCS
650+
651+
static int preserve_gcs_context(struct gcs_context __user *ctx)
652+
{
653+
int err = 0;
654+
u64 gcspr = read_sysreg_s(SYS_GCSPR_EL0);
655+
656+
/*
657+
* If GCS is enabled we will add a cap token to the frame,
658+
* include it in the GCSPR_EL0 we report to support stack
659+
* switching via sigreturn if GCS is enabled. We do not allow
660+
* enabling via sigreturn so the token is only relevant for
661+
* threads with GCS enabled.
662+
*/
663+
if (task_gcs_el0_enabled(current))
664+
gcspr -= 8;
665+
666+
__put_user_error(GCS_MAGIC, &ctx->head.magic, err);
667+
__put_user_error(sizeof(*ctx), &ctx->head.size, err);
668+
__put_user_error(gcspr, &ctx->gcspr, err);
669+
__put_user_error(0, &ctx->reserved, err);
670+
__put_user_error(current->thread.gcs_el0_mode,
671+
&ctx->features_enabled, err);
672+
673+
return err;
674+
}
675+
676+
static int restore_gcs_context(struct user_ctxs *user)
677+
{
678+
u64 gcspr, enabled;
679+
int err = 0;
680+
681+
if (user->gcs_size != sizeof(*user->gcs))
682+
return -EINVAL;
683+
684+
__get_user_error(gcspr, &user->gcs->gcspr, err);
685+
__get_user_error(enabled, &user->gcs->features_enabled, err);
686+
if (err)
687+
return err;
688+
689+
/* Don't allow unknown modes */
690+
if (enabled & ~PR_SHADOW_STACK_SUPPORTED_STATUS_MASK)
691+
return -EINVAL;
692+
693+
err = gcs_check_locked(current, enabled);
694+
if (err != 0)
695+
return err;
696+
697+
/* Don't allow enabling */
698+
if (!task_gcs_el0_enabled(current) &&
699+
(enabled & PR_SHADOW_STACK_ENABLE))
700+
return -EINVAL;
701+
702+
/* If we are disabling disable everything */
703+
if (!(enabled & PR_SHADOW_STACK_ENABLE))
704+
enabled = 0;
705+
706+
current->thread.gcs_el0_mode = enabled;
707+
708+
/*
709+
* We let userspace set GCSPR_EL0 to anything here, we will
710+
* validate later in gcs_restore_signal().
711+
*/
712+
write_sysreg_s(gcspr, SYS_GCSPR_EL0);
713+
714+
return 0;
715+
}
716+
717+
#else /* ! CONFIG_ARM64_GCS */
718+
719+
/* Turn any non-optimised out attempts to use these into a link error: */
720+
extern int preserve_gcs_context(void __user *ctx);
721+
extern int restore_gcs_context(struct user_ctxs *user);
722+
723+
#endif /* ! CONFIG_ARM64_GCS */
724+
646725
static int parse_user_sigframe(struct user_ctxs *user,
647726
struct rt_sigframe __user *sf)
648727
{
@@ -661,6 +740,7 @@ static int parse_user_sigframe(struct user_ctxs *user,
661740
user->zt = NULL;
662741
user->fpmr = NULL;
663742
user->poe = NULL;
743+
user->gcs = NULL;
664744

665745
if (!IS_ALIGNED((unsigned long)base, 16))
666746
goto invalid;
@@ -777,6 +857,17 @@ static int parse_user_sigframe(struct user_ctxs *user,
777857
user->fpmr_size = size;
778858
break;
779859

860+
case GCS_MAGIC:
861+
if (!system_supports_gcs())
862+
goto invalid;
863+
864+
if (user->gcs)
865+
goto invalid;
866+
867+
user->gcs = (struct gcs_context __user *)head;
868+
user->gcs_size = size;
869+
break;
870+
780871
case EXTRA_MAGIC:
781872
if (have_extra_context)
782873
goto invalid;
@@ -896,6 +987,9 @@ static int restore_sigframe(struct pt_regs *regs,
896987
err = restore_fpsimd_context(&user);
897988
}
898989

990+
if (err == 0 && system_supports_gcs() && user.gcs)
991+
err = restore_gcs_context(&user);
992+
899993
if (err == 0 && system_supports_tpidr2() && user.tpidr2)
900994
err = restore_tpidr2_context(&user);
901995

@@ -1029,6 +1123,15 @@ static int setup_sigframe_layout(struct rt_sigframe_user_layout *user,
10291123
return err;
10301124
}
10311125

1126+
#ifdef CONFIG_ARM64_GCS
1127+
if (system_supports_gcs() && (add_all || current->thread.gcspr_el0)) {
1128+
err = sigframe_alloc(user, &user->gcs_offset,
1129+
sizeof(struct gcs_context));
1130+
if (err)
1131+
return err;
1132+
}
1133+
#endif
1134+
10321135
if (system_supports_sve() || system_supports_sme()) {
10331136
unsigned int vq = 0;
10341137

@@ -1136,6 +1239,12 @@ static int setup_sigframe(struct rt_sigframe_user_layout *user,
11361239
__put_user_error(current->thread.fault_code, &esr_ctx->esr, err);
11371240
}
11381241

1242+
if (system_supports_gcs() && err == 0 && user->gcs_offset) {
1243+
struct gcs_context __user *gcs_ctx =
1244+
apply_user_offset(user, user->gcs_offset);
1245+
err |= preserve_gcs_context(gcs_ctx);
1246+
}
1247+
11391248
/* Scalable Vector Extension state (including streaming), if present */
11401249
if ((system_supports_sve() || system_supports_sme()) &&
11411250
err == 0 && user->sve_offset) {

0 commit comments

Comments
 (0)