Commit 9831c625 authored by Peter Zijlstra's avatar Peter Zijlstra

x86/cfi: Extend ENDBR sealing to kCFI

Kees noted that IBT sealing could be extended to kCFI.

Fundamentally it is the list of functions that do not have their
address taken and are thus never called indirectly. It doesn't matter
that objtool uses IBT infrastructure to determine this list, once we
have it it can also be used to clobber kCFI hashes and avoid kCFI
indirect calls.
Suggested-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>
Reviewed-by: default avatarSami Tolvanen <samitolvanen@google.com>
Link: https://lkml.kernel.org/r/20230622144321.494426891%40infradead.org
parent be0fffa5
...@@ -778,6 +778,8 @@ void __init_or_module noinline apply_returns(s32 *start, s32 *end) { } ...@@ -778,6 +778,8 @@ void __init_or_module noinline apply_returns(s32 *start, s32 *end) { }
#ifdef CONFIG_X86_KERNEL_IBT #ifdef CONFIG_X86_KERNEL_IBT
static void poison_cfi(void *addr);
static void __init_or_module poison_endbr(void *addr, bool warn) static void __init_or_module poison_endbr(void *addr, bool warn)
{ {
u32 endbr, poison = gen_endbr_poison(); u32 endbr, poison = gen_endbr_poison();
...@@ -802,6 +804,9 @@ static void __init_or_module poison_endbr(void *addr, bool warn) ...@@ -802,6 +804,9 @@ static void __init_or_module poison_endbr(void *addr, bool warn)
/* /*
* Generated by: objtool --ibt * Generated by: objtool --ibt
*
* Seal the functions for indirect calls by clobbering the ENDBR instructions
* and the kCFI hash value.
*/ */
void __init_or_module noinline apply_seal_endbr(s32 *start, s32 *end) void __init_or_module noinline apply_seal_endbr(s32 *start, s32 *end)
{ {
...@@ -812,7 +817,7 @@ void __init_or_module noinline apply_seal_endbr(s32 *start, s32 *end) ...@@ -812,7 +817,7 @@ void __init_or_module noinline apply_seal_endbr(s32 *start, s32 *end)
poison_endbr(addr, true); poison_endbr(addr, true);
if (IS_ENABLED(CONFIG_FINEIBT)) if (IS_ENABLED(CONFIG_FINEIBT))
poison_endbr(addr - 16, false); poison_cfi(addr - 16);
} }
} }
...@@ -1177,6 +1182,41 @@ static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline, ...@@ -1177,6 +1182,41 @@ static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline,
pr_err("Something went horribly wrong trying to rewrite the CFI implementation.\n"); pr_err("Something went horribly wrong trying to rewrite the CFI implementation.\n");
} }
static inline void poison_hash(void *addr)
{
*(u32 *)addr = 0;
}
static void poison_cfi(void *addr)
{
switch (cfi_mode) {
case CFI_FINEIBT:
/*
* __cfi_\func:
* osp nopl (%rax)
* subl $0, %r10d
* jz 1f
* ud2
* 1: nop
*/
poison_endbr(addr, false);
poison_hash(addr + fineibt_preamble_hash);
break;
case CFI_KCFI:
/*
* __cfi_\func:
* movl $0, %eax
* .skip 11, 0x90
*/
poison_hash(addr + 1);
break;
default:
break;
}
}
#else #else
static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline, static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline,
...@@ -1184,6 +1224,8 @@ static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline, ...@@ -1184,6 +1224,8 @@ static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline,
{ {
} }
static void poison_cfi(void *addr) { }
#endif #endif
void apply_fineibt(s32 *start_retpoline, s32 *end_retpoline, void apply_fineibt(s32 *start_retpoline, s32 *end_retpoline,
......
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