Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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
...

+1462 -334
-11
arch/powerpc/include/asm/livepatch.h
··· 17 17 ftrace_instruction_pointer_set(fregs, ip); 18 18 } 19 19 20 - #define klp_get_ftrace_location klp_get_ftrace_location 21 - static inline unsigned long klp_get_ftrace_location(unsigned long faddr) 22 - { 23 - /* 24 - * Live patch works on PPC32 and only with -mprofile-kernel on PPC64. In 25 - * both cases, the ftrace location is always within the first 16 bytes. 26 - */ 27 - return ftrace_location_range(faddr, faddr + 16); 28 - } 29 - #endif /* CONFIG_LIVEPATCH */ 30 - 31 20 #ifdef CONFIG_LIVEPATCH_64 32 21 static inline void klp_init_thread_info(struct task_struct *p) 33 22 {
+21 -13
arch/powerpc/kernel/kprobes.c
··· 105 105 return addr; 106 106 } 107 107 108 + static bool arch_kprobe_on_func_entry(unsigned long offset) 109 + { 110 + #ifdef PPC64_ELF_ABI_v2 111 + #ifdef CONFIG_KPROBES_ON_FTRACE 112 + return offset <= 16; 113 + #else 114 + return offset <= 8; 115 + #endif 116 + #else 117 + return !offset; 118 + #endif 119 + } 120 + 121 + /* XXX try and fold the magic of kprobe_lookup_name() in this */ 122 + kprobe_opcode_t *arch_adjust_kprobe_addr(unsigned long addr, unsigned long offset, 123 + bool *on_func_entry) 124 + { 125 + *on_func_entry = arch_kprobe_on_func_entry(offset); 126 + return (kprobe_opcode_t *)(addr + offset); 127 + } 128 + 108 129 void *alloc_insn_page(void) 109 130 { 110 131 void *page; ··· 237 216 { 238 217 __this_cpu_write(current_kprobe, p); 239 218 kcb->kprobe_saved_msr = regs->msr; 240 - } 241 - 242 - bool arch_kprobe_on_func_entry(unsigned long offset) 243 - { 244 - #ifdef PPC64_ELF_ABI_v2 245 - #ifdef CONFIG_KPROBES_ON_FTRACE 246 - return offset <= 16; 247 - #else 248 - return offset <= 8; 249 - #endif 250 - #else 251 - return !offset; 252 - #endif 253 219 } 254 220 255 221 void arch_prepare_kretprobe(struct kretprobe_instance *ri, struct pt_regs *regs)
+4
arch/um/kernel/um_arch.c
··· 424 424 os_check_bugs(); 425 425 } 426 426 427 + void apply_ibt_endbr(s32 *start, s32 *end) 428 + { 429 + } 430 + 427 431 void apply_retpolines(s32 *start, s32 *end) 428 432 { 429 433 }
+37 -6
arch/x86/Kconfig
··· 1842 1842 specific cases in protected and virtual-8086 modes. Emulated 1843 1843 results are dummy. 1844 1844 1845 + config CC_HAS_IBT 1846 + # GCC >= 9 and binutils >= 2.29 1847 + # Retpoline check to work around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93654 1848 + # Clang/LLVM >= 14 1849 + # https://github.com/llvm/llvm-project/commit/e0b89df2e0f0130881bf6c39bf31d7f6aac00e0f 1850 + # https://github.com/llvm/llvm-project/commit/dfcf69770bc522b9e411c66454934a37c1f35332 1851 + def_bool ((CC_IS_GCC && $(cc-option, -fcf-protection=branch -mindirect-branch-register)) || \ 1852 + (CC_IS_CLANG && CLANG_VERSION >= 140000)) && \ 1853 + $(as-instr,endbr64) 1854 + 1855 + config X86_KERNEL_IBT 1856 + prompt "Indirect Branch Tracking" 1857 + bool 1858 + depends on X86_64 && CC_HAS_IBT && STACK_VALIDATION 1859 + # https://github.com/llvm/llvm-project/commit/9d7001eba9c4cb311e03cd8cdc231f9e579f2d0f 1860 + depends on !LD_IS_LLD || LLD_VERSION >= 140000 1861 + help 1862 + Build the kernel with support for Indirect Branch Tracking, a 1863 + hardware support course-grain forward-edge Control Flow Integrity 1864 + protection. It enforces that all indirect calls must land on 1865 + an ENDBR instruction, as such, the compiler will instrument the 1866 + code with them to make this happen. 1867 + 1868 + In addition to building the kernel with IBT, seal all functions that 1869 + are not indirect call targets, avoiding them ever becomming one. 1870 + 1871 + This requires LTO like objtool runs and will slow down the build. It 1872 + does significantly reduce the number of ENDBR instructions in the 1873 + kernel image. 1874 + 1845 1875 config X86_INTEL_MEMORY_PROTECTION_KEYS 1846 1876 prompt "Memory Protection Keys" 1847 1877 def_bool y ··· 2845 2815 help 2846 2816 Support old a.out binaries in the 32bit emulation. 2847 2817 2848 - config X86_X32 2818 + config X86_X32_ABI 2849 2819 bool "x32 ABI for 64-bit mode" 2850 2820 depends on X86_64 2821 + # llvm-objcopy does not convert x86_64 .note.gnu.property or 2822 + # compressed debug sections to x86_x32 properly: 2823 + # https://github.com/ClangBuiltLinux/linux/issues/514 2824 + # https://github.com/ClangBuiltLinux/linux/issues/1141 2825 + depends on $(success,$(OBJCOPY) --version | head -n1 | grep -qv llvm) 2851 2826 help 2852 2827 Include code to run binaries for the x32 native 32-bit ABI 2853 2828 for 64-bit processors. An x32 process gets access to the 2854 2829 full 64-bit register file and wide data path while leaving 2855 2830 pointers at 32 bits for smaller memory footprint. 2856 - 2857 - You will need a recent binutils (2.22 or later) with 2858 - elf32_x86_64 support enabled to compile a kernel with this 2859 - option set. 2860 2831 2861 2832 config COMPAT_32 2862 2833 def_bool y ··· 2867 2836 2868 2837 config COMPAT 2869 2838 def_bool y 2870 - depends on IA32_EMULATION || X86_X32 2839 + depends on IA32_EMULATION || X86_X32_ABI 2871 2840 2872 2841 if COMPAT 2873 2842 config COMPAT_FOR_U64_ALIGNMENT
+14 -18
arch/x86/Makefile
··· 36 36 37 37 # How to compile the 16-bit code. Note we always compile for -march=i386; 38 38 # that way we can complain to the user if the CPU is insufficient. 39 - REALMODE_CFLAGS := -m16 -g -Os -DDISABLE_BRANCH_PROFILING \ 39 + REALMODE_CFLAGS := -m16 -g -Os -DDISABLE_BRANCH_PROFILING -D__DISABLE_EXPORTS \ 40 40 -Wall -Wstrict-prototypes -march=i386 -mregparm=3 \ 41 41 -fno-strict-aliasing -fomit-frame-pointer -fno-pic \ 42 42 -mno-mmx -mno-sse $(call cc-option,-fcf-protection=none) ··· 62 62 # 63 63 KBUILD_CFLAGS += -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx 64 64 65 - # Intel CET isn't enabled in the kernel 65 + ifeq ($(CONFIG_X86_KERNEL_IBT),y) 66 + # 67 + # Kernel IBT has S_CET.NOTRACK_EN=0, as such the compilers must not generate 68 + # NOTRACK prefixes. Current generation compilers unconditionally employ NOTRACK 69 + # for jump-tables, as such, disable jump-tables for now. 70 + # 71 + # (jump-tables are implicitly disabled by RETPOLINE) 72 + # 73 + # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104816 74 + # 75 + KBUILD_CFLAGS += $(call cc-option,-fcf-protection=branch -fno-jump-tables) 76 + else 66 77 KBUILD_CFLAGS += $(call cc-option,-fcf-protection=none) 78 + endif 67 79 68 80 ifeq ($(CONFIG_X86_32),y) 69 81 BITS := 32 ··· 151 139 KBUILD_CFLAGS += -mno-red-zone 152 140 KBUILD_CFLAGS += -mcmodel=kernel 153 141 endif 154 - 155 - ifdef CONFIG_X86_X32 156 - x32_ld_ok := $(call try-run,\ 157 - /bin/echo -e '1: .quad 1b' | \ 158 - $(CC) $(KBUILD_AFLAGS) -c -x assembler -o "$$TMP" - && \ 159 - $(OBJCOPY) -O elf32-x86-64 "$$TMP" "$$TMP.o" && \ 160 - $(LD) -m elf32_x86_64 "$$TMP.o" -o "$$TMP",y,n) 161 - ifeq ($(x32_ld_ok),y) 162 - CONFIG_X86_X32_ABI := y 163 - KBUILD_AFLAGS += -DCONFIG_X86_X32_ABI 164 - KBUILD_CFLAGS += -DCONFIG_X86_X32_ABI 165 - else 166 - $(warning CONFIG_X86_X32 enabled but no binutils support) 167 - endif 168 - endif 169 - export CONFIG_X86_X32_ABI 170 142 171 143 # 172 144 # If the function graph tracer is used with mcount instead of fentry,
+3
arch/x86/crypto/crc32c-pcl-intel-asm_64.S
··· 195 195 .altmacro 196 196 LABEL crc_ %i 197 197 .noaltmacro 198 + ENDBR 198 199 crc32q -i*8(block_0), crc_init 199 200 crc32q -i*8(block_1), crc1 200 201 crc32q -i*8(block_2), crc2 ··· 205 204 .altmacro 206 205 LABEL crc_ %i 207 206 .noaltmacro 207 + ENDBR 208 208 crc32q -i*8(block_0), crc_init 209 209 crc32q -i*8(block_1), crc1 210 210 # SKIP crc32 -i*8(block_2), crc2 ; Don't do this one yet ··· 239 237 ################################################################ 240 238 241 239 LABEL crc_ 0 240 + ENDBR 242 241 mov tmp, len 243 242 cmp $128*24, tmp 244 243 jae full_block
+27 -4
arch/x86/entry/entry_64.S
··· 86 86 87 87 SYM_CODE_START(entry_SYSCALL_64) 88 88 UNWIND_HINT_EMPTY 89 + ENDBR 89 90 90 91 swapgs 91 92 /* tss.sp2 is scratch space. */ ··· 95 94 movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp 96 95 97 96 SYM_INNER_LABEL(entry_SYSCALL_64_safe_stack, SYM_L_GLOBAL) 97 + ANNOTATE_NOENDBR 98 98 99 99 /* Construct struct pt_regs on stack */ 100 100 pushq $__USER_DS /* pt_regs->ss */ ··· 278 276 .pushsection .text, "ax" 279 277 SYM_CODE_START(ret_from_fork) 280 278 UNWIND_HINT_EMPTY 279 + ANNOTATE_NOENDBR // copy_thread 281 280 movq %rax, %rdi 282 281 call schedule_tail /* rdi: 'prev' task parameter */ 283 282 ··· 353 350 .macro idtentry vector asmsym cfunc has_error_code:req 354 351 SYM_CODE_START(\asmsym) 355 352 UNWIND_HINT_IRET_REGS offset=\has_error_code*8 353 + ENDBR 356 354 ASM_CLAC 357 355 358 356 .if \has_error_code == 0 ··· 421 417 .macro idtentry_mce_db vector asmsym cfunc 422 418 SYM_CODE_START(\asmsym) 423 419 UNWIND_HINT_IRET_REGS 420 + ENDBR 424 421 ASM_CLAC 425 422 426 423 pushq $-1 /* ORIG_RAX: no syscall to restart */ ··· 477 472 .macro idtentry_vc vector asmsym cfunc 478 473 SYM_CODE_START(\asmsym) 479 474 UNWIND_HINT_IRET_REGS 475 + ENDBR 480 476 ASM_CLAC 481 477 482 478 /* ··· 539 533 .macro idtentry_df vector asmsym cfunc 540 534 SYM_CODE_START(\asmsym) 541 535 UNWIND_HINT_IRET_REGS offset=8 536 + ENDBR 542 537 ASM_CLAC 543 538 544 539 /* paranoid_entry returns GS information for paranoid_exit in EBX. */ ··· 550 543 movq ORIG_RAX(%rsp), %rsi /* get error code into 2nd argument*/ 551 544 movq $-1, ORIG_RAX(%rsp) /* no syscall to restart */ 552 545 call \cfunc 546 + 547 + /* For some configurations \cfunc ends up being a noreturn. */ 548 + REACHABLE 553 549 554 550 jmp paranoid_exit 555 551 ··· 574 564 .align 16 575 565 .globl __irqentry_text_end 576 566 __irqentry_text_end: 567 + ANNOTATE_NOENDBR 577 568 578 569 SYM_CODE_START_LOCAL(common_interrupt_return) 579 570 SYM_INNER_LABEL(swapgs_restore_regs_and_return_to_usermode, SYM_L_GLOBAL) ··· 619 608 620 609 /* Restore RDI. */ 621 610 popq %rdi 622 - SWAPGS 623 - INTERRUPT_RETURN 611 + swapgs 612 + jmp .Lnative_iret 624 613 625 614 626 615 SYM_INNER_LABEL(restore_regs_and_return_to_kernel, SYM_L_GLOBAL) ··· 637 626 * ARCH_HAS_MEMBARRIER_SYNC_CORE rely on IRET core serialization 638 627 * when returning from IPI handler. 639 628 */ 640 - INTERRUPT_RETURN 629 + #ifdef CONFIG_XEN_PV 630 + SYM_INNER_LABEL(early_xen_iret_patch, SYM_L_GLOBAL) 631 + ANNOTATE_NOENDBR 632 + .byte 0xe9 633 + .long .Lnative_iret - (. + 4) 634 + #endif 641 635 642 - SYM_INNER_LABEL_ALIGN(native_iret, SYM_L_GLOBAL) 636 + .Lnative_iret: 643 637 UNWIND_HINT_IRET_REGS 644 638 /* 645 639 * Are we returning to a stack segment from the LDT? Note: in ··· 656 640 #endif 657 641 658 642 SYM_INNER_LABEL(native_irq_return_iret, SYM_L_GLOBAL) 643 + ANNOTATE_NOENDBR // exc_double_fault 659 644 /* 660 645 * This may fault. Non-paranoid faults on return to userspace are 661 646 * handled by fixup_bad_iret. These include #SS, #GP, and #NP. ··· 751 734 FRAME_BEGIN 752 735 swapgs 753 736 .Lgs_change: 737 + ANNOTATE_NOENDBR // error_entry 754 738 movl %edi, %gs 755 739 2: ALTERNATIVE "", "mfence", X86_BUG_SWAPGS_FENCE 756 740 swapgs ··· 822 804 */ 823 805 SYM_CODE_START(xen_failsafe_callback) 824 806 UNWIND_HINT_EMPTY 807 + ENDBR 825 808 movl %ds, %ecx 826 809 cmpw %cx, 0x10(%rsp) 827 810 jne 1f ··· 1082 1063 */ 1083 1064 SYM_CODE_START(asm_exc_nmi) 1084 1065 UNWIND_HINT_IRET_REGS 1066 + ENDBR 1085 1067 1086 1068 /* 1087 1069 * We allow breakpoints in NMIs. If a breakpoint occurs, then ··· 1330 1310 #endif 1331 1311 1332 1312 repeat_nmi: 1313 + ANNOTATE_NOENDBR // this code 1333 1314 /* 1334 1315 * If there was a nested NMI, the first NMI's iret will return 1335 1316 * here. But NMIs are still enabled and we can take another ··· 1359 1338 .endr 1360 1339 subq $(5*8), %rsp 1361 1340 end_repeat_nmi: 1341 + ANNOTATE_NOENDBR // this code 1362 1342 1363 1343 /* 1364 1344 * Everything below this point can be preempted by a nested NMI. ··· 1443 1421 */ 1444 1422 SYM_CODE_START(ignore_sysret) 1445 1423 UNWIND_HINT_EMPTY 1424 + ENDBR 1446 1425 mov $-ENOSYS, %eax 1447 1426 sysretl 1448 1427 SYM_CODE_END(ignore_sysret)
+5
arch/x86/entry/entry_64_compat.S
··· 48 48 */ 49 49 SYM_CODE_START(entry_SYSENTER_compat) 50 50 UNWIND_HINT_EMPTY 51 + ENDBR 51 52 /* Interrupts are off on entry. */ 52 53 SWAPGS 53 54 ··· 148 147 popfq 149 148 jmp .Lsysenter_flags_fixed 150 149 SYM_INNER_LABEL(__end_entry_SYSENTER_compat, SYM_L_GLOBAL) 150 + ANNOTATE_NOENDBR // is_sysenter_singlestep 151 151 SYM_CODE_END(entry_SYSENTER_compat) 152 152 153 153 /* ··· 200 198 */ 201 199 SYM_CODE_START(entry_SYSCALL_compat) 202 200 UNWIND_HINT_EMPTY 201 + ENDBR 203 202 /* Interrupts are off on entry. */ 204 203 swapgs 205 204 ··· 214 211 movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp 215 212 216 213 SYM_INNER_LABEL(entry_SYSCALL_compat_safe_stack, SYM_L_GLOBAL) 214 + ANNOTATE_NOENDBR 217 215 218 216 /* Construct struct pt_regs on stack */ 219 217 pushq $__USER32_DS /* pt_regs->ss */ ··· 344 340 */ 345 341 SYM_CODE_START(entry_INT80_compat) 346 342 UNWIND_HINT_EMPTY 343 + ENDBR 347 344 /* 348 345 * Interrupts are off on entry. 349 346 */
+1 -1
arch/x86/entry/syscalls/Makefile
··· 67 67 syshdr-y += syscalls_32.h 68 68 syshdr-$(CONFIG_X86_64) += unistd_32_ia32.h unistd_64_x32.h 69 69 syshdr-$(CONFIG_X86_64) += syscalls_64.h 70 - syshdr-$(CONFIG_X86_X32) += syscalls_x32.h 70 + syshdr-$(CONFIG_X86_X32_ABI) += syscalls_x32.h 71 71 syshdr-$(CONFIG_XEN) += xen-hypercalls.h 72 72 73 73 uapisyshdr-y := $(addprefix $(uapi)/, $(uapisyshdr-y))
+1
arch/x86/include/asm/alternative.h
··· 76 76 extern void alternative_instructions(void); 77 77 extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end); 78 78 extern void apply_retpolines(s32 *start, s32 *end); 79 + extern void apply_ibt_endbr(s32 *start, s32 *end); 79 80 80 81 struct module; 81 82
+1
arch/x86/include/asm/bug.h
··· 4 4 5 5 #include <linux/stringify.h> 6 6 #include <linux/instrumentation.h> 7 + #include <linux/objtool.h> 7 8 8 9 /* 9 10 * Despite that some emulators terminate on UD2, we use it for WARN().
+4
arch/x86/include/asm/cpu.h
··· 7 7 #include <linux/topology.h> 8 8 #include <linux/nodemask.h> 9 9 #include <linux/percpu.h> 10 + #include <asm/ibt.h> 10 11 11 12 #ifdef CONFIG_SMP 12 13 ··· 73 72 #else 74 73 static inline void init_ia32_feat_ctl(struct cpuinfo_x86 *c) {} 75 74 #endif 75 + 76 + extern __noendbr void cet_disable(void); 77 + 76 78 #endif /* _ASM_X86_CPU_H */
+1
arch/x86/include/asm/cpufeatures.h
··· 388 388 #define X86_FEATURE_TSXLDTRK (18*32+16) /* TSX Suspend Load Address Tracking */ 389 389 #define X86_FEATURE_PCONFIG (18*32+18) /* Intel PCONFIG */ 390 390 #define X86_FEATURE_ARCH_LBR (18*32+19) /* Intel ARCH LBR */ 391 + #define X86_FEATURE_IBT (18*32+20) /* Indirect Branch Tracking */ 391 392 #define X86_FEATURE_AMX_BF16 (18*32+22) /* AMX bf16 Support */ 392 393 #define X86_FEATURE_AVX512_FP16 (18*32+23) /* AVX512 FP16 */ 393 394 #define X86_FEATURE_AMX_TILE (18*32+24) /* AMX tile Support */
+7 -2
arch/x86/include/asm/efi.h
··· 7 7 #include <asm/tlb.h> 8 8 #include <asm/nospec-branch.h> 9 9 #include <asm/mmu_context.h> 10 + #include <asm/ibt.h> 10 11 #include <linux/build_bug.h> 11 12 #include <linux/kernel.h> 12 13 #include <linux/pgtable.h> ··· 121 120 efi_enter_mm(); \ 122 121 }) 123 122 124 - #define arch_efi_call_virt(p, f, args...) \ 125 - efi_call((void *)p->f, args) \ 123 + #define arch_efi_call_virt(p, f, args...) ({ \ 124 + u64 ret, ibt = ibt_save(); \ 125 + ret = efi_call((void *)p->f, args); \ 126 + ibt_restore(ibt); \ 127 + ret; \ 128 + }) 126 129 127 130 #define arch_efi_call_virt_teardown() \ 128 131 ({ \
+105
arch/x86/include/asm/ibt.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef _ASM_X86_IBT_H 3 + #define _ASM_X86_IBT_H 4 + 5 + #include <linux/types.h> 6 + 7 + /* 8 + * The rules for enabling IBT are: 9 + * 10 + * - CC_HAS_IBT: the toolchain supports it 11 + * - X86_KERNEL_IBT: it is selected in Kconfig 12 + * - !__DISABLE_EXPORTS: this is regular kernel code 13 + * 14 + * Esp. that latter one is a bit non-obvious, but some code like compressed, 15 + * purgatory, realmode etc.. is built with custom CFLAGS that do not include 16 + * -fcf-protection=branch and things will go *bang*. 17 + * 18 + * When all the above are satisfied, HAS_KERNEL_IBT will be 1, otherwise 0. 19 + */ 20 + #if defined(CONFIG_X86_KERNEL_IBT) && !defined(__DISABLE_EXPORTS) 21 + 22 + #define HAS_KERNEL_IBT 1 23 + 24 + #ifndef __ASSEMBLY__ 25 + 26 + #ifdef CONFIG_X86_64 27 + #define ASM_ENDBR "endbr64\n\t" 28 + #else 29 + #define ASM_ENDBR "endbr32\n\t" 30 + #endif 31 + 32 + #define __noendbr __attribute__((nocf_check)) 33 + 34 + static inline __attribute_const__ u32 gen_endbr(void) 35 + { 36 + u32 endbr; 37 + 38 + /* 39 + * Generate ENDBR64 in a way that is sure to not result in 40 + * an ENDBR64 instruction as immediate. 41 + */ 42 + asm ( "mov $~0xfa1e0ff3, %[endbr]\n\t" 43 + "not %[endbr]\n\t" 44 + : [endbr] "=&r" (endbr) ); 45 + 46 + return endbr; 47 + } 48 + 49 + static inline __attribute_const__ u32 gen_endbr_poison(void) 50 + { 51 + /* 52 + * 4 byte NOP that isn't NOP4 (in fact it is OSP NOP3), such that it 53 + * will be unique to (former) ENDBR sites. 54 + */ 55 + return 0x001f0f66; /* osp nopl (%rax) */ 56 + } 57 + 58 + static inline bool is_endbr(u32 val) 59 + { 60 + if (val == gen_endbr_poison()) 61 + return true; 62 + 63 + val &= ~0x01000000U; /* ENDBR32 -> ENDBR64 */ 64 + return val == gen_endbr(); 65 + } 66 + 67 + extern __noendbr u64 ibt_save(void); 68 + extern __noendbr void ibt_restore(u64 save); 69 + 70 + #else /* __ASSEMBLY__ */ 71 + 72 + #ifdef CONFIG_X86_64 73 + #define ENDBR endbr64 74 + #else 75 + #define ENDBR endbr32 76 + #endif 77 + 78 + #endif /* __ASSEMBLY__ */ 79 + 80 + #else /* !IBT */ 81 + 82 + #define HAS_KERNEL_IBT 0 83 + 84 + #ifndef __ASSEMBLY__ 85 + 86 + #define ASM_ENDBR 87 + 88 + #define __noendbr 89 + 90 + static inline bool is_endbr(u32 val) { return false; } 91 + 92 + static inline u64 ibt_save(void) { return 0; } 93 + static inline void ibt_restore(u64 save) { } 94 + 95 + #else /* __ASSEMBLY__ */ 96 + 97 + #define ENDBR 98 + 99 + #endif /* __ASSEMBLY__ */ 100 + 101 + #endif /* CONFIG_X86_KERNEL_IBT */ 102 + 103 + #define ENDBR_INSN_SIZE (4*HAS_KERNEL_IBT) 104 + 105 + #endif /* _ASM_X86_IBT_H */
+16 -9
arch/x86/include/asm/idtentry.h
··· 5 5 /* Interrupts/Exceptions */ 6 6 #include <asm/trapnr.h> 7 7 8 + #define IDT_ALIGN (8 * (1 + HAS_KERNEL_IBT)) 9 + 8 10 #ifndef __ASSEMBLY__ 9 11 #include <linux/entry-common.h> 10 12 #include <linux/hardirq.h> ··· 482 480 483 481 /* 484 482 * ASM code to emit the common vector entry stubs where each stub is 485 - * packed into 8 bytes. 483 + * packed into IDT_ALIGN bytes. 486 484 * 487 485 * Note, that the 'pushq imm8' is emitted via '.byte 0x6a, vector' because 488 486 * GCC treats the local vector variable as unsigned int and would expand ··· 494 492 * point is to mask off the bits above bit 7 because the push is sign 495 493 * extending. 496 494 */ 497 - .align 8 495 + .align IDT_ALIGN 498 496 SYM_CODE_START(irq_entries_start) 499 497 vector=FIRST_EXTERNAL_VECTOR 500 498 .rept NR_EXTERNAL_VECTORS 501 499 UNWIND_HINT_IRET_REGS 502 500 0 : 501 + ENDBR 503 502 .byte 0x6a, vector 504 503 jmp asm_common_interrupt 505 - nop 506 - /* Ensure that the above is 8 bytes max */ 507 - . = 0b + 8 504 + /* Ensure that the above is IDT_ALIGN bytes max */ 505 + .fill 0b + IDT_ALIGN - ., 1, 0xcc 508 506 vector = vector+1 509 507 .endr 510 508 SYM_CODE_END(irq_entries_start) 511 509 512 510 #ifdef CONFIG_X86_LOCAL_APIC 513 - .align 8 511 + .align IDT_ALIGN 514 512 SYM_CODE_START(spurious_entries_start) 515 513 vector=FIRST_SYSTEM_VECTOR 516 514 .rept NR_SYSTEM_VECTORS 517 515 UNWIND_HINT_IRET_REGS 518 516 0 : 517 + ENDBR 519 518 .byte 0x6a, vector 520 519 jmp asm_spurious_interrupt 521 - nop 522 - /* Ensure that the above is 8 bytes max */ 523 - . = 0b + 8 520 + /* Ensure that the above is IDT_ALIGN bytes max */ 521 + .fill 0b + IDT_ALIGN - ., 1, 0xcc 524 522 vector = vector+1 525 523 .endr 526 524 SYM_CODE_END(spurious_entries_start) ··· 615 613 DECLARE_IDTENTRY_DF(X86_TRAP_DF, exc_double_fault); 616 614 #ifdef CONFIG_XEN_PV 617 615 DECLARE_IDTENTRY_RAW_ERRORCODE(X86_TRAP_DF, xenpv_exc_double_fault); 616 + #endif 617 + 618 + /* #CP */ 619 + #ifdef CONFIG_X86_KERNEL_IBT 620 + DECLARE_IDTENTRY_ERRORCODE(X86_TRAP_CP, exc_control_protection); 618 621 #endif 619 622 620 623 /* #VC */
+3 -1
arch/x86/include/asm/irq_stack.h
··· 3 3 #define _ASM_X86_IRQ_STACK_H 4 4 5 5 #include <linux/ptrace.h> 6 + #include <linux/objtool.h> 6 7 7 8 #include <asm/processor.h> 8 9 ··· 100 99 } 101 100 102 101 #define ASM_CALL_ARG0 \ 103 - "call %P[__func] \n" 102 + "call %P[__func] \n" \ 103 + ASM_REACHABLE 104 104 105 105 #define ASM_CALL_ARG1 \ 106 106 "movq %[arg1], %%rdi \n" \
-5
arch/x86/include/asm/irqflags.h
··· 141 141 #ifdef CONFIG_X86_64 142 142 #ifdef CONFIG_XEN_PV 143 143 #define SWAPGS ALTERNATIVE "swapgs", "", X86_FEATURE_XENPV 144 - #define INTERRUPT_RETURN \ 145 - ANNOTATE_RETPOLINE_SAFE; \ 146 - ALTERNATIVE_TERNARY("jmp *paravirt_iret(%rip);", \ 147 - X86_FEATURE_XENPV, "jmp xen_iret;", "jmp native_iret;") 148 144 #else 149 145 #define SWAPGS swapgs 150 - #define INTERRUPT_RETURN jmp native_iret 151 146 #endif 152 147 #endif 153 148 #endif /* !__ASSEMBLY__ */
+31
arch/x86/include/asm/linkage.h
··· 3 3 #define _ASM_X86_LINKAGE_H 4 4 5 5 #include <linux/stringify.h> 6 + #include <asm/ibt.h> 6 7 7 8 #undef notrace 8 9 #define notrace __attribute__((no_instrument_function)) ··· 34 33 #endif 35 34 36 35 #endif /* __ASSEMBLY__ */ 36 + 37 + /* SYM_FUNC_START -- use for global functions */ 38 + #define SYM_FUNC_START(name) \ 39 + SYM_START(name, SYM_L_GLOBAL, SYM_A_ALIGN) \ 40 + ENDBR 41 + 42 + /* SYM_FUNC_START_NOALIGN -- use for global functions, w/o alignment */ 43 + #define SYM_FUNC_START_NOALIGN(name) \ 44 + SYM_START(name, SYM_L_GLOBAL, SYM_A_NONE) \ 45 + ENDBR 46 + 47 + /* SYM_FUNC_START_LOCAL -- use for local functions */ 48 + #define SYM_FUNC_START_LOCAL(name) \ 49 + SYM_START(name, SYM_L_LOCAL, SYM_A_ALIGN) \ 50 + ENDBR 51 + 52 + /* SYM_FUNC_START_LOCAL_NOALIGN -- use for local functions, w/o alignment */ 53 + #define SYM_FUNC_START_LOCAL_NOALIGN(name) \ 54 + SYM_START(name, SYM_L_LOCAL, SYM_A_NONE) \ 55 + ENDBR 56 + 57 + /* SYM_FUNC_START_WEAK -- use for weak functions */ 58 + #define SYM_FUNC_START_WEAK(name) \ 59 + SYM_START(name, SYM_L_WEAK, SYM_A_ALIGN) \ 60 + ENDBR 61 + 62 + /* SYM_FUNC_START_WEAK_NOALIGN -- use for weak functions, w/o alignment */ 63 + #define SYM_FUNC_START_WEAK_NOALIGN(name) \ 64 + SYM_START(name, SYM_L_WEAK, SYM_A_NONE) \ 65 + ENDBR 37 66 38 67 #endif /* _ASM_X86_LINKAGE_H */ 39 68
+19 -1
arch/x86/include/asm/msr-index.h
··· 362 362 #define MSR_ATOM_CORE_TURBO_RATIOS 0x0000066c 363 363 #define MSR_ATOM_CORE_TURBO_VIDS 0x0000066d 364 364 365 - 366 365 #define MSR_CORE_PERF_LIMIT_REASONS 0x00000690 367 366 #define MSR_GFX_PERF_LIMIT_REASONS 0x000006B0 368 367 #define MSR_RING_PERF_LIMIT_REASONS 0x000006B1 368 + 369 + /* Control-flow Enforcement Technology MSRs */ 370 + #define MSR_IA32_U_CET 0x000006a0 /* user mode cet */ 371 + #define MSR_IA32_S_CET 0x000006a2 /* kernel mode cet */ 372 + #define CET_SHSTK_EN BIT_ULL(0) 373 + #define CET_WRSS_EN BIT_ULL(1) 374 + #define CET_ENDBR_EN BIT_ULL(2) 375 + #define CET_LEG_IW_EN BIT_ULL(3) 376 + #define CET_NO_TRACK_EN BIT_ULL(4) 377 + #define CET_SUPPRESS_DISABLE BIT_ULL(5) 378 + #define CET_RESERVED (BIT_ULL(6) | BIT_ULL(7) | BIT_ULL(8) | BIT_ULL(9)) 379 + #define CET_SUPPRESS BIT_ULL(10) 380 + #define CET_WAIT_ENDBR BIT_ULL(11) 381 + 382 + #define MSR_IA32_PL0_SSP 0x000006a4 /* ring-0 shadow stack pointer */ 383 + #define MSR_IA32_PL1_SSP 0x000006a5 /* ring-1 shadow stack pointer */ 384 + #define MSR_IA32_PL2_SSP 0x000006a6 /* ring-2 shadow stack pointer */ 385 + #define MSR_IA32_PL3_SSP 0x000006a7 /* ring-3 shadow stack pointer */ 386 + #define MSR_IA32_INT_SSP_TAB 0x000006a8 /* exception shadow stack table */ 369 387 370 388 /* Hardware P state interface */ 371 389 #define MSR_PPERF 0x0000064e
+1
arch/x86/include/asm/paravirt.h
··· 666 666 ".globl " PV_THUNK_NAME(func) ";" \ 667 667 ".type " PV_THUNK_NAME(func) ", @function;" \ 668 668 PV_THUNK_NAME(func) ":" \ 669 + ASM_ENDBR \ 669 670 FRAME_BEGIN \ 670 671 PV_SAVE_ALL_CALLER_REGS \ 671 672 "call " #func ";" \
-1
arch/x86/include/asm/paravirt_types.h
··· 272 272 273 273 extern struct pv_info pv_info; 274 274 extern struct paravirt_patch_template pv_ops; 275 - extern void (*paravirt_iret)(void); 276 275 277 276 #define PARAVIRT_PATCH(x) \ 278 277 (offsetof(struct paravirt_patch_template, x) / sizeof(void *))
+1 -1
arch/x86/include/asm/processor.h
··· 837 837 #define xen_set_default_idle 0 838 838 #endif 839 839 840 - void stop_this_cpu(void *dummy); 840 + void __noreturn stop_this_cpu(void *dummy); 841 841 void microcode_check(void); 842 842 843 843 enum l1tf_mitigations {
+3
arch/x86/include/asm/qspinlock_paravirt.h
··· 2 2 #ifndef __ASM_QSPINLOCK_PARAVIRT_H 3 3 #define __ASM_QSPINLOCK_PARAVIRT_H 4 4 5 + #include <asm/ibt.h> 6 + 5 7 /* 6 8 * For x86-64, PV_CALLEE_SAVE_REGS_THUNK() saves and restores 8 64-bit 7 9 * registers. For i386, however, only 1 32-bit register needs to be saved ··· 41 39 ".type " PV_UNLOCK ", @function;" 42 40 ".align 4,0x90;" 43 41 PV_UNLOCK ": " 42 + ASM_ENDBR 44 43 FRAME_BEGIN 45 44 "push %rdx;" 46 45 "mov $0x1,%eax;"
+3 -2
arch/x86/include/asm/segment.h
··· 4 4 5 5 #include <linux/const.h> 6 6 #include <asm/alternative.h> 7 + #include <asm/ibt.h> 7 8 8 9 /* 9 10 * Constructor for a conventional segment GDT (or LDT) entry. ··· 276 275 * vector has no error code (two bytes), a 'push $vector_number' (two 277 276 * bytes), and a jump to the common entry code (up to five bytes). 278 277 */ 279 - #define EARLY_IDT_HANDLER_SIZE 9 278 + #define EARLY_IDT_HANDLER_SIZE (9 + ENDBR_INSN_SIZE) 280 279 281 280 /* 282 281 * xen_early_idt_handler_array is for Xen pv guests: for each entry in ··· 284 283 * pop %rcx; pop %r11; jmp early_idt_handler_array[i]; summing up to 285 284 * max 8 bytes. 286 285 */ 287 - #define XEN_EARLY_IDT_HANDLER_SIZE 8 286 + #define XEN_EARLY_IDT_HANDLER_SIZE (8 + ENDBR_INSN_SIZE) 288 287 289 288 #ifndef __ASSEMBLY__ 290 289
+2 -1
arch/x86/include/asm/setup.h
··· 8 8 9 9 #include <linux/linkage.h> 10 10 #include <asm/page_types.h> 11 + #include <asm/ibt.h> 11 12 12 13 #ifdef __i386__ 13 14 ··· 120 119 * executable.) 121 120 */ 122 121 #define RESERVE_BRK(name,sz) \ 123 - static void __section(".discard.text") __used notrace \ 122 + static void __section(".discard.text") __noendbr __used notrace \ 124 123 __brk_reservation_fn_##name##__(void) { \ 125 124 asm volatile ( \ 126 125 ".pushsection .brk_reservation,\"aw\",@nobits;" \
+3 -3
arch/x86/include/asm/syscall_wrapper.h
··· 159 159 #endif /* CONFIG_IA32_EMULATION */ 160 160 161 161 162 - #ifdef CONFIG_X86_X32 162 + #ifdef CONFIG_X86_X32_ABI 163 163 /* 164 164 * For the x32 ABI, we need to create a stub for compat_sys_*() which is aware 165 165 * of the x86-64-style parameter ordering of x32 syscalls. The syscalls common ··· 177 177 178 178 #define __X32_COMPAT_SYS_NI(name) \ 179 179 __SYS_NI(x64, compat_sys_##name) 180 - #else /* CONFIG_X86_X32 */ 180 + #else /* CONFIG_X86_X32_ABI */ 181 181 #define __X32_COMPAT_SYS_STUB0(name) 182 182 #define __X32_COMPAT_SYS_STUBx(x, name, ...) 183 183 #define __X32_COMPAT_COND_SYSCALL(name) 184 184 #define __X32_COMPAT_SYS_NI(name) 185 - #endif /* CONFIG_X86_X32 */ 185 + #endif /* CONFIG_X86_X32_ABI */ 186 186 187 187 188 188 #ifdef CONFIG_COMPAT
+31 -15
arch/x86/include/asm/text-patching.h
··· 97 97 }; 98 98 99 99 static __always_inline 100 + void __text_gen_insn(void *buf, u8 opcode, const void *addr, const void *dest, int size) 101 + { 102 + union text_poke_insn *insn = buf; 103 + 104 + BUG_ON(size < text_opcode_size(opcode)); 105 + 106 + /* 107 + * Hide the addresses to avoid the compiler folding in constants when 108 + * referencing code, these can mess up annotations like 109 + * ANNOTATE_NOENDBR. 110 + */ 111 + OPTIMIZER_HIDE_VAR(insn); 112 + OPTIMIZER_HIDE_VAR(addr); 113 + OPTIMIZER_HIDE_VAR(dest); 114 + 115 + insn->opcode = opcode; 116 + 117 + if (size > 1) { 118 + insn->disp = (long)dest - (long)(addr + size); 119 + if (size == 2) { 120 + /* 121 + * Ensure that for JMP8 the displacement 122 + * actually fits the signed byte. 123 + */ 124 + BUG_ON((insn->disp >> 31) != (insn->disp >> 7)); 125 + } 126 + } 127 + } 128 + 129 + static __always_inline 100 130 void *text_gen_insn(u8 opcode, const void *addr, const void *dest) 101 131 { 102 132 static union text_poke_insn insn; /* per instance */ 103 - int size = text_opcode_size(opcode); 104 - 105 - insn.opcode = opcode; 106 - 107 - if (size > 1) { 108 - insn.disp = (long)dest - (long)(addr + size); 109 - if (size == 2) { 110 - /* 111 - * Ensure that for JMP9 the displacement 112 - * actually fits the signed byte. 113 - */ 114 - BUG_ON((insn.disp >> 31) != (insn.disp >> 7)); 115 - } 116 - } 117 - 133 + __text_gen_insn(&insn, opcode, addr, dest, text_opcode_size(opcode)); 118 134 return &insn.text; 119 135 } 120 136
+2
arch/x86/include/asm/traps.h
··· 18 18 asmlinkage __visible noinstr struct pt_regs *vc_switch_off_ist(struct pt_regs *eregs); 19 19 #endif 20 20 21 + extern bool ibt_selftest(void); 22 + 21 23 #ifdef CONFIG_X86_F00F_BUG 22 24 /* For handling the FOOF bug */ 23 25 void handle_invalid_op(struct pt_regs *regs);
+1 -1
arch/x86/include/asm/vdso.h
··· 37 37 extern const struct vdso_image vdso_image_64; 38 38 #endif 39 39 40 - #ifdef CONFIG_X86_X32 40 + #ifdef CONFIG_X86_X32_ABI 41 41 extern const struct vdso_image vdso_image_x32; 42 42 #endif 43 43
+2
arch/x86/include/uapi/asm/processor-flags.h
··· 130 130 #define X86_CR4_SMAP _BITUL(X86_CR4_SMAP_BIT) 131 131 #define X86_CR4_PKE_BIT 22 /* enable Protection Keys support */ 132 132 #define X86_CR4_PKE _BITUL(X86_CR4_PKE_BIT) 133 + #define X86_CR4_CET_BIT 23 /* enable Control-flow Enforcement Technology */ 134 + #define X86_CR4_CET _BITUL(X86_CR4_CET_BIT) 133 135 134 136 /* 135 137 * x86-64 Task Priority Register, CR8
+52 -14
arch/x86/kernel/alternative.c
··· 115 115 } 116 116 117 117 extern s32 __retpoline_sites[], __retpoline_sites_end[]; 118 + extern s32 __ibt_endbr_seal[], __ibt_endbr_seal_end[]; 118 119 extern struct alt_instr __alt_instructions[], __alt_instructions_end[]; 119 120 extern s32 __smp_locks[], __smp_locks_end[]; 120 121 void text_poke_early(void *addr, const void *opcode, size_t len); ··· 513 512 514 513 #endif /* CONFIG_RETPOLINE && CONFIG_STACK_VALIDATION */ 515 514 515 + #ifdef CONFIG_X86_KERNEL_IBT 516 + 517 + /* 518 + * Generated by: objtool --ibt 519 + */ 520 + void __init_or_module noinline apply_ibt_endbr(s32 *start, s32 *end) 521 + { 522 + s32 *s; 523 + 524 + for (s = start; s < end; s++) { 525 + u32 endbr, poison = gen_endbr_poison(); 526 + void *addr = (void *)s + *s; 527 + 528 + if (WARN_ON_ONCE(get_kernel_nofault(endbr, addr))) 529 + continue; 530 + 531 + if (WARN_ON_ONCE(!is_endbr(endbr))) 532 + continue; 533 + 534 + DPRINTK("ENDBR at: %pS (%px)", addr, addr); 535 + 536 + /* 537 + * When we have IBT, the lack of ENDBR will trigger #CP 538 + */ 539 + DUMP_BYTES(((u8*)addr), 4, "%px: orig: ", addr); 540 + DUMP_BYTES(((u8*)&poison), 4, "%px: repl: ", addr); 541 + text_poke_early(addr, &poison, 4); 542 + } 543 + } 544 + 545 + #else 546 + 547 + void __init_or_module noinline apply_ibt_endbr(s32 *start, s32 *end) { } 548 + 549 + #endif /* CONFIG_X86_KERNEL_IBT */ 550 + 516 551 #ifdef CONFIG_SMP 517 552 static void alternatives_smp_lock(const s32 *start, const s32 *end, 518 553 u8 *text, u8 *text_end) ··· 750 713 " .pushsection .init.text, \"ax\", @progbits\n" 751 714 " .type int3_magic, @function\n" 752 715 "int3_magic:\n" 716 + ANNOTATE_NOENDBR 753 717 " movl $1, (%" _ASM_ARG1 ")\n" 754 718 ASM_RET 755 719 " .size int3_magic, .-int3_magic\n" 756 720 " .popsection\n" 757 721 ); 758 722 759 - extern __initdata unsigned long int3_selftest_ip; /* defined in asm below */ 723 + extern void int3_selftest_ip(void); /* defined in asm below */ 760 724 761 725 static int __init 762 726 int3_exception_notify(struct notifier_block *self, unsigned long val, void *data) 763 727 { 728 + unsigned long selftest = (unsigned long)&int3_selftest_ip; 764 729 struct die_args *args = data; 765 730 struct pt_regs *regs = args->regs; 731 + 732 + OPTIMIZER_HIDE_VAR(selftest); 766 733 767 734 if (!regs || user_mode(regs)) 768 735 return NOTIFY_DONE; ··· 774 733 if (val != DIE_INT3) 775 734 return NOTIFY_DONE; 776 735 777 - if (regs->ip - INT3_INSN_SIZE != int3_selftest_ip) 736 + if (regs->ip - INT3_INSN_SIZE != selftest) 778 737 return NOTIFY_DONE; 779 738 780 739 int3_emulate_call(regs, (unsigned long)&int3_magic); 781 740 return NOTIFY_STOP; 782 741 } 783 742 784 - static void __init int3_selftest(void) 743 + /* Must be noinline to ensure uniqueness of int3_selftest_ip. */ 744 + static noinline void __init int3_selftest(void) 785 745 { 786 746 static __initdata struct notifier_block int3_exception_nb = { 787 747 .notifier_call = int3_exception_notify, ··· 795 753 /* 796 754 * Basically: int3_magic(&val); but really complicated :-) 797 755 * 798 - * Stick the address of the INT3 instruction into int3_selftest_ip, 799 - * then trigger the INT3, padded with NOPs to match a CALL instruction 800 - * length. 756 + * INT3 padded with NOP to CALL_INSN_SIZE. The int3_exception_nb 757 + * notifier above will emulate CALL for us. 801 758 */ 802 - asm volatile ("1: int3; nop; nop; nop; nop\n\t" 803 - ".pushsection .init.data,\"aw\"\n\t" 804 - ".align " __ASM_SEL(4, 8) "\n\t" 805 - ".type int3_selftest_ip, @object\n\t" 806 - ".size int3_selftest_ip, " __ASM_SEL(4, 8) "\n\t" 807 - "int3_selftest_ip:\n\t" 808 - __ASM_SEL(.long, .quad) " 1b\n\t" 809 - ".popsection\n\t" 759 + asm volatile ("int3_selftest_ip:\n\t" 760 + ANNOTATE_NOENDBR 761 + " int3; nop; nop; nop; nop\n\t" 810 762 : ASM_CALL_CONSTRAINT 811 763 : __ASM_SEL_RAW(a, D) (&val) 812 764 : "memory"); ··· 866 830 * alternatives can be overwritten by their immediate fragments. 867 831 */ 868 832 apply_alternatives(__alt_instructions, __alt_instructions_end); 833 + 834 + apply_ibt_endbr(__ibt_endbr_seal, __ibt_endbr_seal_end); 869 835 870 836 #ifdef CONFIG_SMP 871 837 /* Patch to UP if other cpus not imminent. */
+7
arch/x86/kernel/apm_32.c
··· 232 232 #include <asm/paravirt.h> 233 233 #include <asm/reboot.h> 234 234 #include <asm/nospec-branch.h> 235 + #include <asm/ibt.h> 235 236 236 237 #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT) 237 238 extern int (*console_blank_hook)(int); ··· 599 598 struct desc_struct save_desc_40; 600 599 struct desc_struct *gdt; 601 600 struct apm_bios_call *call = _call; 601 + u64 ibt; 602 602 603 603 cpu = get_cpu(); 604 604 BUG_ON(cpu != 0); ··· 609 607 610 608 apm_irq_save(flags); 611 609 firmware_restrict_branch_speculation_start(); 610 + ibt = ibt_save(); 612 611 APM_DO_SAVE_SEGS; 613 612 apm_bios_call_asm(call->func, call->ebx, call->ecx, 614 613 &call->eax, &call->ebx, &call->ecx, &call->edx, 615 614 &call->esi); 616 615 APM_DO_RESTORE_SEGS; 616 + ibt_restore(ibt); 617 617 firmware_restrict_branch_speculation_end(); 618 618 apm_irq_restore(flags); 619 619 gdt[0x40 / 8] = save_desc_40; ··· 680 676 struct desc_struct save_desc_40; 681 677 struct desc_struct *gdt; 682 678 struct apm_bios_call *call = _call; 679 + u64 ibt; 683 680 684 681 cpu = get_cpu(); 685 682 BUG_ON(cpu != 0); ··· 690 685 691 686 apm_irq_save(flags); 692 687 firmware_restrict_branch_speculation_start(); 688 + ibt = ibt_save(); 693 689 APM_DO_SAVE_SEGS; 694 690 error = apm_bios_call_simple_asm(call->func, call->ebx, call->ecx, 695 691 &call->eax); 696 692 APM_DO_RESTORE_SEGS; 693 + ibt_restore(ibt); 697 694 firmware_restrict_branch_speculation_end(); 698 695 apm_irq_restore(flags); 699 696 gdt[0x40 / 8] = save_desc_40;
+58 -1
arch/x86/kernel/cpu/common.c
··· 59 59 #include <asm/cpu_device_id.h> 60 60 #include <asm/uv/uv.h> 61 61 #include <asm/sigframe.h> 62 + #include <asm/traps.h> 62 63 63 64 #include "cpu.h" 64 65 ··· 439 438 440 439 /* These bits should not change their value after CPU init is finished. */ 441 440 static const unsigned long cr4_pinned_mask = 442 - X86_CR4_SMEP | X86_CR4_SMAP | X86_CR4_UMIP | X86_CR4_FSGSBASE; 441 + X86_CR4_SMEP | X86_CR4_SMAP | X86_CR4_UMIP | 442 + X86_CR4_FSGSBASE | X86_CR4_CET; 443 443 static DEFINE_STATIC_KEY_FALSE_RO(cr_pinning); 444 444 static unsigned long cr4_pinned_bits __ro_after_init; 445 445 ··· 593 591 } 594 592 __setup("nopku", setup_disable_pku); 595 593 #endif /* CONFIG_X86_64 */ 594 + 595 + #ifdef CONFIG_X86_KERNEL_IBT 596 + 597 + __noendbr u64 ibt_save(void) 598 + { 599 + u64 msr = 0; 600 + 601 + if (cpu_feature_enabled(X86_FEATURE_IBT)) { 602 + rdmsrl(MSR_IA32_S_CET, msr); 603 + wrmsrl(MSR_IA32_S_CET, msr & ~CET_ENDBR_EN); 604 + } 605 + 606 + return msr; 607 + } 608 + 609 + __noendbr void ibt_restore(u64 save) 610 + { 611 + u64 msr; 612 + 613 + if (cpu_feature_enabled(X86_FEATURE_IBT)) { 614 + rdmsrl(MSR_IA32_S_CET, msr); 615 + msr &= ~CET_ENDBR_EN; 616 + msr |= (save & CET_ENDBR_EN); 617 + wrmsrl(MSR_IA32_S_CET, msr); 618 + } 619 + } 620 + 621 + #endif 622 + 623 + static __always_inline void setup_cet(struct cpuinfo_x86 *c) 624 + { 625 + u64 msr = CET_ENDBR_EN; 626 + 627 + if (!HAS_KERNEL_IBT || 628 + !cpu_feature_enabled(X86_FEATURE_IBT)) 629 + return; 630 + 631 + wrmsrl(MSR_IA32_S_CET, msr); 632 + cr4_set_bits(X86_CR4_CET); 633 + 634 + if (!ibt_selftest()) { 635 + pr_err("IBT selftest: Failed!\n"); 636 + setup_clear_cpu_cap(X86_FEATURE_IBT); 637 + return; 638 + } 639 + } 640 + 641 + __noendbr void cet_disable(void) 642 + { 643 + if (cpu_feature_enabled(X86_FEATURE_IBT)) 644 + wrmsrl(MSR_IA32_S_CET, 0); 645 + } 596 646 597 647 /* 598 648 * Some CPU features depend on higher CPUID levels, which may not always ··· 1763 1709 1764 1710 x86_init_rdrand(c); 1765 1711 setup_pku(c); 1712 + setup_cet(c); 1766 1713 1767 1714 /* 1768 1715 * Clear/Set all flags overridden by options, need do it ··· 1832 1777 void __init identify_boot_cpu(void) 1833 1778 { 1834 1779 identify_cpu(&boot_cpu_data); 1780 + if (HAS_KERNEL_IBT && cpu_feature_enabled(X86_FEATURE_IBT)) 1781 + pr_info("CET detected: Indirect Branch Tracking enabled\n"); 1835 1782 #ifdef CONFIG_X86_32 1836 1783 sysenter_setup(); 1837 1784 enable_sep_cpu();
+2 -7
arch/x86/kernel/ftrace.c
··· 316 316 unsigned long offset; 317 317 unsigned long npages; 318 318 unsigned long size; 319 - unsigned long retq; 320 319 unsigned long *ptr; 321 320 void *trampoline; 322 321 void *ip; 323 322 /* 48 8b 15 <offset> is movq <offset>(%rip), %rdx */ 324 323 unsigned const char op_ref[] = { 0x48, 0x8b, 0x15 }; 324 + unsigned const char retq[] = { RET_INSN_OPCODE, INT3_INSN_OPCODE }; 325 325 union ftrace_op_code_union op_ptr; 326 326 int ret; 327 327 ··· 359 359 goto fail; 360 360 361 361 ip = trampoline + size; 362 - 363 - /* The trampoline ends with ret(q) */ 364 - retq = (unsigned long)ftrace_stub; 365 - ret = copy_from_kernel_nofault(ip, (void *)retq, RET_SIZE); 366 - if (WARN_ON(ret < 0)) 367 - goto fail; 362 + memcpy(ip, retq, RET_SIZE); 368 363 369 364 /* No need to test direct calls on created trampolines */ 370 365 if (ops->flags & FTRACE_OPS_FL_SAVE_REGS) {
+24 -4
arch/x86/kernel/ftrace_64.S
··· 145 145 movq %rcx, RSP(%rsp) 146 146 147 147 SYM_INNER_LABEL(ftrace_caller_op_ptr, SYM_L_GLOBAL) 148 + ANNOTATE_NOENDBR 148 149 /* Load the ftrace_ops into the 3rd parameter */ 149 150 movq function_trace_op(%rip), %rdx 150 151 ··· 156 155 movq $0, CS(%rsp) 157 156 158 157 SYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL) 158 + ANNOTATE_NOENDBR 159 159 call ftrace_stub 160 160 161 161 /* Handlers can change the RIP */ ··· 171 169 * layout here. 172 170 */ 173 171 SYM_INNER_LABEL(ftrace_caller_end, SYM_L_GLOBAL) 172 + ANNOTATE_NOENDBR 174 173 175 174 jmp ftrace_epilogue 176 175 SYM_FUNC_END(ftrace_caller); ··· 179 176 SYM_FUNC_START(ftrace_epilogue) 180 177 /* 181 178 * This is weak to keep gas from relaxing the jumps. 182 - * It is also used to copy the RET for trampolines. 183 179 */ 184 180 SYM_INNER_LABEL_ALIGN(ftrace_stub, SYM_L_WEAK) 185 181 UNWIND_HINT_FUNC 182 + ENDBR 186 183 RET 187 184 SYM_FUNC_END(ftrace_epilogue) 188 185 ··· 195 192 /* save_mcount_regs fills in first two parameters */ 196 193 197 194 SYM_INNER_LABEL(ftrace_regs_caller_op_ptr, SYM_L_GLOBAL) 195 + ANNOTATE_NOENDBR 198 196 /* Load the ftrace_ops into the 3rd parameter */ 199 197 movq function_trace_op(%rip), %rdx 200 198 ··· 225 221 leaq (%rsp), %rcx 226 222 227 223 SYM_INNER_LABEL(ftrace_regs_call, SYM_L_GLOBAL) 224 + ANNOTATE_NOENDBR 228 225 call ftrace_stub 229 226 230 227 /* Copy flags back to SS, to restore them */ ··· 253 248 */ 254 249 testq %rax, %rax 255 250 SYM_INNER_LABEL(ftrace_regs_caller_jmp, SYM_L_GLOBAL) 251 + ANNOTATE_NOENDBR 256 252 jnz 1f 257 253 258 254 restore_mcount_regs ··· 267 261 * to the return. 268 262 */ 269 263 SYM_INNER_LABEL(ftrace_regs_caller_end, SYM_L_GLOBAL) 264 + ANNOTATE_NOENDBR 270 265 jmp ftrace_epilogue 271 266 272 267 /* Swap the flags with orig_rax */ ··· 291 284 jnz trace 292 285 293 286 SYM_INNER_LABEL(ftrace_stub, SYM_L_GLOBAL) 287 + ENDBR 294 288 RET 295 289 296 290 trace: ··· 315 307 316 308 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 317 309 SYM_FUNC_START(return_to_handler) 318 - subq $24, %rsp 310 + subq $16, %rsp 319 311 320 312 /* Save the return values */ 321 313 movq %rax, (%rsp) ··· 327 319 movq %rax, %rdi 328 320 movq 8(%rsp), %rdx 329 321 movq (%rsp), %rax 330 - addq $24, %rsp 331 - JMP_NOSPEC rdi 322 + 323 + addq $16, %rsp 324 + /* 325 + * Jump back to the old return address. This cannot be JMP_NOSPEC rdi 326 + * since IBT would demand that contain ENDBR, which simply isn't so for 327 + * return addresses. Use a retpoline here to keep the RSB balanced. 328 + */ 329 + ANNOTATE_INTRA_FUNCTION_CALL 330 + call .Ldo_rop 331 + int3 332 + .Ldo_rop: 333 + mov %rdi, (%rsp) 334 + UNWIND_HINT_FUNC 335 + RET 332 336 SYM_FUNC_END(return_to_handler) 333 337 #endif
+12 -2
arch/x86/kernel/head_64.S
··· 99 99 100 100 SYM_CODE_START(secondary_startup_64) 101 101 UNWIND_HINT_EMPTY 102 + ANNOTATE_NOENDBR 102 103 /* 103 104 * At this point the CPU runs in 64bit mode CS.L = 1 CS.D = 0, 104 105 * and someone has loaded a mapped page table. ··· 128 127 */ 129 128 SYM_INNER_LABEL(secondary_startup_64_no_verify, SYM_L_GLOBAL) 130 129 UNWIND_HINT_EMPTY 130 + ANNOTATE_NOENDBR 131 131 132 132 /* 133 133 * Retrieve the modifier (SME encryption mask if SME is active) to be ··· 194 192 jmp *%rax 195 193 1: 196 194 UNWIND_HINT_EMPTY 195 + ANNOTATE_NOENDBR // above 197 196 198 197 /* 199 198 * We must switch to a new descriptor in kernel space for the GDT ··· 302 299 pushq %rax # target address in negative space 303 300 lretq 304 301 .Lafter_lret: 302 + ANNOTATE_NOENDBR 305 303 SYM_CODE_END(secondary_startup_64) 306 304 307 305 #include "verify_cpu.S" ··· 332 328 */ 333 329 SYM_CODE_START_NOALIGN(vc_boot_ghcb) 334 330 UNWIND_HINT_IRET_REGS offset=8 331 + ENDBR 335 332 336 333 /* Build pt_regs */ 337 334 PUSH_AND_CLEAR_REGS ··· 350 345 /* Remove Error Code */ 351 346 addq $8, %rsp 352 347 353 - /* Pure iret required here - don't use INTERRUPT_RETURN */ 354 348 iretq 355 349 SYM_CODE_END(vc_boot_ghcb) 356 350 #endif ··· 376 372 .rept NUM_EXCEPTION_VECTORS 377 373 .if ((EXCEPTION_ERRCODE_MASK >> i) & 1) == 0 378 374 UNWIND_HINT_IRET_REGS 375 + ENDBR 379 376 pushq $0 # Dummy error code, to make stack frame uniform 380 377 .else 381 378 UNWIND_HINT_IRET_REGS offset=8 379 + ENDBR 382 380 .endif 383 381 pushq $i # 72(%rsp) Vector number 384 382 jmp early_idt_handler_common ··· 388 382 i = i + 1 389 383 .fill early_idt_handler_array + i*EARLY_IDT_HANDLER_SIZE - ., 1, 0xcc 390 384 .endr 391 - UNWIND_HINT_IRET_REGS offset=16 392 385 SYM_CODE_END(early_idt_handler_array) 386 + ANNOTATE_NOENDBR // early_idt_handler_array[NUM_EXCEPTION_VECTORS] 393 387 394 388 SYM_CODE_START_LOCAL(early_idt_handler_common) 389 + UNWIND_HINT_IRET_REGS offset=16 395 390 /* 396 391 * The stack is the hardware frame, an error code or zero, and the 397 392 * vector number. ··· 433 426 * early_idt_handler_array can't be used because it returns via the 434 427 * paravirtualized INTERRUPT_RETURN and pv-ops don't work that early. 435 428 * 429 + * XXX it does, fix this. 430 + * 436 431 * This handler will end up in the .init.text section and not be 437 432 * available to boot secondary CPUs. 438 433 */ 439 434 SYM_CODE_START_NOALIGN(vc_no_ghcb) 440 435 UNWIND_HINT_IRET_REGS offset=8 436 + ENDBR 441 437 442 438 /* Build pt_regs */ 443 439 PUSH_AND_CLEAR_REGS
+7 -2
arch/x86/kernel/idt.c
··· 10 10 #include <asm/proto.h> 11 11 #include <asm/desc.h> 12 12 #include <asm/hw_irq.h> 13 + #include <asm/idtentry.h> 13 14 14 15 #define DPL0 0x0 15 16 #define DPL3 0x3 ··· 102 101 103 102 #ifdef CONFIG_X86_MCE 104 103 ISTG(X86_TRAP_MC, asm_exc_machine_check, IST_INDEX_MCE), 104 + #endif 105 + 106 + #ifdef CONFIG_X86_KERNEL_IBT 107 + INTG(X86_TRAP_CP, asm_exc_control_protection), 105 108 #endif 106 109 107 110 #ifdef CONFIG_AMD_MEM_ENCRYPT ··· 277 272 idt_setup_from_table(idt_table, apic_idts, ARRAY_SIZE(apic_idts), true); 278 273 279 274 for_each_clear_bit_from(i, system_vectors, FIRST_SYSTEM_VECTOR) { 280 - entry = irq_entries_start + 8 * (i - FIRST_EXTERNAL_VECTOR); 275 + entry = irq_entries_start + IDT_ALIGN * (i - FIRST_EXTERNAL_VECTOR); 281 276 set_intr_gate(i, entry); 282 277 } 283 278 ··· 288 283 * system_vectors bitmap. Otherwise they show up in 289 284 * /proc/interrupts. 290 285 */ 291 - entry = spurious_entries_start + 8 * (i - FIRST_SYSTEM_VECTOR); 286 + entry = spurious_entries_start + IDT_ALIGN * (i - FIRST_SYSTEM_VECTOR); 292 287 set_intr_gate(i, entry); 293 288 } 294 289 #endif
+20 -9
arch/x86/kernel/kprobes/core.c
··· 52 52 #include <asm/insn.h> 53 53 #include <asm/debugreg.h> 54 54 #include <asm/set_memory.h> 55 + #include <asm/ibt.h> 55 56 56 57 #include "common.h" 57 58 ··· 194 193 __recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr) 195 194 { 196 195 struct kprobe *kp; 197 - unsigned long faddr; 196 + bool faddr; 198 197 199 198 kp = get_kprobe((void *)addr); 200 - faddr = ftrace_location(addr); 201 - /* 202 - * Addresses inside the ftrace location are refused by 203 - * arch_check_ftrace_location(). Something went terribly wrong 204 - * if such an address is checked here. 205 - */ 206 - if (WARN_ON(faddr && faddr != addr)) 207 - return 0UL; 199 + faddr = ftrace_location(addr) == addr; 208 200 /* 209 201 * Use the current code if it is not modified by Kprobe 210 202 * and it cannot be modified by ftrace. ··· 293 299 } 294 300 295 301 return (addr == paddr); 302 + } 303 + 304 + /* If x86 supports IBT (ENDBR) it must be skipped. */ 305 + kprobe_opcode_t *arch_adjust_kprobe_addr(unsigned long addr, unsigned long offset, 306 + bool *on_func_entry) 307 + { 308 + if (is_endbr(*(u32 *)addr)) { 309 + *on_func_entry = !offset || offset == 4; 310 + if (*on_func_entry) 311 + offset = 4; 312 + 313 + } else { 314 + *on_func_entry = !offset; 315 + } 316 + 317 + return (kprobe_opcode_t *)(addr + offset); 296 318 } 297 319 298 320 /* ··· 1033 1023 ".type __kretprobe_trampoline, @function\n" 1034 1024 "__kretprobe_trampoline:\n" 1035 1025 #ifdef CONFIG_X86_64 1026 + ANNOTATE_NOENDBR 1036 1027 /* Push a fake return address to tell the unwinder it's a kretprobe. */ 1037 1028 " pushq $__kretprobe_trampoline\n" 1038 1029 UNWIND_HINT_FUNC
+2 -1
arch/x86/kernel/kvm.c
··· 1029 1029 ".global __raw_callee_save___kvm_vcpu_is_preempted;" 1030 1030 ".type __raw_callee_save___kvm_vcpu_is_preempted, @function;" 1031 1031 "__raw_callee_save___kvm_vcpu_is_preempted:" 1032 + ASM_ENDBR 1032 1033 "movq __per_cpu_offset(,%rdi,8), %rax;" 1033 1034 "cmpb $0, " __stringify(KVM_STEAL_TIME_preempted) "+steal_time(%rax);" 1034 1035 "setne %al;" 1035 - "ret;" 1036 + ASM_RET 1036 1037 ".size __raw_callee_save___kvm_vcpu_is_preempted, .-__raw_callee_save___kvm_vcpu_is_preempted;" 1037 1038 ".popsection"); 1038 1039
+3 -1
arch/x86/kernel/machine_kexec_64.c
··· 27 27 #include <asm/kexec-bzimage64.h> 28 28 #include <asm/setup.h> 29 29 #include <asm/set_memory.h> 30 + #include <asm/cpu.h> 30 31 31 32 #ifdef CONFIG_ACPI 32 33 /* ··· 311 310 /* Interrupts aren't acceptable while we reboot */ 312 311 local_irq_disable(); 313 312 hw_breakpoint_disable(); 313 + cet_disable(); 314 314 315 315 if (image->preserve_context) { 316 316 #ifdef CONFIG_X86_IO_APIC ··· 327 325 } 328 326 329 327 control_page = page_address(image->control_code_page) + PAGE_SIZE; 330 - memcpy(control_page, relocate_kernel, KEXEC_CONTROL_CODE_MAX_SIZE); 328 + __memcpy(control_page, relocate_kernel, KEXEC_CONTROL_CODE_MAX_SIZE); 331 329 332 330 page_list[PA_CONTROL_PAGE] = virt_to_phys(control_page); 333 331 page_list[VA_CONTROL_PAGE] = (unsigned long)control_page;
+7 -1
arch/x86/kernel/module.c
··· 253 253 { 254 254 const Elf_Shdr *s, *text = NULL, *alt = NULL, *locks = NULL, 255 255 *para = NULL, *orc = NULL, *orc_ip = NULL, 256 - *retpolines = NULL; 256 + *retpolines = NULL, *ibt_endbr = NULL; 257 257 char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; 258 258 259 259 for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { ··· 271 271 orc_ip = s; 272 272 if (!strcmp(".retpoline_sites", secstrings + s->sh_name)) 273 273 retpolines = s; 274 + if (!strcmp(".ibt_endbr_seal", secstrings + s->sh_name)) 275 + ibt_endbr = s; 274 276 } 275 277 276 278 /* ··· 291 289 /* patch .altinstructions */ 292 290 void *aseg = (void *)alt->sh_addr; 293 291 apply_alternatives(aseg, aseg + alt->sh_size); 292 + } 293 + if (ibt_endbr) { 294 + void *iseg = (void *)ibt_endbr->sh_addr; 295 + apply_ibt_endbr(iseg, iseg + ibt_endbr->sh_size); 294 296 } 295 297 if (locks && text) { 296 298 void *lseg = (void *)locks->sh_addr;
+5 -24
arch/x86/kernel/paravirt.c
··· 41 41 asm (".pushsection .entry.text, \"ax\"\n" 42 42 ".global _paravirt_nop\n" 43 43 "_paravirt_nop:\n\t" 44 + ASM_ENDBR 44 45 ASM_RET 45 46 ".size _paravirt_nop, . - _paravirt_nop\n\t" 46 47 ".type _paravirt_nop, @function\n\t" ··· 51 50 asm (".pushsection .entry.text, \"ax\"\n" 52 51 ".global paravirt_ret0\n" 53 52 "paravirt_ret0:\n\t" 53 + ASM_ENDBR 54 54 "xor %" _ASM_AX ", %" _ASM_AX ";\n\t" 55 55 ASM_RET 56 56 ".size paravirt_ret0, . - paravirt_ret0\n\t" ··· 71 69 BUG(); 72 70 } 73 71 74 - struct branch { 75 - unsigned char opcode; 76 - u32 delta; 77 - } __attribute__((packed)); 78 - 79 72 static unsigned paravirt_patch_call(void *insn_buff, const void *target, 80 73 unsigned long addr, unsigned len) 81 74 { 82 - const int call_len = 5; 83 - struct branch *b = insn_buff; 84 - unsigned long delta = (unsigned long)target - (addr+call_len); 85 - 86 - if (len < call_len) { 87 - pr_warn("paravirt: Failed to patch indirect CALL at %ps\n", (void *)addr); 88 - /* Kernel might not be viable if patching fails, bail out: */ 89 - BUG_ON(1); 90 - } 91 - 92 - b->opcode = 0xe8; /* call */ 93 - b->delta = delta; 94 - BUILD_BUG_ON(sizeof(*b) != call_len); 95 - 96 - return call_len; 75 + __text_gen_insn(insn_buff, CALL_INSN_OPCODE, 76 + (void *)addr, target, CALL_INSN_SIZE); 77 + return CALL_INSN_SIZE; 97 78 } 98 79 99 80 #ifdef CONFIG_PARAVIRT_XXL ··· 134 149 } 135 150 136 151 /* These are in entry.S */ 137 - extern void native_iret(void); 138 - 139 152 static struct resource reserve_ioports = { 140 153 .start = 0, 141 154 .end = IO_SPACE_LIMIT, ··· 397 414 398 415 #ifdef CONFIG_PARAVIRT_XXL 399 416 NOKPROBE_SYMBOL(native_load_idt); 400 - 401 - void (*paravirt_iret)(void) = native_iret; 402 417 #endif 403 418 404 419 EXPORT_SYMBOL(pv_ops);
+1 -1
arch/x86/kernel/process.c
··· 747 747 } 748 748 #endif 749 749 750 - void stop_this_cpu(void *dummy) 750 + void __noreturn stop_this_cpu(void *dummy) 751 751 { 752 752 local_irq_disable(); 753 753 /*
+1 -1
arch/x86/kernel/process_64.c
··· 681 681 682 682 static void __set_personality_x32(void) 683 683 { 684 - #ifdef CONFIG_X86_X32 684 + #ifdef CONFIG_X86_X32_ABI 685 685 if (current->mm) 686 686 current->mm->context.flags = 0; 687 687
+10
arch/x86/kernel/relocate_kernel_64.S
··· 42 42 .code64 43 43 SYM_CODE_START_NOALIGN(relocate_kernel) 44 44 UNWIND_HINT_EMPTY 45 + ANNOTATE_NOENDBR 45 46 /* 46 47 * %rdi indirection_page 47 48 * %rsi page_list ··· 114 113 pushq $0 115 114 /* store the start address on the stack */ 116 115 pushq %rdx 116 + 117 + /* 118 + * Clear X86_CR4_CET (if it was set) such that we can clear CR0_WP 119 + * below. 120 + */ 121 + movq %cr4, %rax 122 + andq $~(X86_CR4_CET), %rax 123 + movq %rax, %cr4 117 124 118 125 /* 119 126 * Set cr0 to a known state: ··· 224 215 225 216 SYM_CODE_START_LOCAL_NOALIGN(virtual_mapped) 226 217 UNWIND_HINT_EMPTY 218 + ANNOTATE_NOENDBR // RET target, above 227 219 movq RSP(%r8), %rsp 228 220 movq CR4(%r8), %rax 229 221 movq %rax, %cr4
+75
arch/x86/kernel/traps.c
··· 210 210 do_error_trap(regs, 0, "overflow", X86_TRAP_OF, SIGSEGV, 0, NULL); 211 211 } 212 212 213 + #ifdef CONFIG_X86_KERNEL_IBT 214 + 215 + static __ro_after_init bool ibt_fatal = true; 216 + 217 + extern void ibt_selftest_ip(void); /* code label defined in asm below */ 218 + 219 + enum cp_error_code { 220 + CP_EC = (1 << 15) - 1, 221 + 222 + CP_RET = 1, 223 + CP_IRET = 2, 224 + CP_ENDBR = 3, 225 + CP_RSTRORSSP = 4, 226 + CP_SETSSBSY = 5, 227 + 228 + CP_ENCL = 1 << 15, 229 + }; 230 + 231 + DEFINE_IDTENTRY_ERRORCODE(exc_control_protection) 232 + { 233 + if (!cpu_feature_enabled(X86_FEATURE_IBT)) { 234 + pr_err("Unexpected #CP\n"); 235 + BUG(); 236 + } 237 + 238 + if (WARN_ON_ONCE(user_mode(regs) || (error_code & CP_EC) != CP_ENDBR)) 239 + return; 240 + 241 + if (unlikely(regs->ip == (unsigned long)&ibt_selftest_ip)) { 242 + regs->ax = 0; 243 + return; 244 + } 245 + 246 + pr_err("Missing ENDBR: %pS\n", (void *)instruction_pointer(regs)); 247 + if (!ibt_fatal) { 248 + printk(KERN_DEFAULT CUT_HERE); 249 + __warn(__FILE__, __LINE__, (void *)regs->ip, TAINT_WARN, regs, NULL); 250 + return; 251 + } 252 + BUG(); 253 + } 254 + 255 + /* Must be noinline to ensure uniqueness of ibt_selftest_ip. */ 256 + noinline bool ibt_selftest(void) 257 + { 258 + unsigned long ret; 259 + 260 + asm (" lea ibt_selftest_ip(%%rip), %%rax\n\t" 261 + ANNOTATE_RETPOLINE_SAFE 262 + " jmp *%%rax\n\t" 263 + "ibt_selftest_ip:\n\t" 264 + UNWIND_HINT_FUNC 265 + ANNOTATE_NOENDBR 266 + " nop\n\t" 267 + 268 + : "=a" (ret) : : "memory"); 269 + 270 + return !ret; 271 + } 272 + 273 + static int __init ibt_setup(char *str) 274 + { 275 + if (!strcmp(str, "off")) 276 + setup_clear_cpu_cap(X86_FEATURE_IBT); 277 + 278 + if (!strcmp(str, "warn")) 279 + ibt_fatal = false; 280 + 281 + return 1; 282 + } 283 + 284 + __setup("ibt=", ibt_setup); 285 + 286 + #endif /* CONFIG_X86_KERNEL_IBT */ 287 + 213 288 #ifdef CONFIG_X86_F00F_BUG 214 289 void handle_invalid_op(struct pt_regs *regs) 215 290 #else
+9
arch/x86/kernel/vmlinux.lds.S
··· 285 285 } 286 286 #endif 287 287 288 + #ifdef CONFIG_X86_KERNEL_IBT 289 + . = ALIGN(8); 290 + .ibt_endbr_seal : AT(ADDR(.ibt_endbr_seal) - LOAD_OFFSET) { 291 + __ibt_endbr_seal = .; 292 + *(.ibt_endbr_seal) 293 + __ibt_endbr_seal_end = .; 294 + } 295 + #endif 296 + 288 297 /* 289 298 * struct alt_inst entries. From the header (alternative.h): 290 299 * "Alternative instructions for different CPU types or capabilities"
+10 -6
arch/x86/kvm/emulate.c
··· 24 24 #include <linux/stringify.h> 25 25 #include <asm/debugreg.h> 26 26 #include <asm/nospec-branch.h> 27 + #include <asm/ibt.h> 27 28 28 29 #include "x86.h" 29 30 #include "tss.h" ··· 190 189 #define X16(x...) X8(x), X8(x) 191 190 192 191 #define NR_FASTOP (ilog2(sizeof(ulong)) + 1) 193 - #define FASTOP_SIZE 8 192 + #define FASTOP_SIZE (8 * (1 + HAS_KERNEL_IBT)) 194 193 195 194 struct opcode { 196 195 u64 flags; ··· 312 311 #define __FOP_FUNC(name) \ 313 312 ".align " __stringify(FASTOP_SIZE) " \n\t" \ 314 313 ".type " name ", @function \n\t" \ 315 - name ":\n\t" 314 + name ":\n\t" \ 315 + ASM_ENDBR 316 316 317 317 #define FOP_FUNC(name) \ 318 318 __FOP_FUNC(#name) ··· 435 433 /* 436 434 * Depending on .config the SETcc functions look like: 437 435 * 436 + * ENDBR [4 bytes; CONFIG_X86_KERNEL_IBT] 438 437 * SETcc %al [3 bytes] 439 438 * RET [1 byte] 440 439 * INT3 [1 byte; CONFIG_SLS] 441 440 * 442 - * Which gives possible sizes 4 or 5. When rounded up to the 443 - * next power-of-two alignment they become 4 or 8. 441 + * Which gives possible sizes 4, 5, 8 or 9. When rounded up to the 442 + * next power-of-two alignment they become 4, 8 or 16 resp. 444 443 */ 445 - #define SETCC_LENGTH (4 + IS_ENABLED(CONFIG_SLS)) 446 - #define SETCC_ALIGN (4 << IS_ENABLED(CONFIG_SLS)) 444 + #define SETCC_LENGTH (ENDBR_INSN_SIZE + 4 + IS_ENABLED(CONFIG_SLS)) 445 + #define SETCC_ALIGN (4 << IS_ENABLED(CONFIG_SLS) << HAS_KERNEL_IBT) 447 446 static_assert(SETCC_LENGTH <= SETCC_ALIGN); 448 447 449 448 #define FOP_SETCC(op) \ 450 449 ".align " __stringify(SETCC_ALIGN) " \n\t" \ 451 450 ".type " #op ", @function \n\t" \ 452 451 #op ": \n\t" \ 452 + ASM_ENDBR \ 453 453 #op " %al \n\t" \ 454 454 __FOP_RET(#op) 455 455
+2
arch/x86/lib/error-inject.c
··· 3 3 #include <linux/linkage.h> 4 4 #include <linux/error-injection.h> 5 5 #include <linux/kprobes.h> 6 + #include <linux/objtool.h> 6 7 7 8 asmlinkage void just_return_func(void); 8 9 ··· 12 11 ".type just_return_func, @function\n" 13 12 ".globl just_return_func\n" 14 13 "just_return_func:\n" 14 + ANNOTATE_NOENDBR 15 15 ASM_RET 16 16 ".size just_return_func, .-just_return_func\n" 17 17 );
+1
arch/x86/lib/retpoline.S
··· 55 55 56 56 .align RETPOLINE_THUNK_SIZE 57 57 SYM_CODE_START(__x86_indirect_thunk_array) 58 + ANNOTATE_NOENDBR // apply_retpolines 58 59 59 60 #define GEN(reg) THUNK reg 60 61 #include <asm/GEN-for-each-reg.h>
+24 -2
arch/x86/net/bpf_jit_comp.c
··· 46 46 #define EMIT4_off32(b1, b2, b3, b4, off) \ 47 47 do { EMIT4(b1, b2, b3, b4); EMIT(off, 4); } while (0) 48 48 49 + #ifdef CONFIG_X86_KERNEL_IBT 50 + #define EMIT_ENDBR() EMIT(gen_endbr(), 4) 51 + #else 52 + #define EMIT_ENDBR() 53 + #endif 54 + 49 55 static bool is_imm8(int value) 50 56 { 51 57 return value <= 127 && value >= -128; ··· 247 241 /* Number of bytes emit_patch() needs to generate instructions */ 248 242 #define X86_PATCH_SIZE 5 249 243 /* Number of bytes that will be skipped on tailcall */ 250 - #define X86_TAIL_CALL_OFFSET 11 244 + #define X86_TAIL_CALL_OFFSET (11 + ENDBR_INSN_SIZE) 251 245 252 246 static void push_callee_regs(u8 **pprog, bool *callee_regs_used) 253 247 { ··· 292 286 /* BPF trampoline can be made to work without these nops, 293 287 * but let's waste 5 bytes for now and optimize later 294 288 */ 289 + EMIT_ENDBR(); 295 290 memcpy(prog, x86_nops[5], X86_PATCH_SIZE); 296 291 prog += X86_PATCH_SIZE; 297 292 if (!ebpf_from_cbpf) { ··· 303 296 } 304 297 EMIT1(0x55); /* push rbp */ 305 298 EMIT3(0x48, 0x89, 0xE5); /* mov rbp, rsp */ 299 + 300 + /* X86_TAIL_CALL_OFFSET is here */ 301 + EMIT_ENDBR(); 302 + 306 303 /* sub rsp, rounded_stack_depth */ 307 304 if (stack_depth) 308 305 EMIT3_off32(0x48, 0x81, 0xEC, round_up(stack_depth, 8)); ··· 390 379 !is_bpf_text_address((long)ip)) 391 380 /* BPF poking in modules is not supported */ 392 381 return -EINVAL; 382 + 383 + /* 384 + * See emit_prologue(), for IBT builds the trampoline hook is preceded 385 + * with an ENDBR instruction. 386 + */ 387 + if (is_endbr(*(u32 *)ip)) 388 + ip += ENDBR_INSN_SIZE; 393 389 394 390 return __bpf_arch_text_poke(ip, t, old_addr, new_addr); 395 391 } ··· 2031 2013 2032 2014 ip_off = stack_size; 2033 2015 2034 - if (flags & BPF_TRAMP_F_SKIP_FRAME) 2016 + if (flags & BPF_TRAMP_F_SKIP_FRAME) { 2035 2017 /* skip patched call instruction and point orig_call to actual 2036 2018 * body of the kernel function. 2037 2019 */ 2020 + if (is_endbr(*(u32 *)orig_call)) 2021 + orig_call += ENDBR_INSN_SIZE; 2038 2022 orig_call += X86_PATCH_SIZE; 2023 + } 2039 2024 2040 2025 prog = image; 2041 2026 2027 + EMIT_ENDBR(); 2042 2028 EMIT1(0x55); /* push rbp */ 2043 2029 EMIT3(0x48, 0x89, 0xE5); /* mov rbp, rsp */ 2044 2030 EMIT4(0x48, 0x83, 0xEC, stack_size); /* sub rsp, stack_size */
-1
arch/x86/platform/efi/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 - OBJECT_FILES_NON_STANDARD_efi_thunk_$(BITS).o := y 3 2 KASAN_SANITIZE := n 4 3 GCOV_PROFILE := n 5 4
+4 -2
arch/x86/platform/efi/efi_thunk_64.S
··· 20 20 */ 21 21 22 22 #include <linux/linkage.h> 23 + #include <linux/objtool.h> 23 24 #include <asm/page_types.h> 24 25 #include <asm/segment.h> 25 26 26 27 .text 27 28 .code64 28 - SYM_CODE_START(__efi64_thunk) 29 + SYM_FUNC_START(__efi64_thunk) 30 + STACK_FRAME_NON_STANDARD __efi64_thunk 29 31 push %rbp 30 32 push %rbx 31 33 ··· 81 79 2: pushl $__KERNEL_CS 82 80 pushl %ebp 83 81 lret 84 - SYM_CODE_END(__efi64_thunk) 82 + SYM_FUNC_END(__efi64_thunk) 85 83 86 84 .bss 87 85 .balign 8
+9 -1
arch/x86/xen/enlighten_pv.c
··· 624 624 TRAP_ENTRY(exc_coprocessor_error, false ), 625 625 TRAP_ENTRY(exc_alignment_check, false ), 626 626 TRAP_ENTRY(exc_simd_coprocessor_error, false ), 627 + #ifdef CONFIG_X86_KERNEL_IBT 628 + TRAP_ENTRY(exc_control_protection, false ), 629 + #endif 627 630 }; 628 631 629 632 static bool __ref get_trap_addr(void **addr, unsigned int ist) ··· 1180 1177 x86_platform.legacy.rtc = 0; 1181 1178 } 1182 1179 1180 + extern void early_xen_iret_patch(void); 1181 + 1183 1182 /* First C function to be called on Xen boot */ 1184 1183 asmlinkage __visible void __init xen_start_kernel(void) 1185 1184 { ··· 1192 1187 if (!xen_start_info) 1193 1188 return; 1194 1189 1190 + __text_gen_insn(&early_xen_iret_patch, 1191 + JMP32_INSN_OPCODE, &early_xen_iret_patch, &xen_iret, 1192 + JMP32_INSN_SIZE); 1193 + 1195 1194 xen_domain_type = XEN_PV_DOMAIN; 1196 1195 xen_start_flags = xen_start_info->flags; 1197 1196 ··· 1204 1195 /* Install Xen paravirt ops */ 1205 1196 pv_info = xen_info; 1206 1197 pv_ops.cpu = xen_cpu_ops.cpu; 1207 - paravirt_iret = xen_iret; 1208 1198 xen_init_irq_ops(); 1209 1199 1210 1200 /*
+10
arch/x86/xen/xen-asm.S
··· 122 122 .macro xen_pv_trap name 123 123 SYM_CODE_START(xen_\name) 124 124 UNWIND_HINT_EMPTY 125 + ENDBR 125 126 pop %rcx 126 127 pop %r11 127 128 jmp \name ··· 148 147 xen_pv_trap asm_exc_spurious_interrupt_bug 149 148 xen_pv_trap asm_exc_coprocessor_error 150 149 xen_pv_trap asm_exc_alignment_check 150 + #ifdef CONFIG_X86_KERNEL_IBT 151 + xen_pv_trap asm_exc_control_protection 152 + #endif 151 153 #ifdef CONFIG_X86_MCE 152 154 xen_pv_trap asm_xenpv_exc_machine_check 153 155 #endif /* CONFIG_X86_MCE */ ··· 166 162 i = 0 167 163 .rept NUM_EXCEPTION_VECTORS 168 164 UNWIND_HINT_EMPTY 165 + ENDBR 169 166 pop %rcx 170 167 pop %r11 171 168 jmp early_idt_handler_array + i*EARLY_IDT_HANDLER_SIZE ··· 194 189 */ 195 190 SYM_CODE_START(xen_iret) 196 191 UNWIND_HINT_EMPTY 192 + ANNOTATE_NOENDBR 197 193 pushq $0 198 194 jmp hypercall_iret 199 195 SYM_CODE_END(xen_iret) ··· 236 230 /* Normal 64-bit system call target */ 237 231 SYM_CODE_START(xen_syscall_target) 238 232 UNWIND_HINT_EMPTY 233 + ENDBR 239 234 popq %rcx 240 235 popq %r11 241 236 ··· 256 249 /* 32-bit compat syscall target */ 257 250 SYM_CODE_START(xen_syscall32_target) 258 251 UNWIND_HINT_EMPTY 252 + ENDBR 259 253 popq %rcx 260 254 popq %r11 261 255 ··· 274 266 /* 32-bit compat sysenter target */ 275 267 SYM_CODE_START(xen_sysenter_target) 276 268 UNWIND_HINT_EMPTY 269 + ENDBR 277 270 /* 278 271 * NB: Xen is polite and clears TF from EFLAGS for us. This means 279 272 * that we don't need to guard against single step exceptions here. ··· 298 289 SYM_CODE_START(xen_syscall32_target) 299 290 SYM_CODE_START(xen_sysenter_target) 300 291 UNWIND_HINT_EMPTY 292 + ENDBR 301 293 lea 16(%rsp), %rsp /* strip %rcx, %r11 */ 302 294 mov $-ENOSYS, %rax 303 295 pushq $0
+7 -2
arch/x86/xen/xen-head.S
··· 25 25 SYM_CODE_START(hypercall_page) 26 26 .rept (PAGE_SIZE / 32) 27 27 UNWIND_HINT_FUNC 28 - .skip 31, 0x90 29 - RET 28 + ANNOTATE_NOENDBR 29 + ret 30 + /* 31 + * Xen will write the hypercall page, and sort out ENDBR. 32 + */ 33 + .skip 31, 0xcc 30 34 .endr 31 35 32 36 #define HYPERCALL(n) \ ··· 78 74 .pushsection .text 79 75 SYM_CODE_START(asm_cpu_bringup_and_idle) 80 76 UNWIND_HINT_EMPTY 77 + ENDBR 81 78 82 79 call cpu_bringup_and_idle 83 80 SYM_CODE_END(asm_cpu_bringup_and_idle)
+1 -1
fs/fuse/ioctl.c
··· 170 170 #else 171 171 if (flags & FUSE_IOCTL_COMPAT) { 172 172 inarg.flags |= FUSE_IOCTL_32BIT; 173 - #ifdef CONFIG_X86_X32 173 + #ifdef CONFIG_X86_X32_ABI 174 174 if (in_x32_syscall()) 175 175 inarg.flags |= FUSE_IOCTL_COMPAT_X32; 176 176 #endif
+1 -1
fs/xfs/xfs_ioctl32.c
··· 217 217 inumbers_fmt_pf inumbers_func = xfs_fsinumbers_fmt_compat; 218 218 bulkstat_one_fmt_pf bs_one_func = xfs_fsbulkstat_one_fmt_compat; 219 219 220 - #ifdef CONFIG_X86_X32 220 + #ifdef CONFIG_X86_X32_ABI 221 221 if (in_x32_syscall()) { 222 222 /* 223 223 * ... but on x32 the input xfs_fsop_bulkreq has pointers
+4
include/asm-generic/vmlinux.lds.h
··· 394 394 KEEP(*(__jump_table)) \ 395 395 __stop___jump_table = .; 396 396 397 + #ifdef CONFIG_HAVE_STATIC_CALL_INLINE 397 398 #define STATIC_CALL_DATA \ 398 399 . = ALIGN(8); \ 399 400 __start_static_call_sites = .; \ ··· 403 402 __start_static_call_tramp_key = .; \ 404 403 KEEP(*(.static_call_tramp_key)) \ 405 404 __stop_static_call_tramp_key = .; 405 + #else 406 + #define STATIC_CALL_DATA 407 + #endif 406 408 407 409 /* 408 410 * Allow architectures to handle ro_after_init data on their
+10 -1
include/linux/cfi.h
··· 34 34 35 35 #else /* !CONFIG_CFI_CLANG */ 36 36 37 - #define __CFI_ADDRESSABLE(fn, __attr) 37 + #ifdef CONFIG_X86_KERNEL_IBT 38 + 39 + #define __CFI_ADDRESSABLE(fn, __attr) \ 40 + const void *__cfi_jt_ ## fn __visible __attr = (void *)&fn 41 + 42 + #endif /* CONFIG_X86_KERNEL_IBT */ 38 43 39 44 #endif /* CONFIG_CFI_CLANG */ 45 + 46 + #ifndef __CFI_ADDRESSABLE 47 + #define __CFI_ADDRESSABLE(fn, __attr) 48 + #endif 40 49 41 50 #endif /* _LINUX_CFI_H */
-7
include/linux/compiler.h
··· 125 125 }) 126 126 #define annotate_unreachable() __annotate_unreachable(__COUNTER__) 127 127 128 - #define ASM_REACHABLE \ 129 - "998:\n\t" \ 130 - ".pushsection .discard.reachable\n\t" \ 131 - ".long 998b - .\n\t" \ 132 - ".popsection\n\t" 133 - 134 128 /* Annotate a C jump table to allow objtool to follow the code flow */ 135 129 #define __annotate_jump_table __section(".rodata..c_jump_table") 136 130 137 131 #else 138 132 #define annotate_unreachable() 139 - # define ASM_REACHABLE 140 133 #define __annotate_jump_table 141 134 #endif 142 135
+1 -1
include/linux/cred.h
··· 176 176 * check for validity of credentials 177 177 */ 178 178 #ifdef CONFIG_DEBUG_CREDENTIALS 179 - extern void __invalid_creds(const struct cred *, const char *, unsigned); 179 + extern void __noreturn __invalid_creds(const struct cred *, const char *, unsigned); 180 180 extern void __validate_process_creds(struct task_struct *, 181 181 const char *, unsigned); 182 182
+2 -1
include/linux/kprobes.h
··· 265 265 extern void kprobes_inc_nmissed_count(struct kprobe *p); 266 266 extern bool arch_within_kprobe_blacklist(unsigned long addr); 267 267 extern int arch_populate_kprobe_blacklist(void); 268 - extern bool arch_kprobe_on_func_entry(unsigned long offset); 269 268 extern int kprobe_on_func_entry(kprobe_opcode_t *addr, const char *sym, unsigned long offset); 270 269 271 270 extern bool within_kprobe_blacklist(unsigned long addr); ··· 383 384 } 384 385 385 386 kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset); 387 + kprobe_opcode_t *arch_adjust_kprobe_addr(unsigned long addr, unsigned long offset, bool *on_func_entry); 388 + 386 389 int register_kprobe(struct kprobe *p); 387 390 void unregister_kprobe(struct kprobe *p); 388 391 int register_kprobes(struct kprobe **kps, int num);
+32
include/linux/objtool.h
··· 77 77 #define STACK_FRAME_NON_STANDARD_FP(func) 78 78 #endif 79 79 80 + #define ANNOTATE_NOENDBR \ 81 + "986: \n\t" \ 82 + ".pushsection .discard.noendbr\n\t" \ 83 + _ASM_PTR " 986b\n\t" \ 84 + ".popsection\n\t" 85 + 86 + #define ASM_REACHABLE \ 87 + "998:\n\t" \ 88 + ".pushsection .discard.reachable\n\t" \ 89 + ".long 998b - .\n\t" \ 90 + ".popsection\n\t" 91 + 80 92 #else /* __ASSEMBLY__ */ 81 93 82 94 /* ··· 141 129 .popsection 142 130 .endm 143 131 132 + .macro ANNOTATE_NOENDBR 133 + .Lhere_\@: 134 + .pushsection .discard.noendbr 135 + .quad .Lhere_\@ 136 + .popsection 137 + .endm 138 + 139 + .macro REACHABLE 140 + .Lhere_\@: 141 + .pushsection .discard.reachable 142 + .long .Lhere_\@ - . 143 + .popsection 144 + .endm 145 + 144 146 #endif /* __ASSEMBLY__ */ 145 147 146 148 #else /* !CONFIG_STACK_VALIDATION */ ··· 165 139 "\n\t" 166 140 #define STACK_FRAME_NON_STANDARD(func) 167 141 #define STACK_FRAME_NON_STANDARD_FP(func) 142 + #define ANNOTATE_NOENDBR 143 + #define ASM_REACHABLE 168 144 #else 169 145 #define ANNOTATE_INTRA_FUNCTION_CALL 170 146 .macro UNWIND_HINT sp_reg:req sp_offset=0 type:req end=0 171 147 .endm 172 148 .macro STACK_FRAME_NON_STANDARD func:req 149 + .endm 150 + .macro ANNOTATE_NOENDBR 151 + .endm 152 + .macro REACHABLE 173 153 .endm 174 154 #endif 175 155
+1 -1
include/linux/sched/task.h
··· 79 79 { 80 80 } 81 81 #endif 82 - extern void do_group_exit(int); 82 + extern __noreturn void do_group_exit(int); 83 83 84 84 extern void exit_files(struct task_struct *); 85 85 extern void exit_itimers(struct signal_struct *);
+4 -16
kernel/bpf/trampoline.c
··· 117 117 tr->mod = NULL; 118 118 } 119 119 120 - static int is_ftrace_location(void *ip) 121 - { 122 - long addr; 123 - 124 - addr = ftrace_location((long)ip); 125 - if (!addr) 126 - return 0; 127 - if (WARN_ON_ONCE(addr != (long)ip)) 128 - return -EFAULT; 129 - return 1; 130 - } 131 - 132 120 static int unregister_fentry(struct bpf_trampoline *tr, void *old_addr) 133 121 { 134 122 void *ip = tr->func.addr; ··· 148 160 static int register_fentry(struct bpf_trampoline *tr, void *new_addr) 149 161 { 150 162 void *ip = tr->func.addr; 163 + unsigned long faddr; 151 164 int ret; 152 165 153 - ret = is_ftrace_location(ip); 154 - if (ret < 0) 155 - return ret; 156 - tr->func.ftrace_managed = ret; 166 + faddr = ftrace_location((unsigned long)ip); 167 + if (faddr) 168 + tr->func.ftrace_managed = true; 157 169 158 170 if (bpf_trampoline_module_get(tr)) 159 171 return -ENOENT;
+1 -1
kernel/cred.c
··· 870 870 /* 871 871 * report use of invalid credentials 872 872 */ 873 - void __invalid_creds(const struct cred *cred, const char *file, unsigned line) 873 + void __noreturn __invalid_creds(const struct cred *cred, const char *file, unsigned line) 874 874 { 875 875 printk(KERN_ERR "CRED: Invalid credentials\n"); 876 876 printk(KERN_ERR "CRED: At %s:%u\n", file, line);
+1 -1
kernel/exit.c
··· 895 895 * Take down every thread in the group. This is called by fatal signals 896 896 * as well as by sys_exit_group (below). 897 897 */ 898 - void 898 + void __noreturn 899 899 do_group_exit(int exit_code) 900 900 { 901 901 struct signal_struct *sig = current->signal;
+54 -20
kernel/kprobes.c
··· 1489 1489 } 1490 1490 1491 1491 /* 1492 + * arch_adjust_kprobe_addr - adjust the address 1493 + * @addr: symbol base address 1494 + * @offset: offset within the symbol 1495 + * @on_func_entry: was this @addr+@offset on the function entry 1496 + * 1497 + * Typically returns @addr + @offset, except for special cases where the 1498 + * function might be prefixed by a CFI landing pad, in that case any offset 1499 + * inside the landing pad is mapped to the first 'real' instruction of the 1500 + * symbol. 1501 + * 1502 + * Specifically, for things like IBT/BTI, skip the resp. ENDBR/BTI.C 1503 + * instruction at +0. 1504 + */ 1505 + kprobe_opcode_t *__weak arch_adjust_kprobe_addr(unsigned long addr, 1506 + unsigned long offset, 1507 + bool *on_func_entry) 1508 + { 1509 + *on_func_entry = !offset; 1510 + return (kprobe_opcode_t *)(addr + offset); 1511 + } 1512 + 1513 + /* 1492 1514 * If 'symbol_name' is specified, look it up and add the 'offset' 1493 1515 * to it. This way, we can specify a relative address to a symbol. 1494 1516 * This returns encoded errors if it fails to look up symbol or invalid 1495 1517 * combination of parameters. 1496 1518 */ 1497 - static kprobe_opcode_t *_kprobe_addr(kprobe_opcode_t *addr, 1498 - const char *symbol_name, unsigned int offset) 1519 + static kprobe_opcode_t * 1520 + _kprobe_addr(kprobe_opcode_t *addr, const char *symbol_name, 1521 + unsigned long offset, bool *on_func_entry) 1499 1522 { 1500 1523 if ((symbol_name && addr) || (!symbol_name && !addr)) 1501 1524 goto invalid; 1502 1525 1503 1526 if (symbol_name) { 1527 + /* 1528 + * Input: @sym + @offset 1529 + * Output: @addr + @offset 1530 + * 1531 + * NOTE: kprobe_lookup_name() does *NOT* fold the offset 1532 + * argument into it's output! 1533 + */ 1504 1534 addr = kprobe_lookup_name(symbol_name, offset); 1505 1535 if (!addr) 1506 1536 return ERR_PTR(-ENOENT); 1507 1537 } 1508 1538 1509 - addr = (kprobe_opcode_t *)(((char *)addr) + offset); 1539 + /* 1540 + * So here we have @addr + @offset, displace it into a new 1541 + * @addr' + @offset' where @addr' is the symbol start address. 1542 + */ 1543 + addr = (void *)addr + offset; 1544 + if (!kallsyms_lookup_size_offset((unsigned long)addr, NULL, &offset)) 1545 + return ERR_PTR(-ENOENT); 1546 + addr = (void *)addr - offset; 1547 + 1548 + /* 1549 + * Then ask the architecture to re-combine them, taking care of 1550 + * magical function entry details while telling us if this was indeed 1551 + * at the start of the function. 1552 + */ 1553 + addr = arch_adjust_kprobe_addr((unsigned long)addr, offset, on_func_entry); 1510 1554 if (addr) 1511 1555 return addr; 1512 1556 ··· 1560 1516 1561 1517 static kprobe_opcode_t *kprobe_addr(struct kprobe *p) 1562 1518 { 1563 - return _kprobe_addr(p->addr, p->symbol_name, p->offset); 1519 + bool on_func_entry; 1520 + return _kprobe_addr(p->addr, p->symbol_name, p->offset, &on_func_entry); 1564 1521 } 1565 1522 1566 1523 /* ··· 1607 1562 1608 1563 static int check_ftrace_location(struct kprobe *p) 1609 1564 { 1610 - unsigned long ftrace_addr; 1565 + unsigned long addr = (unsigned long)p->addr; 1611 1566 1612 - ftrace_addr = ftrace_location((unsigned long)p->addr); 1613 - if (ftrace_addr) { 1567 + if (ftrace_location(addr) == addr) { 1614 1568 #ifdef CONFIG_KPROBES_ON_FTRACE 1615 - /* Given address is not on the instruction boundary */ 1616 - if ((unsigned long)p->addr != ftrace_addr) 1617 - return -EILSEQ; 1618 1569 p->flags |= KPROBE_FLAG_FTRACE; 1619 1570 #else /* !CONFIG_KPROBES_ON_FTRACE */ 1620 1571 return -EINVAL; ··· 2088 2047 } 2089 2048 NOKPROBE_SYMBOL(pre_handler_kretprobe); 2090 2049 2091 - bool __weak arch_kprobe_on_func_entry(unsigned long offset) 2092 - { 2093 - return !offset; 2094 - } 2095 - 2096 2050 /** 2097 2051 * kprobe_on_func_entry() -- check whether given address is function entry 2098 2052 * @addr: Target address ··· 2103 2067 */ 2104 2068 int kprobe_on_func_entry(kprobe_opcode_t *addr, const char *sym, unsigned long offset) 2105 2069 { 2106 - kprobe_opcode_t *kp_addr = _kprobe_addr(addr, sym, offset); 2070 + bool on_func_entry; 2071 + kprobe_opcode_t *kp_addr = _kprobe_addr(addr, sym, offset, &on_func_entry); 2107 2072 2108 2073 if (IS_ERR(kp_addr)) 2109 2074 return PTR_ERR(kp_addr); 2110 2075 2111 - if (!kallsyms_lookup_size_offset((unsigned long)kp_addr, NULL, &offset)) 2112 - return -ENOENT; 2113 - 2114 - if (!arch_kprobe_on_func_entry(offset)) 2076 + if (!on_func_entry) 2115 2077 return -EINVAL; 2116 2078 2117 2079 return 0;
+2 -17
kernel/livepatch/patch.c
··· 124 124 ftrace_test_recursion_unlock(bit); 125 125 } 126 126 127 - /* 128 - * Convert a function address into the appropriate ftrace location. 129 - * 130 - * Usually this is just the address of the function, but on some architectures 131 - * it's more complicated so allow them to provide a custom behaviour. 132 - */ 133 - #ifndef klp_get_ftrace_location 134 - static unsigned long klp_get_ftrace_location(unsigned long faddr) 135 - { 136 - return faddr; 137 - } 138 - #endif 139 - 140 127 static void klp_unpatch_func(struct klp_func *func) 141 128 { 142 129 struct klp_ops *ops; ··· 140 153 if (list_is_singular(&ops->func_stack)) { 141 154 unsigned long ftrace_loc; 142 155 143 - ftrace_loc = 144 - klp_get_ftrace_location((unsigned long)func->old_func); 156 + ftrace_loc = ftrace_location((unsigned long)func->old_func); 145 157 if (WARN_ON(!ftrace_loc)) 146 158 return; 147 159 ··· 172 186 if (!ops) { 173 187 unsigned long ftrace_loc; 174 188 175 - ftrace_loc = 176 - klp_get_ftrace_location((unsigned long)func->old_func); 189 + ftrace_loc = ftrace_location((unsigned long)func->old_func); 177 190 if (!ftrace_loc) { 178 191 pr_err("failed to find location for function '%s'\n", 179 192 func->old_name);
+40 -8
kernel/trace/ftrace.c
··· 1568 1568 } 1569 1569 1570 1570 /** 1571 - * ftrace_location - return true if the ip giving is a traced location 1571 + * ftrace_location - return the ftrace location 1572 1572 * @ip: the instruction pointer to check 1573 1573 * 1574 - * Returns rec->ip if @ip given is a pointer to a ftrace location. 1575 - * That is, the instruction that is either a NOP or call to 1576 - * the function tracer. It checks the ftrace internal tables to 1577 - * determine if the address belongs or not. 1574 + * If @ip matches the ftrace location, return @ip. 1575 + * If @ip matches sym+0, return sym's ftrace location. 1576 + * Otherwise, return 0. 1578 1577 */ 1579 1578 unsigned long ftrace_location(unsigned long ip) 1580 1579 { 1581 - return ftrace_location_range(ip, ip); 1580 + struct dyn_ftrace *rec; 1581 + unsigned long offset; 1582 + unsigned long size; 1583 + 1584 + rec = lookup_rec(ip, ip); 1585 + if (!rec) { 1586 + if (!kallsyms_lookup_size_offset(ip, &size, &offset)) 1587 + goto out; 1588 + 1589 + /* map sym+0 to __fentry__ */ 1590 + if (!offset) 1591 + rec = lookup_rec(ip, ip + size - 1); 1592 + } 1593 + 1594 + if (rec) 1595 + return rec->ip; 1596 + 1597 + out: 1598 + return 0; 1582 1599 } 1583 1600 1584 1601 /** ··· 4979 4962 { 4980 4963 struct ftrace_func_entry *entry; 4981 4964 4982 - if (!ftrace_location(ip)) 4965 + ip = ftrace_location(ip); 4966 + if (!ip) 4983 4967 return -EINVAL; 4984 4968 4985 4969 if (remove) { ··· 5149 5131 struct ftrace_func_entry *entry; 5150 5132 struct ftrace_hash *free_hash = NULL; 5151 5133 struct dyn_ftrace *rec; 5152 - int ret = -EBUSY; 5134 + int ret = -ENODEV; 5153 5135 5154 5136 mutex_lock(&direct_mutex); 5155 5137 5138 + ip = ftrace_location(ip); 5139 + if (!ip) 5140 + goto out_unlock; 5141 + 5156 5142 /* See if there's a direct function at @ip already */ 5143 + ret = -EBUSY; 5157 5144 if (ftrace_find_rec_direct(ip)) 5158 5145 goto out_unlock; 5159 5146 ··· 5265 5242 int ret = -ENODEV; 5266 5243 5267 5244 mutex_lock(&direct_mutex); 5245 + 5246 + ip = ftrace_location(ip); 5247 + if (!ip) 5248 + goto out_unlock; 5268 5249 5269 5250 entry = find_direct_entry(&ip, NULL); 5270 5251 if (!entry) ··· 5402 5375 mutex_lock(&direct_mutex); 5403 5376 5404 5377 mutex_lock(&ftrace_lock); 5378 + 5379 + ip = ftrace_location(ip); 5380 + if (!ip) 5381 + goto out_unlock; 5382 + 5405 5383 entry = find_direct_entry(&ip, &rec); 5406 5384 if (!entry) 5407 5385 goto out_unlock;
+5
samples/ftrace/ftrace-direct-modify.c
··· 24 24 25 25 #ifdef CONFIG_X86_64 26 26 27 + #include <asm/ibt.h> 28 + 27 29 asm ( 28 30 " .pushsection .text, \"ax\", @progbits\n" 29 31 " .type my_tramp1, @function\n" 30 32 " .globl my_tramp1\n" 31 33 " my_tramp1:" 34 + ASM_ENDBR 32 35 " pushq %rbp\n" 33 36 " movq %rsp, %rbp\n" 34 37 " call my_direct_func1\n" 35 38 " leave\n" 36 39 " .size my_tramp1, .-my_tramp1\n" 37 40 ASM_RET 41 + 38 42 " .type my_tramp2, @function\n" 39 43 " .globl my_tramp2\n" 40 44 " my_tramp2:" 45 + ASM_ENDBR 41 46 " pushq %rbp\n" 42 47 " movq %rsp, %rbp\n" 43 48 " call my_direct_func2\n"
+7 -3
samples/ftrace/ftrace-direct-multi-modify.c
··· 22 22 23 23 #ifdef CONFIG_X86_64 24 24 25 + #include <asm/ibt.h> 26 + 25 27 asm ( 26 28 " .pushsection .text, \"ax\", @progbits\n" 27 29 " .type my_tramp1, @function\n" 28 30 " .globl my_tramp1\n" 29 31 " my_tramp1:" 32 + ASM_ENDBR 30 33 " pushq %rbp\n" 31 34 " movq %rsp, %rbp\n" 32 35 " pushq %rdi\n" ··· 37 34 " call my_direct_func1\n" 38 35 " popq %rdi\n" 39 36 " leave\n" 40 - " ret\n" 37 + ASM_RET 41 38 " .size my_tramp1, .-my_tramp1\n" 39 + 42 40 " .type my_tramp2, @function\n" 43 - "\n" 44 41 " .globl my_tramp2\n" 45 42 " my_tramp2:" 43 + ASM_ENDBR 46 44 " pushq %rbp\n" 47 45 " movq %rsp, %rbp\n" 48 46 " pushq %rdi\n" ··· 51 47 " call my_direct_func2\n" 52 48 " popq %rdi\n" 53 49 " leave\n" 54 - " ret\n" 50 + ASM_RET 55 51 " .size my_tramp2, .-my_tramp2\n" 56 52 " .popsection\n" 57 53 );
+4 -1
samples/ftrace/ftrace-direct-multi.c
··· 17 17 18 18 #ifdef CONFIG_X86_64 19 19 20 + #include <asm/ibt.h> 21 + 20 22 asm ( 21 23 " .pushsection .text, \"ax\", @progbits\n" 22 24 " .type my_tramp, @function\n" 23 25 " .globl my_tramp\n" 24 26 " my_tramp:" 27 + ASM_ENDBR 25 28 " pushq %rbp\n" 26 29 " movq %rsp, %rbp\n" 27 30 " pushq %rdi\n" ··· 32 29 " call my_direct_func\n" 33 30 " popq %rdi\n" 34 31 " leave\n" 35 - " ret\n" 32 + ASM_RET 36 33 " .size my_tramp, .-my_tramp\n" 37 34 " .popsection\n" 38 35 );
+3
samples/ftrace/ftrace-direct-too.c
··· 19 19 20 20 #ifdef CONFIG_X86_64 21 21 22 + #include <asm/ibt.h> 23 + 22 24 asm ( 23 25 " .pushsection .text, \"ax\", @progbits\n" 24 26 " .type my_tramp, @function\n" 25 27 " .globl my_tramp\n" 26 28 " my_tramp:" 29 + ASM_ENDBR 27 30 " pushq %rbp\n" 28 31 " movq %rsp, %rbp\n" 29 32 " pushq %rdi\n"
+3
samples/ftrace/ftrace-direct.c
··· 16 16 17 17 #ifdef CONFIG_X86_64 18 18 19 + #include <asm/ibt.h> 20 + 19 21 asm ( 20 22 " .pushsection .text, \"ax\", @progbits\n" 21 23 " .type my_tramp, @function\n" 22 24 " .globl my_tramp\n" 23 25 " my_tramp:" 26 + ASM_ENDBR 24 27 " pushq %rbp\n" 25 28 " movq %rsp, %rbp\n" 26 29 " pushq %rdi\n"
+14 -13
scripts/Makefile.build
··· 88 88 89 89 targets-for-modules := $(patsubst %.o, %.mod, $(filter %.o, $(obj-m))) 90 90 91 - ifdef CONFIG_LTO_CLANG 92 - targets-for-modules += $(patsubst %.o, %.lto.o, $(filter %.o, $(obj-m))) 91 + ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),) 92 + targets-for-modules += $(patsubst %.o, %.prelink.o, $(filter %.o, $(obj-m))) 93 93 endif 94 94 95 95 ifdef need-modorder ··· 230 230 objtool_args = \ 231 231 $(if $(CONFIG_UNWINDER_ORC),orc generate,check) \ 232 232 $(if $(part-of-module), --module) \ 233 + $(if $(CONFIG_X86_KERNEL_IBT), --lto --ibt) \ 233 234 $(if $(CONFIG_FRAME_POINTER),, --no-fp) \ 234 235 $(if $(CONFIG_GCOV_KERNEL)$(CONFIG_LTO_CLANG), --no-unreachable)\ 235 236 $(if $(CONFIG_RETPOLINE), --retpoline) \ ··· 243 242 244 243 endif # CONFIG_STACK_VALIDATION 245 244 246 - ifdef CONFIG_LTO_CLANG 245 + ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),) 247 246 248 247 # Skip objtool for LLVM bitcode 249 248 $(obj)/%.o: objtool-enabled := ··· 289 288 $(call if_changed_rule,cc_o_c) 290 289 $(call cmd,force_checksrc) 291 290 292 - ifdef CONFIG_LTO_CLANG 291 + ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),) 293 292 # Module .o files may contain LLVM bitcode, compile them into native code 294 293 # before ELF processing 295 - quiet_cmd_cc_lto_link_modules = LTO [M] $@ 296 - cmd_cc_lto_link_modules = \ 294 + quiet_cmd_cc_prelink_modules = LD [M] $@ 295 + cmd_cc_prelink_modules = \ 297 296 $(LD) $(ld_flags) -r -o $@ \ 298 - $(shell [ -s $(@:.lto.o=.o.symversions) ] && \ 299 - echo -T $(@:.lto.o=.o.symversions)) \ 297 + $(shell [ -s $(@:.prelink.o=.o.symversions) ] && \ 298 + echo -T $(@:.prelink.o=.o.symversions)) \ 300 299 --whole-archive $(filter-out FORCE,$^) \ 301 300 $(cmd_objtool) 302 301 303 302 # objtool was skipped for LLVM bitcode, run it now that we have compiled 304 303 # modules into native code 305 - $(obj)/%.lto.o: objtool-enabled = y 306 - $(obj)/%.lto.o: part-of-module := y 304 + $(obj)/%.prelink.o: objtool-enabled = y 305 + $(obj)/%.prelink.o: part-of-module := y 307 306 308 - $(obj)/%.lto.o: $(obj)/%.o FORCE 309 - $(call if_changed,cc_lto_link_modules) 307 + $(obj)/%.prelink.o: $(obj)/%.o FORCE 308 + $(call if_changed,cc_prelink_modules) 310 309 endif 311 310 312 311 cmd_mod = { \ ··· 470 469 # Do not replace $(filter %.o,^) with $(real-prereqs). When a single object 471 470 # module is turned into a multi object module, $^ will contain header file 472 471 # dependencies recorded in the .*.cmd file. 473 - ifdef CONFIG_LTO_CLANG 472 + ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),) 474 473 quiet_cmd_link_multi-m = AR [M] $@ 475 474 cmd_link_multi-m = \ 476 475 $(cmd_update_lto_symversions); \
+2 -2
scripts/Makefile.lib
··· 225 225 $(addprefix -I,$(DTC_INCLUDE)) \ 226 226 -undef -D__DTS__ 227 227 228 - ifeq ($(CONFIG_LTO_CLANG),y) 228 + ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),) 229 229 # With CONFIG_LTO_CLANG, .o files in modules might be LLVM bitcode, so we 230 230 # need to run LTO to compile them into native code (.lto.o) before further 231 231 # processing. 232 - mod-prelink-ext := .lto 232 + mod-prelink-ext := .prelink 233 233 endif 234 234 235 235 # Useful for describing the dependency of composite objects
+6 -6
scripts/mod/modpost.c
··· 1996 1996 if (m && (s[n + m] == '.' || s[n + m] == 0)) 1997 1997 s[n] = 0; 1998 1998 1999 - /* strip trailing .lto */ 2000 - if (strends(s, ".lto")) 2001 - s[strlen(s) - 4] = '\0'; 1999 + /* strip trailing .prelink */ 2000 + if (strends(s, ".prelink")) 2001 + s[strlen(s) - 8] = '\0'; 2002 2002 } 2003 2003 return s; 2004 2004 } ··· 2022 2022 /* strip trailing .o */ 2023 2023 tmp = NOFAIL(strdup(modname)); 2024 2024 tmp[strlen(tmp) - 2] = '\0'; 2025 - /* strip trailing .lto */ 2026 - if (strends(tmp, ".lto")) 2027 - tmp[strlen(tmp) - 4] = '\0'; 2025 + /* strip trailing .prelink */ 2026 + if (strends(tmp, ".prelink")) 2027 + tmp[strlen(tmp) - 8] = '\0'; 2028 2028 mod = new_module(tmp); 2029 2029 free(tmp); 2030 2030 }
+8 -8
sound/core/control_compat.c
··· 150 150 unsigned char reserved[128]; 151 151 }; 152 152 153 - #ifdef CONFIG_X86_X32 153 + #ifdef CONFIG_X86_X32_ABI 154 154 /* x32 has a different alignment for 64bit values from ia32 */ 155 155 struct snd_ctl_elem_value_x32 { 156 156 struct snd_ctl_elem_id id; ··· 162 162 } value; 163 163 unsigned char reserved[128]; 164 164 }; 165 - #endif /* CONFIG_X86_X32 */ 165 + #endif /* CONFIG_X86_X32_ABI */ 166 166 167 167 /* get the value type and count of the control */ 168 168 static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id, ··· 347 347 return ctl_elem_write_user(file, data32, &data32->value); 348 348 } 349 349 350 - #ifdef CONFIG_X86_X32 350 + #ifdef CONFIG_X86_X32_ABI 351 351 static int snd_ctl_elem_read_user_x32(struct snd_card *card, 352 352 struct snd_ctl_elem_value_x32 __user *data32) 353 353 { ··· 359 359 { 360 360 return ctl_elem_write_user(file, data32, &data32->value); 361 361 } 362 - #endif /* CONFIG_X86_X32 */ 362 + #endif /* CONFIG_X86_X32_ABI */ 363 363 364 364 /* add or replace a user control */ 365 365 static int snd_ctl_elem_add_compat(struct snd_ctl_file *file, ··· 418 418 SNDRV_CTL_IOCTL_ELEM_WRITE32 = _IOWR('U', 0x13, struct snd_ctl_elem_value32), 419 419 SNDRV_CTL_IOCTL_ELEM_ADD32 = _IOWR('U', 0x17, struct snd_ctl_elem_info32), 420 420 SNDRV_CTL_IOCTL_ELEM_REPLACE32 = _IOWR('U', 0x18, struct snd_ctl_elem_info32), 421 - #ifdef CONFIG_X86_X32 421 + #ifdef CONFIG_X86_X32_ABI 422 422 SNDRV_CTL_IOCTL_ELEM_READ_X32 = _IOWR('U', 0x12, struct snd_ctl_elem_value_x32), 423 423 SNDRV_CTL_IOCTL_ELEM_WRITE_X32 = _IOWR('U', 0x13, struct snd_ctl_elem_value_x32), 424 - #endif /* CONFIG_X86_X32 */ 424 + #endif /* CONFIG_X86_X32_ABI */ 425 425 }; 426 426 427 427 static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) ··· 460 460 return snd_ctl_elem_add_compat(ctl, argp, 0); 461 461 case SNDRV_CTL_IOCTL_ELEM_REPLACE32: 462 462 return snd_ctl_elem_add_compat(ctl, argp, 1); 463 - #ifdef CONFIG_X86_X32 463 + #ifdef CONFIG_X86_X32_ABI 464 464 case SNDRV_CTL_IOCTL_ELEM_READ_X32: 465 465 return snd_ctl_elem_read_user_x32(ctl->card, argp); 466 466 case SNDRV_CTL_IOCTL_ELEM_WRITE_X32: 467 467 return snd_ctl_elem_write_user_x32(ctl, argp); 468 - #endif /* CONFIG_X86_X32 */ 468 + #endif /* CONFIG_X86_X32_ABI */ 469 469 } 470 470 471 471 down_read(&snd_ioctl_rwsem);
+10 -10
sound/core/pcm_compat.c
··· 147 147 return err; 148 148 } 149 149 150 - #ifdef CONFIG_X86_X32 150 + #ifdef CONFIG_X86_X32_ABI 151 151 /* X32 ABI has the same struct as x86-64 for snd_pcm_channel_info */ 152 152 static int snd_pcm_channel_info_user(struct snd_pcm_substream *substream, 153 153 struct snd_pcm_channel_info __user *src); 154 154 #define snd_pcm_ioctl_channel_info_x32(s, p) \ 155 155 snd_pcm_channel_info_user(s, p) 156 - #endif /* CONFIG_X86_X32 */ 156 + #endif /* CONFIG_X86_X32_ABI */ 157 157 158 158 struct compat_snd_pcm_status64 { 159 159 snd_pcm_state_t state; ··· 375 375 return err; 376 376 } 377 377 378 - #ifdef CONFIG_X86_X32 378 + #ifdef CONFIG_X86_X32_ABI 379 379 /* X32 ABI has 64bit timespec and 64bit alignment */ 380 380 struct snd_pcm_mmap_status_x32 { 381 381 snd_pcm_state_t state; ··· 468 468 469 469 return 0; 470 470 } 471 - #endif /* CONFIG_X86_X32 */ 471 + #endif /* CONFIG_X86_X32_ABI */ 472 472 473 473 #ifdef __BIG_ENDIAN 474 474 typedef char __pad_before_u32[4]; ··· 560 560 SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct snd_xfern32), 561 561 SNDRV_PCM_IOCTL_STATUS_COMPAT64 = _IOR('A', 0x20, struct compat_snd_pcm_status64), 562 562 SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT64 = _IOWR('A', 0x24, struct compat_snd_pcm_status64), 563 - #ifdef CONFIG_X86_X32 563 + #ifdef CONFIG_X86_X32_ABI 564 564 SNDRV_PCM_IOCTL_CHANNEL_INFO_X32 = _IOR('A', 0x32, struct snd_pcm_channel_info), 565 565 SNDRV_PCM_IOCTL_SYNC_PTR_X32 = _IOWR('A', 0x23, struct snd_pcm_sync_ptr_x32), 566 - #endif /* CONFIG_X86_X32 */ 566 + #endif /* CONFIG_X86_X32_ABI */ 567 567 }; 568 568 569 569 static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) ··· 607 607 case __SNDRV_PCM_IOCTL_SYNC_PTR32: 608 608 return snd_pcm_common_ioctl(file, substream, cmd, argp); 609 609 case __SNDRV_PCM_IOCTL_SYNC_PTR64: 610 - #ifdef CONFIG_X86_X32 610 + #ifdef CONFIG_X86_X32_ABI 611 611 if (in_x32_syscall()) 612 612 return snd_pcm_ioctl_sync_ptr_x32(substream, argp); 613 - #endif /* CONFIG_X86_X32 */ 613 + #endif /* CONFIG_X86_X32_ABI */ 614 614 return snd_pcm_ioctl_sync_ptr_buggy(substream, argp); 615 615 case SNDRV_PCM_IOCTL_HW_REFINE32: 616 616 return snd_pcm_ioctl_hw_params_compat(substream, 1, argp); ··· 642 642 return snd_pcm_status_user_compat64(substream, argp, false); 643 643 case SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT64: 644 644 return snd_pcm_status_user_compat64(substream, argp, true); 645 - #ifdef CONFIG_X86_X32 645 + #ifdef CONFIG_X86_X32_ABI 646 646 case SNDRV_PCM_IOCTL_CHANNEL_INFO_X32: 647 647 return snd_pcm_ioctl_channel_info_x32(substream, argp); 648 - #endif /* CONFIG_X86_X32 */ 648 + #endif /* CONFIG_X86_X32_ABI */ 649 649 } 650 650 651 651 return -ENOIOCTLCMD;
+32
tools/include/linux/objtool.h
··· 77 77 #define STACK_FRAME_NON_STANDARD_FP(func) 78 78 #endif 79 79 80 + #define ANNOTATE_NOENDBR \ 81 + "986: \n\t" \ 82 + ".pushsection .discard.noendbr\n\t" \ 83 + _ASM_PTR " 986b\n\t" \ 84 + ".popsection\n\t" 85 + 86 + #define ASM_REACHABLE \ 87 + "998:\n\t" \ 88 + ".pushsection .discard.reachable\n\t" \ 89 + ".long 998b - .\n\t" \ 90 + ".popsection\n\t" 91 + 80 92 #else /* __ASSEMBLY__ */ 81 93 82 94 /* ··· 141 129 .popsection 142 130 .endm 143 131 132 + .macro ANNOTATE_NOENDBR 133 + .Lhere_\@: 134 + .pushsection .discard.noendbr 135 + .quad .Lhere_\@ 136 + .popsection 137 + .endm 138 + 139 + .macro REACHABLE 140 + .Lhere_\@: 141 + .pushsection .discard.reachable 142 + .long .Lhere_\@ - . 143 + .popsection 144 + .endm 145 + 144 146 #endif /* __ASSEMBLY__ */ 145 147 146 148 #else /* !CONFIG_STACK_VALIDATION */ ··· 165 139 "\n\t" 166 140 #define STACK_FRAME_NON_STANDARD(func) 167 141 #define STACK_FRAME_NON_STANDARD_FP(func) 142 + #define ANNOTATE_NOENDBR 143 + #define ASM_REACHABLE 168 144 #else 169 145 #define ANNOTATE_INTRA_FUNCTION_CALL 170 146 .macro UNWIND_HINT sp_reg:req sp_offset=0 type:req end=0 171 147 .endm 172 148 .macro STACK_FRAME_NON_STANDARD func:req 149 + .endm 150 + .macro ANNOTATE_NOENDBR 151 + .endm 152 + .macro REACHABLE 173 153 .endm 174 154 #endif 175 155
+29 -5
tools/objtool/arch/x86/decode.c
··· 103 103 #define rm_is_mem(reg) (mod_is_mem() && !is_RIP() && rm_is(reg)) 104 104 #define rm_is_reg(reg) (mod_is_reg() && modrm_rm == (reg)) 105 105 106 + static bool has_notrack_prefix(struct insn *insn) 107 + { 108 + int i; 109 + 110 + for (i = 0; i < insn->prefixes.nbytes; i++) { 111 + if (insn->prefixes.bytes[i] == 0x3e) 112 + return true; 113 + } 114 + 115 + return false; 116 + } 117 + 106 118 int arch_decode_instruction(struct objtool_file *file, const struct section *sec, 107 119 unsigned long offset, unsigned int maxlen, 108 120 unsigned int *len, enum insn_type *type, ··· 124 112 const struct elf *elf = file->elf; 125 113 struct insn insn; 126 114 int x86_64, ret; 127 - unsigned char op1, op2, op3, 115 + unsigned char op1, op2, op3, prefix, 128 116 rex = 0, rex_b = 0, rex_r = 0, rex_w = 0, rex_x = 0, 129 117 modrm = 0, modrm_mod = 0, modrm_rm = 0, modrm_reg = 0, 130 118 sib = 0, /* sib_scale = 0, */ sib_index = 0, sib_base = 0; ··· 148 136 149 137 if (insn.vex_prefix.nbytes) 150 138 return 0; 139 + 140 + prefix = insn.prefixes.bytes[0]; 151 141 152 142 op1 = insn.opcode.bytes[0]; 153 143 op2 = insn.opcode.bytes[1]; ··· 506 492 /* nopl/nopw */ 507 493 *type = INSN_NOP; 508 494 495 + } else if (op2 == 0x1e) { 496 + 497 + if (prefix == 0xf3 && (modrm == 0xfa || modrm == 0xfb)) 498 + *type = INSN_ENDBR; 499 + 500 + 509 501 } else if (op2 == 0x38 && op3 == 0xf8) { 510 502 if (insn.prefixes.nbytes == 1 && 511 503 insn.prefixes.bytes[0] == 0xf2) { ··· 656 636 break; 657 637 658 638 case 0xff: 659 - if (modrm_reg == 2 || modrm_reg == 3) 639 + if (modrm_reg == 2 || modrm_reg == 3) { 660 640 661 641 *type = INSN_CALL_DYNAMIC; 642 + if (has_notrack_prefix(&insn)) 643 + WARN("notrack prefix found at %s:0x%lx", sec->name, offset); 662 644 663 - else if (modrm_reg == 4) 645 + } else if (modrm_reg == 4) { 664 646 665 647 *type = INSN_JUMP_DYNAMIC; 648 + if (has_notrack_prefix(&insn)) 649 + WARN("notrack prefix found at %s:0x%lx", sec->name, offset); 666 650 667 - else if (modrm_reg == 5) 651 + } else if (modrm_reg == 5) { 668 652 669 653 /* jmpf */ 670 654 *type = INSN_CONTEXT_SWITCH; 671 655 672 - else if (modrm_reg == 6) { 656 + } else if (modrm_reg == 6) { 673 657 674 658 /* push from mem */ 675 659 ADD_OP(op) {
+5 -2
tools/objtool/builtin-check.c
··· 20 20 #include <objtool/objtool.h> 21 21 22 22 bool no_fp, no_unreachable, retpoline, module, backtrace, uaccess, stats, 23 - validate_dup, vmlinux, mcount, noinstr, backup, sls; 23 + lto, vmlinux, mcount, noinstr, backup, sls, dryrun, 24 + ibt; 24 25 25 26 static const char * const check_usage[] = { 26 27 "objtool check [<options>] file.o", ··· 41 40 OPT_BOOLEAN('b', "backtrace", &backtrace, "unwind on error"), 42 41 OPT_BOOLEAN('a', "uaccess", &uaccess, "enable uaccess checking"), 43 42 OPT_BOOLEAN('s', "stats", &stats, "print statistics"), 44 - OPT_BOOLEAN('d', "duplicate", &validate_dup, "duplicate validation for vmlinux.o"), 43 + OPT_BOOLEAN(0, "lto", &lto, "whole-archive like runs"), 45 44 OPT_BOOLEAN('n', "noinstr", &noinstr, "noinstr validation for vmlinux.o"), 46 45 OPT_BOOLEAN('l', "vmlinux", &vmlinux, "vmlinux.o validation"), 47 46 OPT_BOOLEAN('M', "mcount", &mcount, "generate __mcount_loc"), 48 47 OPT_BOOLEAN('B', "backup", &backup, "create .orig files before modification"), 49 48 OPT_BOOLEAN('S', "sls", &sls, "validate straight-line-speculation"), 49 + OPT_BOOLEAN(0, "dry-run", &dryrun, "don't write the modifications"), 50 + OPT_BOOLEAN(0, "ibt", &ibt, "validate ENDBR placement"), 50 51 OPT_END(), 51 52 }; 52 53
+376 -24
tools/objtool/check.c
··· 181 181 "kunit_try_catch_throw", 182 182 "xen_start_kernel", 183 183 "cpu_bringup_and_idle", 184 + "do_group_exit", 185 + "stop_this_cpu", 186 + "__invalid_creds", 184 187 }; 185 188 186 189 if (!func) ··· 383 380 memset(insn, 0, sizeof(*insn)); 384 381 INIT_LIST_HEAD(&insn->alts); 385 382 INIT_LIST_HEAD(&insn->stack_ops); 383 + INIT_LIST_HEAD(&insn->call_node); 386 384 387 385 insn->sec = sec; 388 386 insn->offset = offset; ··· 395 391 &insn->stack_ops); 396 392 if (ret) 397 393 goto err; 394 + 395 + /* 396 + * By default, "ud2" is a dead end unless otherwise 397 + * annotated, because GCC 7 inserts it for certain 398 + * divide-by-zero cases. 399 + */ 400 + if (insn->type == INSN_BUG) 401 + insn->dead_end = true; 398 402 399 403 hash_add(file->insn_hash, &insn->hash, sec_offset_hash(sec, insn->offset)); 400 404 list_add_tail(&insn->list, &file->insn_list); ··· 419 407 return -1; 420 408 } 421 409 422 - sym_for_each_insn(file, func, insn) 410 + sym_for_each_insn(file, func, insn) { 423 411 insn->func = func; 412 + if (insn->type == INSN_ENDBR && list_empty(&insn->call_node)) { 413 + if (insn->offset == insn->func->offset) { 414 + list_add_tail(&insn->call_node, &file->endbr_list); 415 + file->nr_endbr++; 416 + } else { 417 + file->nr_endbr_int++; 418 + } 419 + } 420 + } 424 421 } 425 422 } 426 423 ··· 540 519 struct section *sec; 541 520 struct reloc *reloc; 542 521 struct instruction *insn; 543 - 544 - /* 545 - * By default, "ud2" is a dead end unless otherwise annotated, because 546 - * GCC 7 inserts it for certain divide-by-zero cases. 547 - */ 548 - for_each_insn(file, insn) 549 - if (insn->type == INSN_BUG) 550 - insn->dead_end = true; 551 522 552 523 /* 553 524 * Check for manually annotated dead ends. ··· 735 722 R_X86_64_PC32, 736 723 insn->sec, insn->offset)) { 737 724 WARN("elf_add_reloc_to_insn: .retpoline_sites"); 725 + return -1; 726 + } 727 + 728 + idx++; 729 + } 730 + 731 + return 0; 732 + } 733 + 734 + static int create_ibt_endbr_seal_sections(struct objtool_file *file) 735 + { 736 + struct instruction *insn; 737 + struct section *sec; 738 + int idx; 739 + 740 + sec = find_section_by_name(file->elf, ".ibt_endbr_seal"); 741 + if (sec) { 742 + WARN("file already has .ibt_endbr_seal, skipping"); 743 + return 0; 744 + } 745 + 746 + idx = 0; 747 + list_for_each_entry(insn, &file->endbr_list, call_node) 748 + idx++; 749 + 750 + if (stats) { 751 + printf("ibt: ENDBR at function start: %d\n", file->nr_endbr); 752 + printf("ibt: ENDBR inside functions: %d\n", file->nr_endbr_int); 753 + printf("ibt: superfluous ENDBR: %d\n", idx); 754 + } 755 + 756 + if (!idx) 757 + return 0; 758 + 759 + sec = elf_create_section(file->elf, ".ibt_endbr_seal", 0, 760 + sizeof(int), idx); 761 + if (!sec) { 762 + WARN("elf_create_section: .ibt_endbr_seal"); 763 + return -1; 764 + } 765 + 766 + idx = 0; 767 + list_for_each_entry(insn, &file->endbr_list, call_node) { 768 + 769 + int *site = (int *)sec->data->d_buf + idx; 770 + *site = 0; 771 + 772 + if (elf_add_reloc_to_insn(file->elf, sec, 773 + idx * sizeof(int), 774 + R_X86_64_PC32, 775 + insn->sec, insn->offset)) { 776 + WARN("elf_add_reloc_to_insn: .ibt_endbr_seal"); 738 777 return -1; 739 778 } 740 779 ··· 1176 1111 list_add_tail(&insn->call_node, &file->mcount_loc_list); 1177 1112 return; 1178 1113 } 1114 + 1115 + if (!sibling && dead_end_function(file, sym)) 1116 + insn->dead_end = true; 1179 1117 } 1180 1118 1181 1119 static void add_call_dest(struct objtool_file *file, struct instruction *insn, ··· 1233 1165 1234 1166 annotate_call_site(file, insn, false); 1235 1167 } 1168 + 1169 + static bool same_function(struct instruction *insn1, struct instruction *insn2) 1170 + { 1171 + return insn1->func->pfunc == insn2->func->pfunc; 1172 + } 1173 + 1174 + static bool is_first_func_insn(struct instruction *insn) 1175 + { 1176 + return insn->offset == insn->func->offset || 1177 + (insn->type == INSN_ENDBR && 1178 + insn->offset == insn->func->offset + insn->len); 1179 + } 1180 + 1236 1181 /* 1237 1182 * Find the destination instructions for all jumps. 1238 1183 */ ··· 1326 1245 insn->func->cfunc = insn->jump_dest->func; 1327 1246 insn->jump_dest->func->pfunc = insn->func; 1328 1247 1329 - } else if (insn->jump_dest->func->pfunc != insn->func->pfunc && 1330 - insn->jump_dest->offset == insn->jump_dest->func->offset) { 1248 + } else if (!same_function(insn, insn->jump_dest) && 1249 + is_first_func_insn(insn->jump_dest)) { 1331 1250 /* internal sibling call (without reloc) */ 1332 1251 add_call_dest(file, insn, insn->jump_dest->func, true); 1333 1252 } ··· 1917 1836 1918 1837 insn->hint = true; 1919 1838 1839 + if (ibt && hint->type == UNWIND_HINT_TYPE_REGS_PARTIAL) { 1840 + struct symbol *sym = find_symbol_by_offset(insn->sec, insn->offset); 1841 + 1842 + if (sym && sym->bind == STB_GLOBAL && 1843 + insn->type != INSN_ENDBR && !insn->noendbr) { 1844 + WARN_FUNC("UNWIND_HINT_IRET_REGS without ENDBR", 1845 + insn->sec, insn->offset); 1846 + } 1847 + } 1848 + 1920 1849 if (hint->type == UNWIND_HINT_TYPE_FUNC) { 1921 1850 insn->cfi = &func_cfi; 1922 1851 continue; ··· 1946 1855 cfi.end = hint->end; 1947 1856 1948 1857 insn->cfi = cfi_hash_find_or_add(&cfi); 1858 + } 1859 + 1860 + return 0; 1861 + } 1862 + 1863 + static int read_noendbr_hints(struct objtool_file *file) 1864 + { 1865 + struct section *sec; 1866 + struct instruction *insn; 1867 + struct reloc *reloc; 1868 + 1869 + sec = find_section_by_name(file->elf, ".rela.discard.noendbr"); 1870 + if (!sec) 1871 + return 0; 1872 + 1873 + list_for_each_entry(reloc, &sec->reloc_list, list) { 1874 + insn = find_insn(file, reloc->sym->sec, reloc->sym->offset + reloc->addend); 1875 + if (!insn) { 1876 + WARN("bad .discard.noendbr entry"); 1877 + return -1; 1878 + } 1879 + 1880 + if (insn->type == INSN_ENDBR) 1881 + WARN_FUNC("ANNOTATE_NOENDBR on ENDBR", insn->sec, insn->offset); 1882 + 1883 + insn->noendbr = 1; 1949 1884 } 1950 1885 1951 1886 return 0; ··· 2203 2086 if (ret) 2204 2087 return ret; 2205 2088 2206 - ret = add_dead_ends(file); 2207 - if (ret) 2208 - return ret; 2209 - 2210 2089 add_ignores(file); 2211 2090 add_uaccess_safe(file); 2212 2091 2213 2092 ret = add_ignore_alternatives(file); 2093 + if (ret) 2094 + return ret; 2095 + 2096 + /* 2097 + * Must be before read_unwind_hints() since that needs insn->noendbr. 2098 + */ 2099 + ret = read_noendbr_hints(file); 2214 2100 if (ret) 2215 2101 return ret; 2216 2102 ··· 2245 2125 return ret; 2246 2126 2247 2127 ret = add_call_destinations(file); 2128 + if (ret) 2129 + return ret; 2130 + 2131 + /* 2132 + * Must be after add_call_destinations() such that it can override 2133 + * dead_end_function() marks. 2134 + */ 2135 + ret = add_dead_ends(file); 2248 2136 if (ret) 2249 2137 return ret; 2250 2138 ··· 3154 3026 return next_insn_same_sec(file, insn); 3155 3027 } 3156 3028 3029 + static struct instruction * 3030 + validate_ibt_reloc(struct objtool_file *file, struct reloc *reloc) 3031 + { 3032 + struct instruction *dest; 3033 + struct section *sec; 3034 + unsigned long off; 3035 + 3036 + sec = reloc->sym->sec; 3037 + off = reloc->sym->offset; 3038 + 3039 + if ((reloc->sec->base->sh.sh_flags & SHF_EXECINSTR) && 3040 + (reloc->type == R_X86_64_PC32 || reloc->type == R_X86_64_PLT32)) 3041 + off += arch_dest_reloc_offset(reloc->addend); 3042 + else 3043 + off += reloc->addend; 3044 + 3045 + dest = find_insn(file, sec, off); 3046 + if (!dest) 3047 + return NULL; 3048 + 3049 + if (dest->type == INSN_ENDBR) { 3050 + if (!list_empty(&dest->call_node)) 3051 + list_del_init(&dest->call_node); 3052 + 3053 + return NULL; 3054 + } 3055 + 3056 + if (reloc->sym->static_call_tramp) 3057 + return NULL; 3058 + 3059 + return dest; 3060 + } 3061 + 3062 + static void warn_noendbr(const char *msg, struct section *sec, unsigned long offset, 3063 + struct instruction *dest) 3064 + { 3065 + WARN_FUNC("%srelocation to !ENDBR: %s+0x%lx", sec, offset, msg, 3066 + dest->func ? dest->func->name : dest->sec->name, 3067 + dest->func ? dest->offset - dest->func->offset : dest->offset); 3068 + } 3069 + 3070 + static void validate_ibt_dest(struct objtool_file *file, struct instruction *insn, 3071 + struct instruction *dest) 3072 + { 3073 + if (dest->func && dest->func == insn->func) { 3074 + /* 3075 + * Anything from->to self is either _THIS_IP_ or IRET-to-self. 3076 + * 3077 + * There is no sane way to annotate _THIS_IP_ since the compiler treats the 3078 + * relocation as a constant and is happy to fold in offsets, skewing any 3079 + * annotation we do, leading to vast amounts of false-positives. 3080 + * 3081 + * There's also compiler generated _THIS_IP_ through KCOV and 3082 + * such which we have no hope of annotating. 3083 + * 3084 + * As such, blanket accept self-references without issue. 3085 + */ 3086 + return; 3087 + } 3088 + 3089 + if (dest->noendbr) 3090 + return; 3091 + 3092 + warn_noendbr("", insn->sec, insn->offset, dest); 3093 + } 3094 + 3095 + static void validate_ibt_insn(struct objtool_file *file, struct instruction *insn) 3096 + { 3097 + struct instruction *dest; 3098 + struct reloc *reloc; 3099 + 3100 + switch (insn->type) { 3101 + case INSN_CALL: 3102 + case INSN_CALL_DYNAMIC: 3103 + case INSN_JUMP_CONDITIONAL: 3104 + case INSN_JUMP_UNCONDITIONAL: 3105 + case INSN_JUMP_DYNAMIC: 3106 + case INSN_JUMP_DYNAMIC_CONDITIONAL: 3107 + case INSN_RETURN: 3108 + /* 3109 + * We're looking for code references setting up indirect code 3110 + * flow. As such, ignore direct code flow and the actual 3111 + * dynamic branches. 3112 + */ 3113 + return; 3114 + 3115 + case INSN_NOP: 3116 + /* 3117 + * handle_group_alt() will create INSN_NOP instruction that 3118 + * don't belong to any section, ignore all NOP since they won't 3119 + * carry a (useful) relocation anyway. 3120 + */ 3121 + return; 3122 + 3123 + default: 3124 + break; 3125 + } 3126 + 3127 + for (reloc = insn_reloc(file, insn); 3128 + reloc; 3129 + reloc = find_reloc_by_dest_range(file->elf, insn->sec, 3130 + reloc->offset + 1, 3131 + (insn->offset + insn->len) - (reloc->offset + 1))) { 3132 + dest = validate_ibt_reloc(file, reloc); 3133 + if (dest) 3134 + validate_ibt_dest(file, insn, dest); 3135 + } 3136 + } 3137 + 3157 3138 /* 3158 3139 * Follow the branch starting at the given instruction, and recursively follow 3159 3140 * any other branches (jumps). Meanwhile, track the frame pointer state at ··· 3352 3115 switch (insn->type) { 3353 3116 3354 3117 case INSN_RETURN: 3355 - if (next_insn && next_insn->type == INSN_TRAP) { 3356 - next_insn->ignore = true; 3357 - } else if (sls && !insn->retpoline_safe) { 3118 + if (sls && !insn->retpoline_safe && 3119 + next_insn && next_insn->type != INSN_TRAP) { 3358 3120 WARN_FUNC("missing int3 after ret", 3359 3121 insn->sec, insn->offset); 3360 3122 } ··· 3372 3136 return 1; 3373 3137 } 3374 3138 3375 - if (dead_end_function(file, insn->call_dest)) 3139 + if (insn->dead_end) 3376 3140 return 0; 3377 3141 3378 3142 break; ··· 3400 3164 break; 3401 3165 3402 3166 case INSN_JUMP_DYNAMIC: 3403 - if (next_insn && next_insn->type == INSN_TRAP) { 3404 - next_insn->ignore = true; 3405 - } else if (sls && !insn->retpoline_safe) { 3167 + if (sls && !insn->retpoline_safe && 3168 + next_insn && next_insn->type != INSN_TRAP) { 3406 3169 WARN_FUNC("missing int3 after indirect jump", 3407 3170 insn->sec, insn->offset); 3408 3171 } ··· 3471 3236 default: 3472 3237 break; 3473 3238 } 3239 + 3240 + if (ibt) 3241 + validate_ibt_insn(file, insn); 3474 3242 3475 3243 if (insn->dead_end) 3476 3244 return 0; ··· 3575 3337 int i; 3576 3338 struct instruction *prev_insn; 3577 3339 3578 - if (insn->ignore || insn->type == INSN_NOP) 3340 + if (insn->ignore || insn->type == INSN_NOP || insn->type == INSN_TRAP) 3579 3341 return true; 3580 3342 3581 3343 /* ··· 3585 3347 if (!strcmp(insn->sec->name, ".altinstr_replacement") || 3586 3348 !strcmp(insn->sec->name, ".altinstr_aux")) 3587 3349 return true; 3350 + 3351 + /* 3352 + * Whole archive runs might encounder dead code from weak symbols. 3353 + * This is where the linker will have dropped the weak symbol in 3354 + * favour of a regular symbol, but leaves the code in place. 3355 + * 3356 + * In this case we'll find a piece of code (whole function) that is not 3357 + * covered by a !section symbol. Ignore them. 3358 + */ 3359 + if (!insn->func && lto) { 3360 + int size = find_symbol_hole_containing(insn->sec, insn->offset); 3361 + unsigned long end = insn->offset + size; 3362 + 3363 + if (!size) /* not a hole */ 3364 + return false; 3365 + 3366 + if (size < 0) /* hole until the end */ 3367 + return true; 3368 + 3369 + sec_for_each_insn_continue(file, insn) { 3370 + /* 3371 + * If we reach a visited instruction at or before the 3372 + * end of the hole, ignore the unreachable. 3373 + */ 3374 + if (insn->visited) 3375 + return true; 3376 + 3377 + if (insn->offset >= end) 3378 + break; 3379 + 3380 + /* 3381 + * If this hole jumps to a .cold function, mark it ignore too. 3382 + */ 3383 + if (insn->jump_dest && insn->jump_dest->func && 3384 + strstr(insn->jump_dest->func->name, ".cold")) { 3385 + struct instruction *dest = insn->jump_dest; 3386 + func_for_each_insn(file, dest->func, dest) 3387 + dest->ignore = true; 3388 + } 3389 + } 3390 + 3391 + return false; 3392 + } 3588 3393 3589 3394 if (!insn->func) 3590 3395 return false; ··· 3760 3479 return warnings; 3761 3480 } 3762 3481 3482 + static int validate_ibt(struct objtool_file *file) 3483 + { 3484 + struct section *sec; 3485 + struct reloc *reloc; 3486 + 3487 + for_each_sec(file, sec) { 3488 + bool is_data; 3489 + 3490 + /* already done in validate_branch() */ 3491 + if (sec->sh.sh_flags & SHF_EXECINSTR) 3492 + continue; 3493 + 3494 + if (!sec->reloc) 3495 + continue; 3496 + 3497 + if (!strncmp(sec->name, ".orc", 4)) 3498 + continue; 3499 + 3500 + if (!strncmp(sec->name, ".discard", 8)) 3501 + continue; 3502 + 3503 + if (!strncmp(sec->name, ".debug", 6)) 3504 + continue; 3505 + 3506 + if (!strcmp(sec->name, "_error_injection_whitelist")) 3507 + continue; 3508 + 3509 + if (!strcmp(sec->name, "_kprobe_blacklist")) 3510 + continue; 3511 + 3512 + is_data = strstr(sec->name, ".data") || strstr(sec->name, ".rodata"); 3513 + 3514 + list_for_each_entry(reloc, &sec->reloc->reloc_list, list) { 3515 + struct instruction *dest; 3516 + 3517 + dest = validate_ibt_reloc(file, reloc); 3518 + if (is_data && dest && !dest->noendbr) { 3519 + warn_noendbr("data ", reloc->sym->sec, 3520 + reloc->sym->offset + reloc->addend, 3521 + dest); 3522 + } 3523 + } 3524 + } 3525 + 3526 + return 0; 3527 + } 3528 + 3763 3529 static int validate_reachable_instructions(struct objtool_file *file) 3764 3530 { 3765 3531 struct instruction *insn; ··· 3829 3501 { 3830 3502 int ret, warnings = 0; 3831 3503 3504 + if (lto && !(vmlinux || module)) { 3505 + fprintf(stderr, "--lto requires: --vmlinux or --module\n"); 3506 + return 1; 3507 + } 3508 + 3509 + if (ibt && !lto) { 3510 + fprintf(stderr, "--ibt requires: --lto\n"); 3511 + return 1; 3512 + } 3513 + 3832 3514 arch_initial_func_cfi_state(&initial_func_cfi); 3833 3515 init_cfi_state(&init_cfi); 3834 3516 init_cfi_state(&func_cfi); ··· 3859 3521 if (list_empty(&file->insn_list)) 3860 3522 goto out; 3861 3523 3862 - if (vmlinux && !validate_dup) { 3524 + if (vmlinux && !lto) { 3863 3525 ret = validate_vmlinux_functions(file); 3864 3526 if (ret < 0) 3865 3527 goto out; ··· 3885 3547 goto out; 3886 3548 warnings += ret; 3887 3549 3550 + if (ibt) { 3551 + ret = validate_ibt(file); 3552 + if (ret < 0) 3553 + goto out; 3554 + warnings += ret; 3555 + } 3556 + 3888 3557 if (!warnings) { 3889 3558 ret = validate_reachable_instructions(file); 3890 3559 if (ret < 0) ··· 3913 3568 3914 3569 if (mcount) { 3915 3570 ret = create_mcount_loc_sections(file); 3571 + if (ret < 0) 3572 + goto out; 3573 + warnings += ret; 3574 + } 3575 + 3576 + if (ibt) { 3577 + ret = create_ibt_endbr_seal_sections(file); 3916 3578 if (ret < 0) 3917 3579 goto out; 3918 3580 warnings += ret;
+63
tools/objtool/elf.c
··· 83 83 return 0; 84 84 } 85 85 86 + struct symbol_hole { 87 + unsigned long key; 88 + const struct symbol *sym; 89 + }; 90 + 91 + /* 92 + * Find !section symbol where @offset is after it. 93 + */ 94 + static int symbol_hole_by_offset(const void *key, const struct rb_node *node) 95 + { 96 + const struct symbol *s = rb_entry(node, struct symbol, node); 97 + struct symbol_hole *sh = (void *)key; 98 + 99 + if (sh->key < s->offset) 100 + return -1; 101 + 102 + if (sh->key >= s->offset + s->len) { 103 + if (s->type != STT_SECTION) 104 + sh->sym = s; 105 + return 1; 106 + } 107 + 108 + return 0; 109 + } 110 + 86 111 struct section *find_section_by_name(const struct elf *elf, const char *name) 87 112 { 88 113 struct section *sec; ··· 185 160 } 186 161 187 162 return NULL; 163 + } 164 + 165 + /* 166 + * Returns size of hole starting at @offset. 167 + */ 168 + int find_symbol_hole_containing(const struct section *sec, unsigned long offset) 169 + { 170 + struct symbol_hole hole = { 171 + .key = offset, 172 + .sym = NULL, 173 + }; 174 + struct rb_node *n; 175 + struct symbol *s; 176 + 177 + /* 178 + * Find the rightmost symbol for which @offset is after it. 179 + */ 180 + n = rb_find(&hole, &sec->symbol_tree, symbol_hole_by_offset); 181 + 182 + /* found a symbol that contains @offset */ 183 + if (n) 184 + return 0; /* not a hole */ 185 + 186 + /* didn't find a symbol for which @offset is after it */ 187 + if (!hole.sym) 188 + return 0; /* not a hole */ 189 + 190 + /* @offset >= sym->offset + sym->len, find symbol after it */ 191 + n = rb_next(&hole.sym->node); 192 + if (!n) 193 + return -1; /* until end of address space */ 194 + 195 + /* hole until start of next symbol */ 196 + s = rb_entry(n, struct symbol, node); 197 + return s->offset - offset; 188 198 } 189 199 190 200 struct symbol *find_func_containing(struct section *sec, unsigned long offset) ··· 1078 1018 { 1079 1019 struct section *sec; 1080 1020 Elf_Scn *s; 1021 + 1022 + if (dryrun) 1023 + return 0; 1081 1024 1082 1025 /* Update changed relocation sections and section headers: */ 1083 1026 list_for_each_entry(sec, &elf->sections, list) {
+1
tools/objtool/include/objtool/arch.h
··· 27 27 INSN_STD, 28 28 INSN_CLD, 29 29 INSN_TRAP, 30 + INSN_ENDBR, 30 31 INSN_OTHER, 31 32 }; 32 33
+2 -1
tools/objtool/include/objtool/builtin.h
··· 9 9 10 10 extern const struct option check_options[]; 11 11 extern bool no_fp, no_unreachable, retpoline, module, backtrace, uaccess, stats, 12 - validate_dup, vmlinux, mcount, noinstr, backup, sls; 12 + lto, vmlinux, mcount, noinstr, backup, sls, dryrun, 13 + ibt; 13 14 14 15 extern int cmd_parse_options(int argc, const char **argv, const char * const usage[]); 15 16
+10 -3
tools/objtool/include/objtool/check.h
··· 45 45 unsigned int len; 46 46 enum insn_type type; 47 47 unsigned long immediate; 48 - bool dead_end, ignore, ignore_alts; 49 - bool hint; 50 - bool retpoline_safe; 48 + 49 + u8 dead_end : 1, 50 + ignore : 1, 51 + ignore_alts : 1, 52 + hint : 1, 53 + retpoline_safe : 1, 54 + noendbr : 1; 55 + /* 2 bit hole */ 51 56 s8 instr; 52 57 u8 visited; 58 + /* u8 hole */ 59 + 53 60 struct alt_group *alt_group; 54 61 struct symbol *call_dest; 55 62 struct instruction *jump_dest;
+1
tools/objtool/include/objtool/elf.h
··· 152 152 struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset); 153 153 struct symbol *find_symbol_by_name(const struct elf *elf, const char *name); 154 154 struct symbol *find_symbol_containing(const struct section *sec, unsigned long offset); 155 + int find_symbol_hole_containing(const struct section *sec, unsigned long offset); 155 156 struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, unsigned long offset); 156 157 struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *sec, 157 158 unsigned long offset, unsigned int len);
+4
tools/objtool/include/objtool/objtool.h
··· 26 26 struct list_head retpoline_call_list; 27 27 struct list_head static_call_list; 28 28 struct list_head mcount_loc_list; 29 + struct list_head endbr_list; 29 30 bool ignore_unreachables, c_file, hints, rodata; 31 + 32 + unsigned int nr_endbr; 33 + unsigned int nr_endbr_int; 30 34 31 35 unsigned long jl_short, jl_long; 32 36 unsigned long jl_nop_short, jl_nop_long;
+2
tools/objtool/include/objtool/warn.h
··· 22 22 unsigned long name_off; 23 23 24 24 func = find_func_containing(sec, offset); 25 + if (!func) 26 + func = find_symbol_containing(sec, offset); 25 27 if (func) { 26 28 name = func->name; 27 29 name_off = offset - func->offset;
+1
tools/objtool/objtool.c
··· 128 128 INIT_LIST_HEAD(&file.retpoline_call_list); 129 129 INIT_LIST_HEAD(&file.static_call_list); 130 130 INIT_LIST_HEAD(&file.mcount_loc_list); 131 + INIT_LIST_HEAD(&file.endbr_list); 131 132 file.c_file = !vmlinux && find_section_by_name(file.elf, ".comment"); 132 133 file.ignore_unreachables = no_unreachable; 133 134 file.hints = false;