Skip to content

Commit 04505bb

Browse files
author
Peter Zijlstra
committed
x86/fineibt: Poison ENDBR at +0
Alyssa noticed that when building the kernel with CFI_CLANG+IBT and booting on IBT enabled hardware to obtain FineIBT, the indirect functions look like: __cfi_foo: endbr64 subl $hash, %r10d jz 1f ud2 nop 1: foo: endbr64 This is because the compiler generates code for kCFI+IBT. In that case the caller does the hash check and will jump to +0, so there must be an ENDBR there. The compiler doesn't know about FineIBT at all; also it is possible to actually use kCFI+IBT when booting with 'cfi=kcfi' on IBT enabled hardware. Having this second ENDBR however makes it possible to elide the CFI check. Therefore, we should poison this second ENDBR when switching to FineIBT mode. Fixes: 931ab63 ("x86/ibt: Implement FineIBT") Reported-by: "Milburn, Alyssa" <alyssa.milburn@intel.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Reviewed-by: Kees Cook <keescook@chromium.org> Reviewed-by: Sami Tolvanen <samitolvanen@google.com> Link: https://lore.kernel.org/r/20230615193722.194131053@infradead.org
1 parent 3aec4ec commit 04505bb

File tree

1 file changed

+16
-0
lines changed

1 file changed

+16
-0
lines changed

arch/x86/kernel/alternative.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1068,6 +1068,17 @@ static int cfi_rewrite_preamble(s32 *start, s32 *end)
10681068
return 0;
10691069
}
10701070

1071+
static void cfi_rewrite_endbr(s32 *start, s32 *end)
1072+
{
1073+
s32 *s;
1074+
1075+
for (s = start; s < end; s++) {
1076+
void *addr = (void *)s + *s;
1077+
1078+
poison_endbr(addr+16, false);
1079+
}
1080+
}
1081+
10711082
/* .retpoline_sites */
10721083
static int cfi_rand_callers(s32 *start, s32 *end)
10731084
{
@@ -1162,14 +1173,19 @@ static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline,
11621173
return;
11631174

11641175
case CFI_FINEIBT:
1176+
/* place the FineIBT preamble at func()-16 */
11651177
ret = cfi_rewrite_preamble(start_cfi, end_cfi);
11661178
if (ret)
11671179
goto err;
11681180

1181+
/* rewrite the callers to target func()-16 */
11691182
ret = cfi_rewrite_callers(start_retpoline, end_retpoline);
11701183
if (ret)
11711184
goto err;
11721185

1186+
/* now that nobody targets func()+0, remove ENDBR there */
1187+
cfi_rewrite_endbr(start_cfi, end_cfi);
1188+
11731189
if (builtin)
11741190
pr_info("Using FineIBT CFI\n");
11751191
return;

0 commit comments

Comments
 (0)