@@ -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
203206static 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+
646725static 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