Commit 70010521 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'x86_core_for_5.18_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 CET-IBT (Control-Flow-Integrity) support from Peter Zijlstra:
 "Add support for Intel CET-IBT, available since Tigerlake (11th gen),
  which is a coarse grained, hardware based, forward edge
  Control-Flow-Integrity mechanism where any indirect CALL/JMP must
  target an ENDBR instruction or suffer #CP.

  Additionally, since Alderlake (12th gen)/Sapphire-Rapids, speculation
  is limited to 2 instructions (and typically fewer) on branch targets
  not starting with ENDBR. CET-IBT also limits speculation of the next
  sequential instruction after the indirect CALL/JMP [1].

  CET-IBT is fundamentally incompatible with retpolines, but provides,
  as described above, speculation limits itself"

[1] https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/technical-documentation/branch-history-injection.html

* tag 'x86_core_for_5.18_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (53 commits)
  kvm/emulate: Fix SETcc emulation for ENDBR
  x86/Kconfig: Only allow CONFIG_X86_KERNEL_IBT with ld.lld >= 14.0.0
  x86/Kconfig: Only enable CONFIG_CC_HAS_IBT for clang >= 14.0.0
  kbuild: Fixup the IBT kbuild changes
  x86/Kconfig: Do not allow CONFIG_X86_X32_ABI=y with llvm-objcopy
  x86: Remove toolchain check for X32 ABI capability
  x86/alternative: Use .ibt_endbr_seal to seal indirect calls
  objtool: Find unused ENDBR instructions
  objtool: Validate IBT assumptions
  objtool: Add IBT/ENDBR decoding
  objtool: Read the NOENDBR annotation
  x86: Annotate idtentry_df()
  x86,objtool: Move the ASM_REACHABLE annotation to objtool.h
  x86: Annotate call_on_stack()
  objtool: Rework ASM_REACHABLE
  x86: Mark __invalid_creds() __noreturn
  exit: Mark do_group_exit() __noreturn
  x86: Mark stop_this_cpu() __noreturn
  objtool: Ignore extra-symbol code
  objtool: Rename --duplicate to --lto
  ...
parents f0228146 3986f65d
Loading
Loading
Loading
Loading
+0 −11
Original line number Diff line number Diff line
@@ -17,17 +17,6 @@ static inline void klp_arch_set_pc(struct ftrace_regs *fregs, unsigned long ip)
	ftrace_instruction_pointer_set(fregs, ip);
}

#define klp_get_ftrace_location klp_get_ftrace_location
static inline unsigned long klp_get_ftrace_location(unsigned long faddr)
{
	/*
	 * Live patch works on PPC32 and only with -mprofile-kernel on PPC64. In
	 * both cases, the ftrace location is always within the first 16 bytes.
	 */
	return ftrace_location_range(faddr, faddr + 16);
}
#endif /* CONFIG_LIVEPATCH */

#ifdef CONFIG_LIVEPATCH_64
static inline void klp_init_thread_info(struct task_struct *p)
{
+21 −13
Original line number Diff line number Diff line
@@ -105,6 +105,27 @@ kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset)
	return addr;
}

static bool arch_kprobe_on_func_entry(unsigned long offset)
{
#ifdef PPC64_ELF_ABI_v2
#ifdef CONFIG_KPROBES_ON_FTRACE
	return offset <= 16;
#else
	return offset <= 8;
#endif
#else
	return !offset;
#endif
}

/* XXX try and fold the magic of kprobe_lookup_name() in this */
kprobe_opcode_t *arch_adjust_kprobe_addr(unsigned long addr, unsigned long offset,
					 bool *on_func_entry)
{
	*on_func_entry = arch_kprobe_on_func_entry(offset);
	return (kprobe_opcode_t *)(addr + offset);
}

