@@ -702,6 +702,47 @@ void __init_or_module noinline apply_ibt_endbr(s32 *start, s32 *end) { }
702702#endif /* CONFIG_X86_KERNEL_IBT */
703703
704704#ifdef CONFIG_FINEIBT
705+
706+ enum cfi_mode {
707+ CFI_DEFAULT ,
708+ CFI_OFF ,
709+ CFI_KCFI ,
710+ CFI_FINEIBT ,
711+ };
712+
713+ static enum cfi_mode cfi_mode __ro_after_init = CFI_DEFAULT ;
714+
715+ static __init int cfi_parse_cmdline (char * str )
716+ {
717+ if (!str )
718+ return - EINVAL ;
719+
720+ while (str ) {
721+ char * next = strchr (str , ',' );
722+ if (next ) {
723+ * next = 0 ;
724+ next ++ ;
725+ }
726+
727+ if (!strcmp (str , "auto" )) {
728+ cfi_mode = CFI_DEFAULT ;
729+ } else if (!strcmp (str , "off" )) {
730+ cfi_mode = CFI_OFF ;
731+ } else if (!strcmp (str , "kcfi" )) {
732+ cfi_mode = CFI_KCFI ;
733+ } else if (!strcmp (str , "fineibt" )) {
734+ cfi_mode = CFI_FINEIBT ;
735+ } else {
736+ pr_err ("Ignoring unknown cfi option (%s)." , str );
737+ }
738+
739+ str = next ;
740+ }
741+
742+ return 0 ;
743+ }
744+ early_param ("cfi" , cfi_parse_cmdline );
745+
705746/*
706747 * kCFI FineIBT
707748 *
@@ -868,30 +909,52 @@ static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline,
868909 "FineIBT preamble wrong size: %ld" , fineibt_preamble_size ))
869910 return ;
870911
871- if (!HAS_KERNEL_IBT || !cpu_feature_enabled (X86_FEATURE_IBT ))
912+ if (cfi_mode == CFI_DEFAULT ) {
913+ cfi_mode = CFI_KCFI ;
914+ if (HAS_KERNEL_IBT && cpu_feature_enabled (X86_FEATURE_IBT ))
915+ cfi_mode = CFI_FINEIBT ;
916+ }
917+
918+ switch (cfi_mode ) {
919+ case CFI_OFF :
920+ ret = cfi_disable_callers (start_retpoline , end_retpoline );
921+ if (ret )
922+ goto err ;
923+
924+ if (builtin )
925+ pr_info ("Disabling CFI\n" );
872926 return ;
873927
874- /*
875- * Rewrite the callers to not use the __cfi_ stubs, such that we might
876- * rewrite them. This disables all CFI. If this succeeds but any of the
877- * later stages fails, we're without CFI.
878- */
879- ret = cfi_disable_callers (start_retpoline , end_retpoline );
880- if (ret )
881- goto err ;
928+ case CFI_KCFI :
929+ if (builtin )
930+ pr_info ("Using kCFI\n" );
931+ return ;
882932
883- ret = cfi_rewrite_preamble (start_cfi , end_cfi );
884- if (ret )
885- goto err ;
933+ case CFI_FINEIBT :
934+ /*
935+ * Rewrite the callers to not use the __cfi_ stubs, such that we might
936+ * rewrite them. This disables all CFI. If this succeeds but any of the
937+ * later stages fails, we're without CFI.
938+ */
939+ ret = cfi_disable_callers (start_retpoline , end_retpoline );
940+ if (ret )
941+ goto err ;
942+
943+ ret = cfi_rewrite_preamble (start_cfi , end_cfi );
944+ if (ret )
945+ goto err ;
886946
887- ret = cfi_rewrite_callers (start_retpoline , end_retpoline );
888- if (ret )
889- goto err ;
947+ ret = cfi_rewrite_callers (start_retpoline , end_retpoline );
948+ if (ret )
949+ goto err ;
890950
891- if (builtin )
892- pr_info ("Using FineIBT CFI\n" );
951+ if (builtin )
952+ pr_info ("Using FineIBT CFI\n" );
953+ return ;
893954
894- return ;
955+ default :
956+ break ;
957+ }
895958
896959err :
897960 pr_err ("Something went horribly wrong trying to rewrite the CFI implementation.\n" );
0 commit comments