[PATCH v3 01/10] x86/cfi: Add warn option

From: Peter Zijlstra
Date: Wed Feb 19 2025 - 11:40:43 EST


Rebuilding with CFI_PERMISSIVE toggled is such a pain, esp. since
clang is so slow.

Signed-off-by: Peter Zijlstra (Intel) <peterz@xxxxxxxxxxxxx>
---
arch/x86/include/asm/cfi.h | 1 +
arch/x86/kernel/alternative.c | 4 ++++
arch/x86/kernel/cfi.c | 14 ++++++++++----
3 files changed, 15 insertions(+), 4 deletions(-)

--- a/arch/x86/include/asm/cfi.h
+++ b/arch/x86/include/asm/cfi.h
@@ -100,6 +100,7 @@ enum cfi_mode {
};

extern enum cfi_mode cfi_mode;
+extern bool cfi_warn;

struct pt_regs;

--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -916,6 +916,7 @@ void __init_or_module apply_seal_endbr(s
#endif

enum cfi_mode cfi_mode __ro_after_init = __CFI_DEFAULT;
+bool cfi_warn __ro_after_init = false;

#ifdef CONFIG_CFI_CLANG
struct bpf_insn;
@@ -1022,6 +1023,9 @@ static __init int cfi_parse_cmdline(char
cfi_mode = CFI_FINEIBT;
} else if (!strcmp(str, "norand")) {
cfi_rand = false;
+ } else if (!strcmp(str, "warn")) {
+ pr_alert("CFI mismatch non-fatal!\n");
+ cfi_warn = true;
} else {
pr_err("Ignoring unknown cfi option (%s).", str);
}
--- a/arch/x86/kernel/cfi.c
+++ b/arch/x86/kernel/cfi.c
@@ -67,16 +67,17 @@ static bool decode_cfi_insn(struct pt_re
*/
enum bug_trap_type handle_cfi_failure(struct pt_regs *regs)
{
- unsigned long target;
+ unsigned long target, addr = regs->ip;
+ enum bug_trap_type btt;
u32 type;

switch (cfi_mode) {
case CFI_KCFI:
- if (!is_cfi_trap(regs->ip))
+ if (!is_cfi_trap(addr))
return BUG_TRAP_TYPE_NONE;

if (!decode_cfi_insn(regs, &target, &type))
- return report_cfi_failure_noaddr(regs, regs->ip);
+ return report_cfi_failure_noaddr(regs, addr);

break;

@@ -90,7 +91,12 @@ enum bug_trap_type handle_cfi_failure(st
return BUG_TRAP_TYPE_NONE;
}

- return report_cfi_failure(regs, regs->ip, &target, type);
+ btt = report_cfi_failure(regs, addr, &target, type);
+ if (btt == BUG_TRAP_TYPE_BUG && cfi_warn) {
+ __warn(NULL, 0, (void *)addr, 0, regs, NULL);
+ btt = BUG_TRAP_TYPE_WARN;
+ }
+ return btt;
}

/*