void *alloc_insn_page(void)
{
	void *page;
@@ -218,19 +239,6 @@ static nokprobe_inline void set_current_kprobe(struct kprobe *p, struct pt_regs
	kcb->kprobe_saved_msr = regs->msr;
}

bool arch_kprobe_on_func_entry(unsigned long offset)
{
#ifdef PPC64_ELF_ABI_v2
#ifdef CONFIG_KPROBES_ON_FTRACE
	return offset <= 16;
#else
	return offset <= 8;
#endif
#else
	return !offset;
#endif
}

void arch_prepare_kretprobe(struct kretprobe_instance *ri, struct pt_regs *regs)
{
	ri->ret_addr = (kprobe_opcode_t *)regs->link;
+4 −0
Original line number Diff line number Diff line
@@ -424,6 +424,10 @@ void __init check_bugs(void)
	os_check_bugs();
}

void apply_ibt_endbr(s32 *start, s32 *end)
{
}

void apply_retpolines(s32 *start, s32 *end)
{
}
+37 −6
Original line number Diff line number Diff line
@@ -1842,6 +1842,36 @@ 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
	# Clang/LLVM >= 14
	# https://github.com/llvm/llvm-project/commit/e0b89df2e0f0130881bf6c39bf31d7f6aac00e0f
	# https://github.com/llvm/llvm-project/commit/dfcf69770bc522b9e411c66454934a37c1f35332
	def_bool ((CC_IS_GCC && $(cc-option, -fcf-protection=branch -mindirect-branch-register)) || \
		  (CC_IS_CLANG && CLANG_VERSION >= 140000)) && \
		  $(as-instr,endbr64)

config X86_KERNEL_IBT
	prompt "Indirect Branch Tracking"
	bool
	depends on X86_64 && CC_HAS_IBT && STACK_VALIDATION
	# https://github.com/llvm/llvm-project/commit/9d7001eba9c4cb311e03cd8cdc231f9e579f2d0f
	depends on !LD_IS_LLD || LLD_VERSION >= 140000
	help
	  Build the kernel with support for Indirect Branch Tracking, a
	  hardware support course-grain forward-edge Control Flow Integrity
	  protection. It enforces that all indirect calls must land on
	  an ENDBR instruction, as such, the compiler will instrument the
	  code with them to make this happen.

	  In addition to building the kernel with IBT, seal all functions that
	  are not indirect call targets, avoiding them ever becomming one.

	  This requires LTO like objtool runs and will slow down the build. It
	  does significantly reduce the number of ENDBR instructions in the
	  kernel image.

config X86_INTEL_MEMORY_PROTECTION_KEYS
	prompt "Memory Protection Keys"
	def_bool y
@@ -2815,19 +2845,20 @@ config IA32_AOUT
	help
	  Support old a.out binaries in the 32bit emulation.

config X86_X32
config X86_X32_ABI
	bool "x32 ABI for 64-bit mode"
	depends on X86_64
	# llvm-objcopy does not convert x86_64 .note.gnu.property or
	# compressed debug sections to x86_x32 properly:
	# https://github.com/ClangBuiltLinux/linux/issues/514
	# https://github.com/ClangBuiltLinux/linux/issues/1141
	depends on $(success,$(OBJCOPY) --version | head -n1 | grep -qv llvm)
	help
	  Include code to run binaries for the x32 native 32-bit ABI
	  for 64-bit processors.  An x32 process gets access to the
	  full 64-bit register file and wide data path while leaving
	  pointers at 32 bits for smaller memory footprint.

	  You will need a recent binutils (2.22 or later) with
	  elf32_x86_64 support enabled to compile a kernel with this
	  option set.

config COMPAT_32
	def_bool y
	depends on IA32_EMULATION || X86_32
@@ -2836,7 +2867,7 @@ config COMPAT_32

config COMPAT
	def_bool y
	depends on IA32_EMULATION || X86_X32
	depends on IA32_EMULATION || X86_X32_ABI

if COMPAT
config COMPAT_FOR_U64_ALIGNMENT
+14 −18
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@ endif

# How to compile the 16-bit code.  Note we always compile for -march=i386;
# that way we can complain to the user if the CPU is insufficient.
REALMODE_CFLAGS	:= -m16 -g -Os -DDISABLE_BRANCH_PROFILING \
REALMODE_CFLAGS	:= -m16 -g -Os -DDISABLE_BRANCH_PROFILING -D__DISABLE_EXPORTS \
		   -Wall -Wstrict-prototypes -march=i386 -mregparm=3 \
		   -fno-strict-aliasing -fomit-frame-pointer -fno-pic \
		   -mno-mmx -mno-sse $(call cc-option,-fcf-protection=none)
@@ -62,8 +62,20 @@ 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_KERNEL_IBT),y)
#
# Kernel IBT has S_CET.NOTRACK_EN=0, as such the compilers must not generate
# NOTRACK prefixes. Current generation compilers unconditionally employ NOTRACK
# for jump-tables, as such, disable jump-tables for now.
#
# (jump-tables are implicitly disabled by RETPOLINE)
#
#   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104816
#
KBUILD_CFLAGS += $(call cc-option,-fcf-protection=branch -fno-jump-tables)
else
KBUILD_CFLAGS += $(call cc-option,-fcf-protection=none)
endif

ifeq ($(CONFIG_X86_32),y)
        BITS := 32
@@ -140,22 +152,6 @@ else
        KBUILD_CFLAGS += -mcmodel=kernel
endif

ifdef CONFIG_X86_X32
	x32_ld_ok := $(call try-run,\
			/bin/echo -e '1: .quad 1b' | \
			$(CC) $(KBUILD_AFLAGS) -c -x assembler -o "$$TMP" - && \
			$(OBJCOPY) -O elf32-x86-64 "$$TMP" "$$TMP.o" && \
			$(LD) -m elf32_x86_64 "$$TMP.o" -o "$$TMP",y,n)
        ifeq ($(x32_ld_ok),y)
                CONFIG_X86_X32_ABI := y
                KBUILD_AFLAGS += -DCONFIG_X86_X32_ABI
                KBUILD_CFLAGS += -DCONFIG_X86_X32_ABI
        else
                $(warning CONFIG_X86_X32 enabled but no binutils support)
        endif
endif
export CONFIG_X86_X32_ABI

#
# If the function graph tracer is used with mcount instead of fentry,
# '-maccumulate-outgoing-args' is needed to prevent a GCC bug
Loading