Commit 082c4c81 authored by Peter Zijlstra's avatar Peter Zijlstra

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: default avatarKees Cook <keescook@chromium.org>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: default avatarKees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/r/20221027092842.699804264@infradead.org
parent 931ab636
......@@ -702,6 +702,47 @@ void __init_or_module noinline apply_ibt_endbr(s32 *start, s32 *end) { }
#endif /* CONFIG_X86_KERNEL_IBT */
#ifdef CONFIG_FINEIBT
enum cfi_mode {
CFI_DEFAULT,
CFI_OFF,
CFI_KCFI,
CFI_FINEIBT,
};
static enum cfi_mode cfi_mode __ro_after_init = CFI_DEFAULT;
static __init int cfi_parse_cmdline(char *str)
{
if (!str)
return -EINVAL;
while (str) {
char *next = strchr(str, ',');
if (next) {
*next = 0;
next++;
}
if (!strcmp(str, "auto")) {
cfi_mode = CFI_DEFAULT;
} else if (!strcmp(str, "off")) {
cfi_mode = CFI_OFF;
} else if (!strcmp(str, "kcfi")) {
cfi_mode = CFI_KCFI;
} else if (!strcmp(str, "fineibt")) {
cfi_mode = CFI_FINEIBT;
} else {
pr_err("Ignoring unknown cfi option (%s).", str);
}
str = next;
}
return 0;
}
early_param("cfi", cfi_parse_cmdline);
/*
* kCFI FineIBT
*
......@@ -868,30 +909,52 @@ static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline,
"FineIBT preamble wrong size: %ld", fineibt_preamble_size))
return;
if (!HAS_KERNEL_IBT || !cpu_feature_enabled(X86_FEATURE_IBT))
if (cfi_mode == CFI_DEFAULT) {
cfi_mode = CFI_KCFI;
if (HAS_KERNEL_IBT && cpu_feature_enabled(X86_FEATURE_IBT))
cfi_mode = CFI_FINEIBT;
}
switch (cfi_mode) {
case CFI_OFF:
ret = cfi_disable_callers(start_retpoline, end_retpoline);
if (ret)
goto err;
if (builtin)
pr_info("Disabling CFI\n");
return;
/*
* Rewrite the callers to not use the __cfi_ stubs, such that we might
* rewrite them. This disables all CFI. If this succeeds but any of the
* later stages fails, we're without CFI.
*/
ret = cfi_disable_callers(start_retpoline, end_retpoline);
if (ret)
goto err;
case CFI_KCFI:
if (builtin)
pr_info("Using kCFI\n");
return;
ret = cfi_rewrite_preamble(start_cfi, end_cfi);
if (ret)
goto err;
case CFI_FINEIBT:
/*
* Rewrite the callers to not use the __cfi_ stubs, such that we might
* rewrite them. This disables all CFI. If this succeeds but any of the
* later stages fails, we're without CFI.
*/
ret = cfi_disable_callers(start_retpoline, end_retpoline);
if (ret)
goto err;
ret = cfi_rewrite_preamble(start_cfi, end_cfi);
if (ret)
goto err;
ret = cfi_rewrite_callers(start_retpoline, end_retpoline);
if (ret)
goto err;
ret = cfi_rewrite_callers(start_retpoline, end_retpoline);
if (ret)
goto err;
if (builtin)
pr_info("Using FineIBT CFI\n");
if (builtin)
pr_info("Using FineIBT CFI\n");
return;
return;
default:
break;
}
err:
pr_err("Something went horribly wrong trying to rewrite the CFI implementation.\n");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment