@@ -66,6 +66,7 @@ struct rt_sigframe_user_layout {
66
66
67
67
unsigned long fpsimd_offset ;
68
68
unsigned long esr_offset ;
69
+ unsigned long gcs_offset ;
69
70
unsigned long sve_offset ;
70
71
unsigned long tpidr2_offset ;
71
72
unsigned long za_offset ;
@@ -198,6 +199,8 @@ struct user_ctxs {
198
199
u32 fpmr_size ;
199
200
struct poe_context __user * poe ;
200
201
u32 poe_size ;
202
+ struct gcs_context __user * gcs ;
203
+ u32 gcs_size ;
201
204
};
202
205
203
206
static int preserve_fpsimd_context (struct fpsimd_context __user * ctx )
@@ -643,6 +646,82 @@ extern int restore_zt_context(struct user_ctxs *user);
643
646
644
647
#endif /* ! CONFIG_ARM64_SME */
645
648
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
+
646
725
static int parse_user_sigframe (struct user_ctxs * user ,
647
726
struct rt_sigframe __user * sf )
648
727
{
@@ -661,6 +740,7 @@ static int parse_user_sigframe(struct user_ctxs *user,
661
740
user -> zt = NULL ;
662
741
user -> fpmr = NULL ;
663
742
user -> poe = NULL ;
743
+ user -> gcs = NULL ;
664
744
665
745
if (!IS_ALIGNED ((unsigned long )base , 16 ))
666
746
goto invalid ;
@@ -777,6 +857,17 @@ static int parse_user_sigframe(struct user_ctxs *user,
777
857
user -> fpmr_size = size ;
778
858
break ;
779
859
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
+
780
871
case EXTRA_MAGIC :
781
872
if (have_extra_context )
782
873
goto invalid ;
@@ -896,6 +987,9 @@ static int restore_sigframe(struct pt_regs *regs,
896
987
err = restore_fpsimd_context (& user );
897
988
}
898
989
990
+ if (err == 0 && system_supports_gcs () && user .gcs )
991
+ err = restore_gcs_context (& user );
992
+
899
993
if (err == 0 && system_supports_tpidr2 () && user .tpidr2 )
900
994
err = restore_tpidr2_context (& user );
901
995
@@ -1029,6 +1123,15 @@ static int setup_sigframe_layout(struct rt_sigframe_user_layout *user,
1029
1123
return err ;
1030
1124
}
1031
1125
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
+
1032
1135
if (system_supports_sve () || system_supports_sme ()) {
1033
1136
unsigned int vq = 0 ;
1034
1137
@@ -1136,6 +1239,12 @@ static int setup_sigframe(struct rt_sigframe_user_layout *user,
1136
1239
__put_user_error (current -> thread .fault_code , & esr_ctx -> esr , err );
1137
1240
}
1138
1241
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
+
1139
1248
/* Scalable Vector Extension state (including streaming), if present */
1140
1249
if ((system_supports_sve () || system_supports_sme ()) &&
1141
1250
err == 0 && user -> sve_offset ) {
0 commit comments