Skip to content

Commit 082c4c8

Browse files
author
Peter Zijlstra
committed
x86/cfi: Boot time selection of CFI scheme
Add the "cfi=" boot parameter to allow people to select a CFI scheme at boot time. Mostly useful for development / debugging. Requested-by: Kees Cook <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Reviewed-by: Kees Cook <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 931ab63 commit 082c4c8

File tree

1 file changed

+81
-18
lines changed

1 file changed

+81
-18
lines changed

arch/x86/kernel/alternative.c

Lines changed: 81 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -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

896959
err:
897960
pr_err("Something went horribly wrong trying to rewrite the CFI implementation.\n");

0 commit comments

Comments
 (0)