Messages in this thread Patch in this message | | | Date | Fri, 18 Feb 2022 17:49:07 +0100 | From | Peter Zijlstra <> | Subject | [PATCH 05/29] x86: Base IBT bits |
| |
Add Kconfig, Makefile and basic instruction support for x86 IBT.
TODO: clang
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> --- arch/x86/Kconfig | 15 ++++++++++++ arch/x86/Makefile | 5 +++- arch/x86/include/asm/ibt.h | 53 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 1 deletion(-)
--- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1861,6 +1861,21 @@ config X86_UMIP specific cases in protected and virtual-8086 modes. Emulated results are dummy. +config CC_HAS_IBT + # GCC >= 9 and binutils >= 2.29 + # Retpoline check to work around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93654 + def_bool $(cc-option, -fcf-protection=branch -mindirect-branch-register) && $(as-instr,endbr64) + +config X86_IBT + prompt "Indirect Branch Tracking" + bool + depends on X86_64 && CC_HAS_IBT + help + Build the kernel with support for Indirect Branch Tracking, a + hardware supported CFI scheme. Any indirect call must land on + an ENDBR instruction, as such, the compiler will litter the + code with them to make this happen. + config X86_INTEL_MEMORY_PROTECTION_KEYS prompt "Memory Protection Keys" def_bool y --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -62,8 +62,11 @@ export BITS # KBUILD_CFLAGS += -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -# Intel CET isn't enabled in the kernel +ifeq ($(CONFIG_X86_IBT),y) +KBUILD_CFLAGS += $(call cc-option,-fcf-protection=branch) +else KBUILD_CFLAGS += $(call cc-option,-fcf-protection=none) +endif ifeq ($(CONFIG_X86_32),y) BITS := 32 --- /dev/null +++ b/arch/x86/include/asm/ibt.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_X86_IBT_H +#define _ASM_X86_IBT_H + +#ifdef CONFIG_X86_IBT + +#ifndef __ASSEMBLY__ + +#ifdef CONFIG_X86_64 +#define ASM_ENDBR "endbr64\n\t" +#else +#define ASM_ENDBR "endbr32\n\t" +#endif + +#define __noendbr __attribute__((nocf_check)) + +/* + * A bit convoluted, but matches both endbr32 and endbr64 without + * having either as literal in the text. + */ +static inline bool is_endbr(const void *addr) +{ + unsigned int val = ~*(unsigned int *)addr; + val |= 0x01000000U; + return val == ~0xfa1e0ff3; +} + +#else /* __ASSEMBLY__ */ + +#ifdef CONFIG_X86_64 +#define ENDBR endbr64 +#else +#define ENDBR endbr32 +#endif + +#endif /* __ASSEMBLY__ */ + +#else /* !IBT */ + +#ifndef __ASSEMBLY__ + +#define ASM_ENDBR + +#define __noendbr + +#else /* __ASSEMBLY__ */ + +#define ENDBR + +#endif /* __ASSEMBLY__ */ + +#endif /* CONFIG_X86_IBT */ +#endif /* _ASM_X86_IBT_H */
| |