From b54083c5cba3b32460fe1b368ffc258fcfdee03e Mon Sep 17 00:00:00 2001 From: Sami Tolvanen Date: Thu, 9 Jan 2020 13:11:05 -0800 Subject: [PATCH] ANDROID: x86: map CFI jump tables in pti_clone_entry_text Allow CFI enabled entry code to make indirect calls by also mapping CFI jump tables, and add a check to ensure the jump table section is not empty. Bug: 145297900 Change-Id: I1204c50a139ba62234f3bb4699c50921a831162b Signed-off-by: Sami Tolvanen --- arch/x86/include/asm/sections.h | 1 + arch/x86/kernel/vmlinux.lds.S | 11 +++++++++++ arch/x86/mm/pti.c | 9 +++++++++ 3 files changed, 21 insertions(+) diff --git a/arch/x86/include/asm/sections.h b/arch/x86/include/asm/sections.h index 949aa3a65f45..dde9f925b474 100644 --- a/arch/x86/include/asm/sections.h +++ b/arch/x86/include/asm/sections.h @@ -6,6 +6,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 86d037b5722a..8eb0c6658de3 100644 --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S @@ -151,6 +151,13 @@ SECTIONS *(.text.__x86.indirect_thunk) __indirect_thunk_end = .; #endif + +#ifdef CONFIG_CFI_CLANG + . = ALIGN(PAGE_SIZE); + __cfi_jt_start = .; + *(.text..L.cfi.jumptable .text..L.cfi.jumptable.*) + __cfi_jt_end = .; +#endif } :text = 0x9090 NOTES :text :note @@ -434,3 +441,7 @@ INIT_PER_CPU(irq_stack_union); "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 fba2ddcd61a7..8316cdb407a0 100644 --- a/arch/x86/mm/pti.c +++ b/arch/x86/mm/pti.c @@ -482,6 +482,15 @@ static void pti_clone_entry_text(void) pti_clone_pgtable((unsigned long) __entry_text_start, (unsigned long) __irqentry_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); } /*