diff --git a/arch/x86/include/asm/sections.h b/arch/x86/include/asm/sections.h index a6e8373a5170..5abf1301d3ff 100644 --- a/arch/x86/include/asm/sections.h +++ b/arch/x86/include/asm/sections.h @@ -8,6 +8,7 @@ #include extern char __brk_base[], __brk_limit[]; +extern char __cfi_jt_start[], __cfi_jt_end[]; extern char __end_rodata_aligned[]; #if defined(CONFIG_X86_64) diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S index bf9e0adb5b7e..9fef0742de1d 100644 --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S @@ -490,3 +490,7 @@ INIT_PER_CPU(irq_stack_backing_store); "kexec control code size is too big"); #endif +#ifdef CONFIG_CFI_CLANG +. = ASSERT((__cfi_jt_end - __cfi_jt_start > 0), + "CFI jump table is empty"); +#endif diff --git a/arch/x86/mm/pti.c b/arch/x86/mm/pti.c index 1aab92930569..f4ee420cc3be 100644 --- a/arch/x86/mm/pti.c +++ b/arch/x86/mm/pti.c @@ -498,6 +498,15 @@ static void pti_clone_entry_text(void) pti_clone_pgtable((unsigned long) __entry_text_start, (unsigned long) __entry_text_end, PTI_CLONE_PMD); + + /* + * If CFI is enabled, also map jump tables, so the entry code can + * make indirect calls. + */ + if (IS_ENABLED(CONFIG_CFI_CLANG)) + pti_clone_pgtable((unsigned long) __cfi_jt_start, + (unsigned long) __cfi_jt_end, + PTI_CLONE_PMD); } /*