mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
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 ...
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -195,6 +195,7 @@ crc_array:
|
||||
.altmacro
|
||||
LABEL crc_ %i
|
||||
.noaltmacro
|
||||
ENDBR
|
||||
crc32q -i*8(block_0), crc_init
|
||||
crc32q -i*8(block_1), crc1
|
||||
crc32q -i*8(block_2), crc2
|
||||
@@ -204,6 +205,7 @@ LABEL crc_ %i
|
||||
.altmacro
|
||||
LABEL crc_ %i
|
||||
.noaltmacro
|
||||
ENDBR
|
||||
crc32q -i*8(block_0), crc_init
|
||||
crc32q -i*8(block_1), crc1
|
||||
# SKIP crc32 -i*8(block_2), crc2 ; Don't do this one yet
|
||||
@@ -237,6 +239,7 @@ LABEL crc_ %i
|
||||
################################################################
|
||||
|
||||
LABEL crc_ 0
|
||||
ENDBR
|
||||
mov tmp, len
|
||||
cmp $128*24, tmp
|
||||
jae full_block
|
||||
|
||||
@@ -86,6 +86,7 @@
|
||||
|
||||
SYM_CODE_START(entry_SYSCALL_64)
|
||||
UNWIND_HINT_EMPTY
|
||||
ENDBR
|
||||
|
||||
swapgs
|
||||
/* tss.sp2 is scratch space. */
|
||||
@@ -94,6 +95,7 @@ SYM_CODE_START(entry_SYSCALL_64)
|
||||
movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
|
||||
|
||||
SYM_INNER_LABEL(entry_SYSCALL_64_safe_stack, SYM_L_GLOBAL)
|
||||
ANNOTATE_NOENDBR
|
||||
|
||||
/* Construct struct pt_regs on stack */
|
||||
pushq $__USER_DS /* pt_regs->ss */
|
||||
@@ -276,6 +278,7 @@ SYM_FUNC_END(__switch_to_asm)
|
||||
.pushsection .text, "ax"
|
||||
SYM_CODE_START(ret_from_fork)
|
||||
UNWIND_HINT_EMPTY
|
||||
ANNOTATE_NOENDBR // copy_thread
|
||||
movq %rax, %rdi
|
||||
call schedule_tail /* rdi: 'prev' task parameter */
|
||||
|
||||
@@ -350,6 +353,7 @@ SYM_CODE_END(ret_from_fork)
|
||||
.macro idtentry vector asmsym cfunc has_error_code:req
|
||||
SYM_CODE_START(\asmsym)
|
||||
UNWIND_HINT_IRET_REGS offset=\has_error_code*8
|
||||
ENDBR
|
||||
ASM_CLAC
|
||||
|
||||
.if \has_error_code == 0
|
||||
@@ -417,6 +421,7 @@ SYM_CODE_END(\asmsym)
|
||||
.macro idtentry_mce_db vector asmsym cfunc
|
||||
SYM_CODE_START(\asmsym)
|
||||
UNWIND_HINT_IRET_REGS
|
||||
ENDBR
|
||||
ASM_CLAC
|
||||
|
||||
pushq $-1 /* ORIG_RAX: no syscall to restart */
|
||||
@@ -472,6 +477,7 @@ SYM_CODE_END(\asmsym)
|
||||
.macro idtentry_vc vector asmsym cfunc
|
||||
SYM_CODE_START(\asmsym)
|
||||
UNWIND_HINT_IRET_REGS
|
||||
ENDBR
|
||||
ASM_CLAC
|
||||
|
||||
/*
|
||||
@@ -533,6 +539,7 @@ SYM_CODE_END(\asmsym)
|
||||
.macro idtentry_df vector asmsym cfunc
|
||||
SYM_CODE_START(\asmsym)
|
||||
UNWIND_HINT_IRET_REGS offset=8
|
||||
ENDBR
|
||||
ASM_CLAC
|
||||
|
||||
/* paranoid_entry returns GS information for paranoid_exit in EBX. */
|
||||
@@ -544,6 +551,9 @@ SYM_CODE_START(\asmsym)
|
||||
movq $-1, ORIG_RAX(%rsp) /* no syscall to restart */
|
||||
call \cfunc
|
||||
|
||||
/* For some configurations \cfunc ends up being a noreturn. */
|
||||
REACHABLE
|
||||
|
||||
jmp paranoid_exit
|
||||
|
||||
_ASM_NOKPROBE(\asmsym)
|
||||
@@ -564,6 +574,7 @@ __irqentry_text_start:
|
||||
.align 16
|
||||
.globl __irqentry_text_end
|
||||
__irqentry_text_end:
|
||||
ANNOTATE_NOENDBR
|
||||
|
||||
SYM_CODE_START_LOCAL(common_interrupt_return)
|
||||
SYM_INNER_LABEL(swapgs_restore_regs_and_return_to_usermode, SYM_L_GLOBAL)
|
||||
@@ -608,8 +619,8 @@ SYM_INNER_LABEL(swapgs_restore_regs_and_return_to_usermode, SYM_L_GLOBAL)
|
||||
|
||||
/* Restore RDI. */
|
||||
popq %rdi
|
||||
SWAPGS
|
||||
INTERRUPT_RETURN
|
||||
swapgs
|
||||
jmp .Lnative_iret
|
||||
|
||||
|
||||
SYM_INNER_LABEL(restore_regs_and_return_to_kernel, SYM_L_GLOBAL)
|
||||
@@ -626,9 +637,14 @@ SYM_INNER_LABEL(restore_regs_and_return_to_kernel, SYM_L_GLOBAL)
|
||||
* ARCH_HAS_MEMBARRIER_SYNC_CORE rely on IRET core serialization
|
||||
* when returning from IPI handler.
|
||||
*/
|
||||
INTERRUPT_RETURN
|
||||
#ifdef CONFIG_XEN_PV
|
||||
SYM_INNER_LABEL(early_xen_iret_patch, SYM_L_GLOBAL)
|
||||
ANNOTATE_NOENDBR
|
||||
.byte 0xe9
|
||||
.long .Lnative_iret - (. + 4)
|
||||
#endif
|
||||
|
||||
SYM_INNER_LABEL_ALIGN(native_iret, SYM_L_GLOBAL)
|
||||
.Lnative_iret:
|
||||
UNWIND_HINT_IRET_REGS
|
||||
/*
|
||||
* Are we returning to a stack segment from the LDT? Note: in
|
||||
@@ -640,6 +656,7 @@ SYM_INNER_LABEL_ALIGN(native_iret, SYM_L_GLOBAL)
|
||||
#endif
|
||||
|
||||
SYM_INNER_LABEL(native_irq_return_iret, SYM_L_GLOBAL)
|
||||
ANNOTATE_NOENDBR // exc_double_fault
|
||||
/*
|
||||
* This may fault. Non-paranoid faults on return to userspace are
|
||||
* handled by fixup_bad_iret. These include #SS, #GP, and #NP.
|
||||
@@ -734,6 +751,7 @@ SYM_FUNC_START(asm_load_gs_index)
|
||||
FRAME_BEGIN
|
||||
swapgs
|
||||
.Lgs_change:
|
||||
ANNOTATE_NOENDBR // error_entry
|
||||
movl %edi, %gs
|
||||
2: ALTERNATIVE "", "mfence", X86_BUG_SWAPGS_FENCE
|
||||
swapgs
|
||||
@@ -804,6 +822,7 @@ SYM_CODE_END(exc_xen_hypervisor_callback)
|
||||
*/
|
||||
SYM_CODE_START(xen_failsafe_callback)
|
||||
UNWIND_HINT_EMPTY
|
||||
ENDBR
|
||||
movl %ds, %ecx
|
||||
cmpw %cx, 0x10(%rsp)
|
||||
jne 1f
|
||||
@@ -1063,6 +1082,7 @@ SYM_CODE_END(error_return)
|
||||
*/
|
||||
SYM_CODE_START(asm_exc_nmi)
|
||||
UNWIND_HINT_IRET_REGS
|
||||
ENDBR
|
||||
|
||||
/*
|
||||
* We allow breakpoints in NMIs. If a breakpoint occurs, then
|
||||
@@ -1310,6 +1330,7 @@ first_nmi:
|
||||
#endif
|
||||
|
||||
repeat_nmi:
|
||||
ANNOTATE_NOENDBR // this code
|
||||
/*
|
||||
* If there was a nested NMI, the first NMI's iret will return
|
||||
* here. But NMIs are still enabled and we can take another
|
||||
@@ -1338,6 +1359,7 @@ repeat_nmi:
|
||||
.endr
|
||||
subq $(5*8), %rsp
|
||||
end_repeat_nmi:
|
||||
ANNOTATE_NOENDBR // this code
|
||||
|
||||
/*
|
||||
* Everything below this point can be preempted by a nested NMI.
|
||||
@@ -1421,6 +1443,7 @@ SYM_CODE_END(asm_exc_nmi)
|
||||
*/
|
||||
SYM_CODE_START(ignore_sysret)
|
||||
UNWIND_HINT_EMPTY
|
||||
ENDBR
|
||||
mov $-ENOSYS, %eax
|
||||
sysretl
|
||||
SYM_CODE_END(ignore_sysret)
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
*/
|
||||
SYM_CODE_START(entry_SYSENTER_compat)
|
||||
UNWIND_HINT_EMPTY
|
||||
ENDBR
|
||||
/* Interrupts are off on entry. */
|
||||
SWAPGS
|
||||
|
||||
@@ -147,6 +148,7 @@ SYM_INNER_LABEL(entry_SYSENTER_compat_after_hwframe, SYM_L_GLOBAL)
|
||||
popfq
|
||||
jmp .Lsysenter_flags_fixed
|
||||
SYM_INNER_LABEL(__end_entry_SYSENTER_compat, SYM_L_GLOBAL)
|
||||
ANNOTATE_NOENDBR // is_sysenter_singlestep
|
||||
SYM_CODE_END(entry_SYSENTER_compat)
|
||||
|
||||
/*
|
||||
@@ -198,6 +200,7 @@ SYM_CODE_END(entry_SYSENTER_compat)
|
||||
*/
|
||||
SYM_CODE_START(entry_SYSCALL_compat)
|
||||
UNWIND_HINT_EMPTY
|
||||
ENDBR
|
||||
/* Interrupts are off on entry. */
|
||||
swapgs
|
||||
|
||||
@@ -211,6 +214,7 @@ SYM_CODE_START(entry_SYSCALL_compat)
|
||||
movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
|
||||
|
||||
SYM_INNER_LABEL(entry_SYSCALL_compat_safe_stack, SYM_L_GLOBAL)
|
||||
ANNOTATE_NOENDBR
|
||||
|
||||
/* Construct struct pt_regs on stack */
|
||||
pushq $__USER32_DS /* pt_regs->ss */
|
||||
@@ -340,6 +344,7 @@ SYM_CODE_END(entry_SYSCALL_compat)
|
||||
*/
|
||||
SYM_CODE_START(entry_INT80_compat)
|
||||
UNWIND_HINT_EMPTY
|
||||
ENDBR
|
||||
/*
|
||||
* Interrupts are off on entry.
|
||||
*/
|
||||
|
||||
@@ -67,7 +67,7 @@ uapisyshdr-y += unistd_32.h unistd_64.h unistd_x32.h
|
||||
syshdr-y += syscalls_32.h
|
||||
syshdr-$(CONFIG_X86_64) += unistd_32_ia32.h unistd_64_x32.h
|
||||
syshdr-$(CONFIG_X86_64) += syscalls_64.h
|
||||
syshdr-$(CONFIG_X86_X32) += syscalls_x32.h
|
||||
syshdr-$(CONFIG_X86_X32_ABI) += syscalls_x32.h
|
||||
syshdr-$(CONFIG_XEN) += xen-hypercalls.h
|
||||
|
||||
uapisyshdr-y := $(addprefix $(uapi)/, $(uapisyshdr-y))
|
||||
|
||||
@@ -76,6 +76,7 @@ extern int alternatives_patched;
|
||||
extern void alternative_instructions(void);
|
||||
extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
|
||||
extern void apply_retpolines(s32 *start, s32 *end);
|
||||
extern void apply_ibt_endbr(s32 *start, s32 *end);
|
||||
|
||||
struct module;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <linux/stringify.h>
|
||||
#include <linux/instrumentation.h>
|
||||
#include <linux/objtool.h>
|
||||
|
||||
/*
|
||||
* Despite that some emulators terminate on UD2, we use it for WARN().
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <linux/topology.h>
|
||||
#include <linux/nodemask.h>
|
||||
#include <linux/percpu.h>
|
||||
#include <asm/ibt.h>
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
@@ -72,4 +73,7 @@ void init_ia32_feat_ctl(struct cpuinfo_x86 *c);
|
||||
#else
|
||||
static inline void init_ia32_feat_ctl(struct cpuinfo_x86 *c) {}
|
||||
#endif
|
||||
|
||||
extern __noendbr void cet_disable(void);
|
||||
|
||||
#endif /* _ASM_X86_CPU_H */
|
||||
|
||||
@@ -388,6 +388,7 @@
|
||||
#define X86_FEATURE_TSXLDTRK (18*32+16) /* TSX Suspend Load Address Tracking */
|
||||
#define X86_FEATURE_PCONFIG (18*32+18) /* Intel PCONFIG */
|
||||
#define X86_FEATURE_ARCH_LBR (18*32+19) /* Intel ARCH LBR */
|
||||
#define X86_FEATURE_IBT (18*32+20) /* Indirect Branch Tracking */
|
||||
#define X86_FEATURE_AMX_BF16 (18*32+22) /* AMX bf16 Support */
|
||||
#define X86_FEATURE_AVX512_FP16 (18*32+23) /* AVX512 FP16 */
|
||||
#define X86_FEATURE_AMX_TILE (18*32+24) /* AMX tile Support */
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <asm/tlb.h>
|
||||
#include <asm/nospec-branch.h>
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/ibt.h>
|
||||
#include <linux/build_bug.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pgtable.h>
|
||||
@@ -120,8 +121,12 @@ extern asmlinkage u64 __efi_call(void *fp, ...);
|
||||
efi_enter_mm(); \
|
||||
})
|
||||
|
||||
#define arch_efi_call_virt(p, f, args...) \
|
||||
efi_call((void *)p->f, args) \
|
||||
#define arch_efi_call_virt(p, f, args...) ({ \
|
||||
u64 ret, ibt = ibt_save(); \
|
||||
ret = efi_call((void *)p->f, args); \
|
||||
ibt_restore(ibt); \
|
||||
ret; \
|
||||
})
|
||||
|
||||
#define arch_efi_call_virt_teardown() \
|
||||
({ \
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ASM_X86_IBT_H
|
||||
#define _ASM_X86_IBT_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/*
|
||||
* The rules for enabling IBT are:
|
||||
*
|
||||
* - CC_HAS_IBT: the toolchain supports it
|
||||
* - X86_KERNEL_IBT: it is selected in Kconfig
|
||||
* - !__DISABLE_EXPORTS: this is regular kernel code
|
||||
*
|
||||
* Esp. that latter one is a bit non-obvious, but some code like compressed,
|
||||
* purgatory, realmode etc.. is built with custom CFLAGS that do not include
|
||||
* -fcf-protection=branch and things will go *bang*.
|
||||
*
|
||||
* When all the above are satisfied, HAS_KERNEL_IBT will be 1, otherwise 0.
|
||||
*/
|
||||
#if defined(CONFIG_X86_KERNEL_IBT) && !defined(__DISABLE_EXPORTS)
|
||||
|
||||
#define HAS_KERNEL_IBT 1
|
||||
|
||||
#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))
|
||||
|
||||
static inline __attribute_const__ u32 gen_endbr(void)
|
||||
{
|
||||
u32 endbr;
|
||||
|
||||
/*
|
||||
* Generate ENDBR64 in a way that is sure to not result in
|
||||
* an ENDBR64 instruction as immediate.
|
||||
*/
|
||||
asm ( "mov $~0xfa1e0ff3, %[endbr]\n\t"
|
||||
"not %[endbr]\n\t"
|
||||
: [endbr] "=&r" (endbr) );
|
||||
|
||||
return endbr;
|
||||
}
|
||||
|
||||
static inline __attribute_const__ u32 gen_endbr_poison(void)
|
||||
{
|
||||
/*
|
||||
* 4 byte NOP that isn't NOP4 (in fact it is OSP NOP3), such that it
|
||||
* will be unique to (former) ENDBR sites.
|
||||
*/
|
||||
return 0x001f0f66; /* osp nopl (%rax) */
|
||||
}
|
||||
|
||||
static inline bool is_endbr(u32 val)
|
||||
{
|
||||
if (val == gen_endbr_poison())
|
||||
return true;
|
||||
|
||||
val &= ~0x01000000U; /* ENDBR32 -> ENDBR64 */
|
||||
return val == gen_endbr();
|
||||
}
|
||||
|
||||
extern __noendbr u64 ibt_save(void);
|
||||
extern __noendbr void ibt_restore(u64 save);
|
||||
|
||||
#else /* __ASSEMBLY__ */
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
#define ENDBR endbr64
|
||||
#else
|
||||
#define ENDBR endbr32
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#else /* !IBT */
|
||||
|
||||
#define HAS_KERNEL_IBT 0
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#define ASM_ENDBR
|
||||
|
||||
#define __noendbr
|
||||
|
||||
static inline bool is_endbr(u32 val) { return false; }
|
||||
|
||||
static inline u64 ibt_save(void) { return 0; }
|
||||
static inline void ibt_restore(u64 save) { }
|
||||
|
||||
#else /* __ASSEMBLY__ */
|
||||
|
||||
#define ENDBR
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* CONFIG_X86_KERNEL_IBT */
|
||||
|
||||
#define ENDBR_INSN_SIZE (4*HAS_KERNEL_IBT)
|
||||
|
||||
#endif /* _ASM_X86_IBT_H */
|
||||
@@ -5,6 +5,8 @@
|
||||
/* Interrupts/Exceptions */
|
||||
#include <asm/trapnr.h>
|
||||
|
||||
#define IDT_ALIGN (8 * (1 + HAS_KERNEL_IBT))
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#include <linux/entry-common.h>
|
||||
#include <linux/hardirq.h>
|
||||
@@ -480,7 +482,7 @@ __visible noinstr void func(struct pt_regs *regs, \
|
||||
|
||||
/*
|
||||
* ASM code to emit the common vector entry stubs where each stub is
|
||||
* packed into 8 bytes.
|
||||
* packed into IDT_ALIGN bytes.
|
||||
*
|
||||
* Note, that the 'pushq imm8' is emitted via '.byte 0x6a, vector' because
|
||||
* GCC treats the local vector variable as unsigned int and would expand
|
||||
@@ -492,33 +494,33 @@ __visible noinstr void func(struct pt_regs *regs, \
|
||||
* point is to mask off the bits above bit 7 because the push is sign
|
||||
* extending.
|
||||
*/
|
||||
.align 8
|
||||
.align IDT_ALIGN
|
||||
SYM_CODE_START(irq_entries_start)
|
||||
vector=FIRST_EXTERNAL_VECTOR
|
||||
.rept NR_EXTERNAL_VECTORS
|
||||
UNWIND_HINT_IRET_REGS
|
||||
0 :
|
||||
ENDBR
|
||||
.byte 0x6a, vector
|
||||
jmp asm_common_interrupt
|
||||
nop
|
||||
/* Ensure that the above is 8 bytes max */
|
||||
. = 0b + 8
|
||||
/* Ensure that the above is IDT_ALIGN bytes max */
|
||||
.fill 0b + IDT_ALIGN - ., 1, 0xcc
|
||||
vector = vector+1
|
||||
.endr
|
||||
SYM_CODE_END(irq_entries_start)
|
||||
|
||||
#ifdef CONFIG_X86_LOCAL_APIC
|
||||
.align 8
|
||||
.align IDT_ALIGN
|
||||
SYM_CODE_START(spurious_entries_start)
|
||||
vector=FIRST_SYSTEM_VECTOR
|
||||
.rept NR_SYSTEM_VECTORS
|
||||
UNWIND_HINT_IRET_REGS
|
||||
0 :
|
||||
ENDBR
|
||||
.byte 0x6a, vector
|
||||
jmp asm_spurious_interrupt
|
||||
nop
|
||||
/* Ensure that the above is 8 bytes max */
|
||||
. = 0b + 8
|
||||
/* Ensure that the above is IDT_ALIGN bytes max */
|
||||
.fill 0b + IDT_ALIGN - ., 1, 0xcc
|
||||
vector = vector+1
|
||||
.endr
|
||||
SYM_CODE_END(spurious_entries_start)
|
||||
@@ -615,6 +617,11 @@ DECLARE_IDTENTRY_DF(X86_TRAP_DF, exc_double_fault);
|
||||
DECLARE_IDTENTRY_RAW_ERRORCODE(X86_TRAP_DF, xenpv_exc_double_fault);
|
||||
#endif
|
||||
|
||||
/* #CP */
|
||||
#ifdef CONFIG_X86_KERNEL_IBT
|
||||
DECLARE_IDTENTRY_ERRORCODE(X86_TRAP_CP, exc_control_protection);
|
||||
#endif
|
||||
|
||||
/* #VC */
|
||||
#ifdef CONFIG_AMD_MEM_ENCRYPT
|
||||
DECLARE_IDTENTRY_VC(X86_TRAP_VC, exc_vmm_communication);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#define _ASM_X86_IRQ_STACK_H
|
||||
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/objtool.h>
|
||||
|
||||
#include <asm/processor.h>
|
||||
|
||||
@@ -99,7 +100,8 @@
|
||||
}
|
||||
|
||||
#define ASM_CALL_ARG0 \
|
||||
"call %P[__func] \n"
|
||||
"call %P[__func] \n" \
|
||||
ASM_REACHABLE
|
||||
|
||||
#define ASM_CALL_ARG1 \
|
||||
"movq %[arg1], %%rdi \n" \
|
||||
|
||||
@@ -141,13 +141,8 @@ static __always_inline void arch_local_irq_restore(unsigned long flags)
|
||||
#ifdef CONFIG_X86_64
|
||||
#ifdef CONFIG_XEN_PV
|
||||
#define SWAPGS ALTERNATIVE "swapgs", "", X86_FEATURE_XENPV
|
||||
#define INTERRUPT_RETURN \
|
||||
ANNOTATE_RETPOLINE_SAFE; \
|
||||
ALTERNATIVE_TERNARY("jmp *paravirt_iret(%rip);", \
|
||||
X86_FEATURE_XENPV, "jmp xen_iret;", "jmp native_iret;")
|
||||
#else
|
||||
#define SWAPGS swapgs
|
||||
#define INTERRUPT_RETURN jmp native_iret
|
||||
#endif
|
||||
#endif
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#define _ASM_X86_LINKAGE_H
|
||||
|
||||
#include <linux/stringify.h>
|
||||
#include <asm/ibt.h>
|
||||
|
||||
#undef notrace
|
||||
#define notrace __attribute__((no_instrument_function))
|
||||
@@ -34,5 +35,35 @@
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
/* SYM_FUNC_START -- use for global functions */
|
||||
#define SYM_FUNC_START(name) \
|
||||
SYM_START(name, SYM_L_GLOBAL, SYM_A_ALIGN) \
|
||||
ENDBR
|
||||
|
||||
/* SYM_FUNC_START_NOALIGN -- use for global functions, w/o alignment */
|
||||
#define SYM_FUNC_START_NOALIGN(name) \
|
||||
SYM_START(name, SYM_L_GLOBAL, SYM_A_NONE) \
|
||||
ENDBR
|
||||
|
||||
/* SYM_FUNC_START_LOCAL -- use for local functions */
|
||||
#define SYM_FUNC_START_LOCAL(name) \
|
||||
SYM_START(name, SYM_L_LOCAL, SYM_A_ALIGN) \
|
||||
ENDBR
|
||||
|
||||
/* SYM_FUNC_START_LOCAL_NOALIGN -- use for local functions, w/o alignment */
|
||||
#define SYM_FUNC_START_LOCAL_NOALIGN(name) \
|
||||
SYM_START(name, SYM_L_LOCAL, SYM_A_NONE) \
|
||||
ENDBR
|
||||
|
||||
/* SYM_FUNC_START_WEAK -- use for weak functions */
|
||||
#define SYM_FUNC_START_WEAK(name) \
|
||||
SYM_START(name, SYM_L_WEAK, SYM_A_ALIGN) \
|
||||
ENDBR
|
||||
|
||||
/* SYM_FUNC_START_WEAK_NOALIGN -- use for weak functions, w/o alignment */
|
||||
#define SYM_FUNC_START_WEAK_NOALIGN(name) \
|
||||
SYM_START(name, SYM_L_WEAK, SYM_A_NONE) \
|
||||
ENDBR
|
||||
|
||||
#endif /* _ASM_X86_LINKAGE_H */
|
||||
|
||||
|
||||
@@ -362,11 +362,29 @@
|
||||
#define MSR_ATOM_CORE_TURBO_RATIOS 0x0000066c
|
||||
#define MSR_ATOM_CORE_TURBO_VIDS 0x0000066d
|
||||
|
||||
|
||||
#define MSR_CORE_PERF_LIMIT_REASONS 0x00000690
|
||||
#define MSR_GFX_PERF_LIMIT_REASONS 0x000006B0
|
||||
#define MSR_RING_PERF_LIMIT_REASONS 0x000006B1
|
||||
|
||||
/* Control-flow Enforcement Technology MSRs */
|
||||
#define MSR_IA32_U_CET 0x000006a0 /* user mode cet */
|
||||
#define MSR_IA32_S_CET 0x000006a2 /* kernel mode cet */
|
||||
#define CET_SHSTK_EN BIT_ULL(0)
|
||||
#define CET_WRSS_EN BIT_ULL(1)
|
||||
#define CET_ENDBR_EN BIT_ULL(2)
|
||||
#define CET_LEG_IW_EN BIT_ULL(3)
|
||||
#define CET_NO_TRACK_EN BIT_ULL(4)
|
||||
#define CET_SUPPRESS_DISABLE BIT_ULL(5)
|
||||
#define CET_RESERVED (BIT_ULL(6) | BIT_ULL(7) | BIT_ULL(8) | BIT_ULL(9))
|
||||
#define CET_SUPPRESS BIT_ULL(10)
|
||||
#define CET_WAIT_ENDBR BIT_ULL(11)
|
||||
|
||||
#define MSR_IA32_PL0_SSP 0x000006a4 /* ring-0 shadow stack pointer */
|
||||
#define MSR_IA32_PL1_SSP 0x000006a5 /* ring-1 shadow stack pointer */
|
||||
#define MSR_IA32_PL2_SSP 0x000006a6 /* ring-2 shadow stack pointer */
|
||||
#define MSR_IA32_PL3_SSP 0x000006a7 /* ring-3 shadow stack pointer */
|
||||
#define MSR_IA32_INT_SSP_TAB 0x000006a8 /* exception shadow stack table */
|
||||
|
||||
/* Hardware P state interface */
|
||||
#define MSR_PPERF 0x0000064e
|
||||
#define MSR_PERF_LIMIT_REASONS 0x0000064f
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user