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 ...
Unified · Split
| @@ -17,17 +17,6 @@ static inline void klp_arch_set_pc(struct ftrace_regs *fregs, unsigned long ip) · 16 unmodified lines | |||
| 17 | ftrace_instruction_pointer_set(fregs, ip); | 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 | #ifdef CONFIG_LIVEPATCH_64 | 20 | #ifdef CONFIG_LIVEPATCH_64 |
| 32 | static inline void klp_init_thread_info(struct task_struct *p) | 21 | static inline void klp_init_thread_info(struct task_struct *p) |
| 33 | { | 22 | { |
| @@ -105,6 +105,27 @@ kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset) · 104 unmodified lines | |||
| 105 | return addr; | 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 | void *alloc_insn_page(void) | 129 | void *alloc_insn_page(void) |
| 109 | { | 130 | { |
| 110 | void *page; | 131 | void *page; |
| @@ -218,19 +239,6 @@ static nokprobe_inline void set_current_kprobe(struct kprobe *p, struct pt_regs · 107 unmodified lines | |||
| 218 | kcb->kprobe_saved_msr = regs->msr; | 239 | kcb->kprobe_saved_msr = regs->msr; |
| 219 | } | 240 | } |
| 220 | 241 | ||
| 221 | bool arch_kprobe_on_func_entry(unsigned long offset) | ||
| 222 | { | ||
| 223 | #ifdef PPC64_ELF_ABI_v2 | ||
| 224 | #ifdef CONFIG_KPROBES_ON_FTRACE | ||
| 225 | return offset <= 16; | ||
| 226 | #else | ||
| 227 | return offset <= 8; | ||
| 228 | #endif | ||
| 229 | #else | ||
| 230 | return !offset; | ||
| 231 | #endif | ||
| 232 | } | ||
| 233 | |||
| 234 | void arch_prepare_kretprobe(struct kretprobe_instance *ri, struct pt_regs *regs) | 242 | void arch_prepare_kretprobe(struct kretprobe_instance *ri, struct pt_regs *regs) |
| 235 | { | 243 | { |
| 236 | ri->ret_addr = (kprobe_opcode_t *)regs->link; | 244 | ri->ret_addr = (kprobe_opcode_t *)regs->link; |
| @@ -424,6 +424,10 @@ void __init check_bugs(void) · 423 unmodified lines | |||
| 424 | os_check_bugs(); | 424 | os_check_bugs(); |
| 425 | } | 425 | } |
| 426 | 426 | ||
| 427 | void apply_ibt_endbr(s32 *start, s32 *end) | ||
| 428 | { | ||
| 429 | } | ||
| 430 | |||
| 427 | void apply_retpolines(s32 *start, s32 *end) | 431 | void apply_retpolines(s32 *start, s32 *end) |
| 428 | { | 432 | { |
| 429 | } | 433 | } |
| @@ -1842,6 +1842,36 @@ config X86_UMIP · 1841 unmodified lines | |||
| 1842 | specific cases in protected and virtual-8086 modes. Emulated | 1842 | specific cases in protected and virtual-8086 modes. Emulated |
| 1843 | results are dummy. | 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 | config X86_INTEL_MEMORY_PROTECTION_KEYS | 1875 | config X86_INTEL_MEMORY_PROTECTION_KEYS |
| 1846 | prompt "Memory Protection Keys" | 1876 | prompt "Memory Protection Keys" |
| 1847 | def_bool y | 1877 | def_bool y |
| @@ -2815,19 +2845,20 @@ config IA32_AOUT · 967 unmodified lines | |||
| 2815 | help | 2845 | help |
| 2816 | Support old a.out binaries in the 32bit emulation. | 2846 | Support old a.out binaries in the 32bit emulation. |
| 2817 | 2847 | ||
| 2818 | config X86_X32 | 2848 | config X86_X32_ABI |
| 2819 | bool "x32 ABI for 64-bit mode" | 2849 | bool "x32 ABI for 64-bit mode" |
| 2820 | depends on X86_64 | 2850 | depends on X86_64 |
| 2851 | # llvm-objcopy does not convert x86_64 .note.gnu.property or | ||
| 2852 | # compressed debug sections to x86_x32 properly: | ||
| 2853 | # https://github.com/ClangBuiltLinux/linux/issues/514 | ||
| 2854 | # https://github.com/ClangBuiltLinux/linux/issues/1141 | ||
| 2855 | depends on $(success,$(OBJCOPY) --version | head -n1 | grep -qv llvm) | ||
| 2821 | help | 2856 | help |
| 2822 | Include code to run binaries for the x32 native 32-bit ABI | 2857 | Include code to run binaries for the x32 native 32-bit ABI |
| 2823 | for 64-bit processors. An x32 process gets access to the | 2858 | for 64-bit processors. An x32 process gets access to the |
| 2824 | full 64-bit register file and wide data path while leaving | 2859 | full 64-bit register file and wide data path while leaving |
| 2825 | pointers at 32 bits for smaller memory footprint. | 2860 | pointers at 32 bits for smaller memory footprint. |
| 2826 | 2861 | ||
| 2827 | You will need a recent binutils (2.22 or later) with | ||
| 2828 | elf32_x86_64 support enabled to compile a kernel with this | ||
| 2829 | option set. | ||
| 2830 | |||
| 2831 | config COMPAT_32 | 2862 | config COMPAT_32 |
| 2832 | def_bool y | 2863 | def_bool y |
| 2833 | depends on IA32_EMULATION || X86_32 | 2864 | depends on IA32_EMULATION || X86_32 |
| @@ -2836,7 +2867,7 @@ config COMPAT_32 · 2 unmodified lines | |||
| 2836 | 2867 | ||
| 2837 | config COMPAT | 2868 | config COMPAT |
| 2838 | def_bool y | 2869 | def_bool y |
| 2839 | depends on IA32_EMULATION || X86_X32 | 2870 | depends on IA32_EMULATION || X86_X32_ABI |
| 2840 | 2871 | ||
| 2841 | if COMPAT | 2872 | if COMPAT |
| 2842 | config COMPAT_FOR_U64_ALIGNMENT | 2873 | config COMPAT_FOR_U64_ALIGNMENT |
| @@ -36,7 +36,7 @@ endif · 35 unmodified lines | |||
| 36 | 36 | ||
| 37 | # How to compile the 16-bit code. Note we always compile for -march=i386; | 37 | # How to compile the 16-bit code. Note we always compile for -march=i386; |
| 38 | # that way we can complain to the user if the CPU is insufficient. | 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 | -Wall -Wstrict-prototypes -march=i386 -mregparm=3 \ | 40 | -Wall -Wstrict-prototypes -march=i386 -mregparm=3 \ |
| 41 | -fno-strict-aliasing -fomit-frame-pointer -fno-pic \ | 41 | -fno-strict-aliasing -fomit-frame-pointer -fno-pic \ |
| 42 | -mno-mmx -mno-sse $(call cc-option,-fcf-protection=none) | 42 | -mno-mmx -mno-sse $(call cc-option,-fcf-protection=none) |
| @@ -62,8 +62,20 @@ export BITS · 19 unmodified lines | |||
| 62 | # | 62 | # |
| 63 | KBUILD_CFLAGS += -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx | 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 | KBUILD_CFLAGS += $(call cc-option,-fcf-protection=none) | 77 | KBUILD_CFLAGS += $(call cc-option,-fcf-protection=none) |
| 78 | endif | ||
| 67 | 79 | ||
| 68 | ifeq ($(CONFIG_X86_32),y) | 80 | ifeq ($(CONFIG_X86_32),y) |
| 69 | BITS := 32 | 81 | BITS := 32 |
| @@ -140,22 +152,6 @@ else · 70 unmodified lines | |||
| 140 | KBUILD_CFLAGS += -mcmodel=kernel | 152 | KBUILD_CFLAGS += -mcmodel=kernel |
| 141 | endif | 153 | endif |
| 142 | 154 | ||
| 143 | ifdef CONFIG_X86_X32 | ||
| 144 | x32_ld_ok := $(call try-run,\ | ||
| 145 | /bin/echo -e '1: .quad 1b' | \ | ||
| 146 | $(CC) $(KBUILD_AFLAGS) -c -x assembler -o "$$TMP" - && \ | ||
| 147 | $(OBJCOPY) -O elf32-x86-64 "$$TMP" "$$TMP.o" && \ | ||
| 148 | $(LD) -m elf32_x86_64 "$$TMP.o" -o "$$TMP",y,n) | ||
| 149 | ifeq ($(x32_ld_ok),y) | ||
| 150 | CONFIG_X86_X32_ABI := y | ||
| 151 | KBUILD_AFLAGS += -DCONFIG_X86_X32_ABI | ||
| 152 | KBUILD_CFLAGS += -DCONFIG_X86_X32_ABI | ||
| 153 | else | ||
| 154 | $(warning CONFIG_X86_X32 enabled but no binutils support) | ||
| 155 | endif | ||
| 156 | endif | ||
| 157 | export CONFIG_X86_X32_ABI | ||
| 158 | |||
| 159 | # | 155 | # |
| 160 | # If the function graph tracer is used with mcount instead of fentry, | 156 | # If the function graph tracer is used with mcount instead of fentry, |
| 161 | # '-maccumulate-outgoing-args' is needed to prevent a GCC bug | 157 | # '-maccumulate-outgoing-args' is needed to prevent a GCC bug |
| @@ -195,6 +195,7 @@ crc_array: · 194 unmodified lines | |||
| 195 | .altmacro | 195 | .altmacro |
| 196 | LABEL crc_ %i | 196 | LABEL crc_ %i |
| 197 | .noaltmacro | 197 | .noaltmacro |
| 198 | ENDBR | ||
| 198 | crc32q -i*8(block_0), crc_init | 199 | crc32q -i*8(block_0), crc_init |
| 199 | crc32q -i*8(block_1), crc1 | 200 | crc32q -i*8(block_1), crc1 |
| 200 | crc32q -i*8(block_2), crc2 | 201 | crc32q -i*8(block_2), crc2 |
| @@ -204,6 +205,7 @@ LABEL crc_ %i · 3 unmodified lines | |||
| 204 | .altmacro | 205 | .altmacro |
| 205 | LABEL crc_ %i | 206 | LABEL crc_ %i |
| 206 | .noaltmacro | 207 | .noaltmacro |
| 208 | ENDBR | ||
| 207 | crc32q -i*8(block_0), crc_init | 209 | crc32q -i*8(block_0), crc_init |
| 208 | crc32q -i*8(block_1), crc1 | 210 | crc32q -i*8(block_1), crc1 |
| 209 | # SKIP crc32 -i*8(block_2), crc2 ; Don't do this one yet | 211 | # SKIP crc32 -i*8(block_2), crc2 ; Don't do this one yet |
| @@ -237,6 +239,7 @@ LABEL crc_ %i · 27 unmodified lines | |||
| 237 | ################################################################ | 239 | ################################################################ |
| 238 | 240 | ||
| 239 | LABEL crc_ 0 | 241 | LABEL crc_ 0 |
| 242 | ENDBR | ||
| 240 | mov tmp, len | 243 | mov tmp, len |
| 241 | cmp $128*24, tmp | 244 | cmp $128*24, tmp |
| 242 | jae full_block | 245 | jae full_block |
| @@ -86,6 +86,7 @@ · 85 unmodified lines | |||
| 86 | 86 | ||
| 87 | SYM_CODE_START(entry_SYSCALL_64) | 87 | SYM_CODE_START(entry_SYSCALL_64) |
| 88 | UNWIND_HINT_EMPTY | 88 | UNWIND_HINT_EMPTY |
| 89 | ENDBR | ||
| 89 | 90 | ||
| 90 | swapgs | 91 | swapgs |
| 91 | /* tss.sp2 is scratch space. */ | 92 | /* tss.sp2 is scratch space. */ |
| @@ -94,6 +95,7 @@ SYM_CODE_START(entry_SYSCALL_64) · 2 unmodified lines | |||
| 94 | movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp | 95 | movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp |
| 95 | 96 | ||
| 96 | SYM_INNER_LABEL(entry_SYSCALL_64_safe_stack, SYM_L_GLOBAL) | 97 | SYM_INNER_LABEL(entry_SYSCALL_64_safe_stack, SYM_L_GLOBAL) |
| 98 | ANNOTATE_NOENDBR | ||
| 97 | 99 | ||
| 98 | /* Construct struct pt_regs on stack */ | 100 | /* Construct struct pt_regs on stack */ |
| 99 | pushq $__USER_DS /* pt_regs->ss */ | 101 | pushq $__USER_DS /* pt_regs->ss */ |
| @@ -276,6 +278,7 @@ SYM_FUNC_END(__switch_to_asm) · 176 unmodified lines | |||
| 276 | .pushsection .text, "ax" | 278 | .pushsection .text, "ax" |
| 277 | SYM_CODE_START(ret_from_fork) | 279 | SYM_CODE_START(ret_from_fork) |
| 278 | UNWIND_HINT_EMPTY | 280 | UNWIND_HINT_EMPTY |
| 281 | ANNOTATE_NOENDBR // copy_thread | ||
| 279 | movq %rax, %rdi | 282 | movq %rax, %rdi |
| 280 | call schedule_tail /* rdi: 'prev' task parameter */ | 283 | call schedule_tail /* rdi: 'prev' task parameter */ |
| 281 | 284 | ||
| @@ -350,6 +353,7 @@ SYM_CODE_END(ret_from_fork) · 68 unmodified lines | |||
| 350 | .macro idtentry vector asmsym cfunc has_error_code:req | 353 | .macro idtentry vector asmsym cfunc has_error_code:req |
| 351 | SYM_CODE_START(\asmsym) | 354 | SYM_CODE_START(\asmsym) |
| 352 | UNWIND_HINT_IRET_REGS offset=\has_error_code*8 | 355 | UNWIND_HINT_IRET_REGS offset=\has_error_code*8 |
| 356 | ENDBR | ||
| 353 | ASM_CLAC | 357 | ASM_CLAC |
| 354 | 358 | ||
| 355 | .if \has_error_code == 0 | 359 | .if \has_error_code == 0 |
| @@ -417,6 +421,7 @@ SYM_CODE_END(\asmsym) · 61 unmodified lines | |||
| 417 | .macro idtentry_mce_db vector asmsym cfunc | 421 | .macro idtentry_mce_db vector asmsym cfunc |
| 418 | SYM_CODE_START(\asmsym) | 422 | SYM_CODE_START(\asmsym) |
| 419 | UNWIND_HINT_IRET_REGS | 423 | UNWIND_HINT_IRET_REGS |
| 424 | ENDBR | ||
| 420 | ASM_CLAC | 425 | ASM_CLAC |
| 421 | 426 | ||
| 422 | pushq $-1 /* ORIG_RAX: no syscall to restart */ | 427 | pushq $-1 /* ORIG_RAX: no syscall to restart */ |
| @@ -472,6 +477,7 @@ SYM_CODE_END(\asmsym) · 49 unmodified lines | |||
| 472 | .macro idtentry_vc vector asmsym cfunc | 477 | .macro idtentry_vc vector asmsym cfunc |
| 473 | SYM_CODE_START(\asmsym) | 478 | SYM_CODE_START(\asmsym) |
| 474 | UNWIND_HINT_IRET_REGS | 479 | UNWIND_HINT_IRET_REGS |
| 480 | ENDBR | ||
| 475 | ASM_CLAC | 481 | ASM_CLAC |
| 476 | 482 | ||
| 477 | /* | 483 | /* |
| @@ -533,6 +539,7 @@ SYM_CODE_END(\asmsym) · 55 unmodified lines | |||
| 533 | .macro idtentry_df vector asmsym cfunc | 539 | .macro idtentry_df vector asmsym cfunc |
| 534 | SYM_CODE_START(\asmsym) | 540 | SYM_CODE_START(\asmsym) |
| 535 | UNWIND_HINT_IRET_REGS offset=8 | 541 | UNWIND_HINT_IRET_REGS offset=8 |
| 542 | ENDBR | ||
| 536 | ASM_CLAC | 543 | ASM_CLAC |
| 537 | 544 | ||
| 538 | /* paranoid_entry returns GS information for paranoid_exit in EBX. */ | 545 | /* paranoid_entry returns GS information for paranoid_exit in EBX. */ |
| @@ -544,6 +551,9 @@ SYM_CODE_START(\asmsym) · 5 unmodified lines | |||
| 544 | movq $-1, ORIG_RAX(%rsp) /* no syscall to restart */ | 551 | movq $-1, ORIG_RAX(%rsp) /* no syscall to restart */ |
| 545 | call \cfunc | 552 | call \cfunc |
| 546 | 553 | ||
| 554 | /* For some configurations \cfunc ends up being a noreturn. */ | ||
| 555 | REACHABLE | ||
| 556 | |||
| 547 | jmp paranoid_exit | 557 | jmp paranoid_exit |
| 548 | 558 | ||
| 549 | _ASM_NOKPROBE(\asmsym) | 559 | _ASM_NOKPROBE(\asmsym) |
| @@ -564,6 +574,7 @@ __irqentry_text_start: · 14 unmodified lines | |||
| 564 | .align 16 | 574 | .align 16 |
| 565 | .globl __irqentry_text_end | 575 | .globl __irqentry_text_end |
| 566 | __irqentry_text_end: | 576 | __irqentry_text_end: |
| 577 | ANNOTATE_NOENDBR | ||
| 567 | 578 | ||
| 568 | SYM_CODE_START_LOCAL(common_interrupt_return) | 579 | SYM_CODE_START_LOCAL(common_interrupt_return) |
| 569 | SYM_INNER_LABEL(swapgs_restore_regs_and_return_to_usermode, SYM_L_GLOBAL) | 580 | SYM_INNER_LABEL(swapgs_restore_regs_and_return_to_usermode, SYM_L_GLOBAL) |
| @@ -608,8 +619,8 @@ SYM_INNER_LABEL(swapgs_restore_regs_and_return_to_usermode, SYM_L_GLOBAL) · 38 unmodified lines | |||
| 608 | 619 | ||
| 609 | /* Restore RDI. */ | 620 | /* Restore RDI. */ |
| 610 | popq %rdi | 621 | popq %rdi |
| 611 | SWAPGS | 622 | swapgs |
| 612 | INTERRUPT_RETURN | 623 | jmp .Lnative_iret |
| 613 | 624 | ||
| 614 | 625 | ||
| 615 | SYM_INNER_LABEL(restore_regs_and_return_to_kernel, SYM_L_GLOBAL) | 626 | SYM_INNER_LABEL(restore_regs_and_return_to_kernel, SYM_L_GLOBAL) |
| @@ -626,9 +637,14 @@ SYM_INNER_LABEL(restore_regs_and_return_to_kernel, SYM_L_GLOBAL) · 10 unmodified lines | |||
| 626 | * ARCH_HAS_MEMBARRIER_SYNC_CORE rely on IRET core serialization | 637 | * ARCH_HAS_MEMBARRIER_SYNC_CORE rely on IRET core serialization |
| 627 | * when returning from IPI handler. | 638 | * when returning from IPI handler. |
| 628 | */ | 639 | */ |
| 629 | INTERRUPT_RETURN | 640 | #ifdef CONFIG_XEN_PV |
| 641 | SYM_INNER_LABEL(early_xen_iret_patch, SYM_L_GLOBAL) | ||
| 642 | ANNOTATE_NOENDBR | ||
| 643 | .byte 0xe9 | ||
| 644 | .long .Lnative_iret - (. + 4) | ||
| 645 | #endif | ||
| 630 | 646 | ||
| 631 | SYM_INNER_LABEL_ALIGN(native_iret, SYM_L_GLOBAL) | 647 | .Lnative_iret: |
| 632 | UNWIND_HINT_IRET_REGS | 648 | UNWIND_HINT_IRET_REGS |
| 633 | /* | 649 | /* |
| 634 | * Are we returning to a stack segment from the LDT? Note: in | 650 | * Are we returning to a stack segment from the LDT? Note: in |
| @@ -640,6 +656,7 @@ SYM_INNER_LABEL_ALIGN(native_iret, SYM_L_GLOBAL) · 5 unmodified lines | |||
| 640 | #endif | 656 | #endif |
| 641 | 657 | ||
| 642 | SYM_INNER_LABEL(native_irq_return_iret, SYM_L_GLOBAL) | 658 | SYM_INNER_LABEL(native_irq_return_iret, SYM_L_GLOBAL) |
| 659 | ANNOTATE_NOENDBR // exc_double_fault | ||
| 643 | /* | 660 | /* |
| 644 | * This may fault. Non-paranoid faults on return to userspace are | 661 | * This may fault. Non-paranoid faults on return to userspace are |
| 645 | * handled by fixup_bad_iret. These include #SS, #GP, and #NP. | 662 | * handled by fixup_bad_iret. These include #SS, #GP, and #NP. |
| @@ -734,6 +751,7 @@ SYM_FUNC_START(asm_load_gs_index) · 88 unmodified lines | |||
| 734 | FRAME_BEGIN | 751 | FRAME_BEGIN |
| 735 | swapgs | 752 | swapgs |
| 736 | .Lgs_change: | 753 | .Lgs_change: |
| 754 | ANNOTATE_NOENDBR // error_entry | ||
| 737 | movl %edi, %gs | 755 | movl %edi, %gs |
| 738 | 2: ALTERNATIVE "", "mfence", X86_BUG_SWAPGS_FENCE | 756 | 2: ALTERNATIVE "", "mfence", X86_BUG_SWAPGS_FENCE |
| 739 | swapgs | 757 | swapgs |
| @@ -804,6 +822,7 @@ SYM_CODE_END(exc_xen_hypervisor_callback) · 64 unmodified lines | |||
| 804 | */ | 822 | */ |
| 805 | SYM_CODE_START(xen_failsafe_callback) | 823 | SYM_CODE_START(xen_failsafe_callback) |
| 806 | UNWIND_HINT_EMPTY | 824 | UNWIND_HINT_EMPTY |
| 825 | ENDBR | ||
| 807 | movl %ds, %ecx | 826 | movl %ds, %ecx |
| 808 | cmpw %cx, 0x10(%rsp) | 827 | cmpw %cx, 0x10(%rsp) |
| 809 | jne 1f | 828 | jne 1f |
| @@ -1063,6 +1082,7 @@ SYM_CODE_END(error_return) · 253 unmodified lines | |||
| 1063 | */ | 1082 | */ |
| 1064 | SYM_CODE_START(asm_exc_nmi) | 1083 | SYM_CODE_START(asm_exc_nmi) |
| 1065 | UNWIND_HINT_IRET_REGS | 1084 | UNWIND_HINT_IRET_REGS |
| 1085 | ENDBR | ||
| 1066 | 1086 | ||
| 1067 | /* | 1087 | /* |
| 1068 | * We allow breakpoints in NMIs. If a breakpoint occurs, then | 1088 | * We allow breakpoints in NMIs. If a breakpoint occurs, then |
| @@ -1310,6 +1330,7 @@ first_nmi: · 241 unmodified lines | |||
| 1310 | #endif | 1330 | #endif |
| 1311 | 1331 | ||
| 1312 | repeat_nmi: | 1332 | repeat_nmi: |
| 1333 | ANNOTATE_NOENDBR // this code | ||
| 1313 | /* | 1334 | /* |
| 1314 | * If there was a nested NMI, the first NMI's iret will return | 1335 | * If there was a nested NMI, the first NMI's iret will return |
| 1315 | * here. But NMIs are still enabled and we can take another | 1336 | * here. But NMIs are still enabled and we can take another |
| @@ -1338,6 +1359,7 @@ repeat_nmi: · 22 unmodified lines | |||
| 1338 | .endr | 1359 | .endr |
| 1339 | subq $(5*8), %rsp | 1360 | subq $(5*8), %rsp |
| 1340 | end_repeat_nmi: | 1361 | end_repeat_nmi: |
| 1362 | ANNOTATE_NOENDBR // this code | ||
| 1341 | 1363 | ||
| 1342 | /* | 1364 | /* |
| 1343 | * Everything below this point can be preempted by a nested NMI. | 1365 | * Everything below this point can be preempted by a nested NMI. |
| @@ -1421,6 +1443,7 @@ SYM_CODE_END(asm_exc_nmi) · 77 unmodified lines | |||
| 1421 | */ | 1443 | */ |
| 1422 | SYM_CODE_START(ignore_sysret) | 1444 | SYM_CODE_START(ignore_sysret) |
| 1423 | UNWIND_HINT_EMPTY | 1445 | UNWIND_HINT_EMPTY |
| 1446 | ENDBR | ||
| 1424 | mov $-ENOSYS, %eax | 1447 | mov $-ENOSYS, %eax |
| 1425 | sysretl | 1448 | sysretl |
| 1426 | SYM_CODE_END(ignore_sysret) | 1449 | SYM_CODE_END(ignore_sysret) |
| @@ -48,6 +48,7 @@ · 47 unmodified lines | |||
| 48 | */ | 48 | */ |
| 49 | SYM_CODE_START(entry_SYSENTER_compat) | 49 | SYM_CODE_START(entry_SYSENTER_compat) |
| 50 | UNWIND_HINT_EMPTY | 50 | UNWIND_HINT_EMPTY |
| 51 | ENDBR | ||
| 51 | /* Interrupts are off on entry. */ | 52 | /* Interrupts are off on entry. */ |
| 52 | SWAPGS | 53 | SWAPGS |
| 53 | 54 | ||
| @@ -147,6 +148,7 @@ SYM_INNER_LABEL(entry_SYSENTER_compat_after_hwframe, SYM_L_GLOBAL) · 93 unmodified lines | |||
| 147 | popfq | 148 | popfq |
| 148 | jmp .Lsysenter_flags_fixed | 149 | jmp .Lsysenter_flags_fixed |
| 149 | SYM_INNER_LABEL(__end_entry_SYSENTER_compat, SYM_L_GLOBAL) | 150 | SYM_INNER_LABEL(__end_entry_SYSENTER_compat, SYM_L_GLOBAL) |
| 151 | ANNOTATE_NOENDBR // is_sysenter_singlestep | ||
| 150 | SYM_CODE_END(entry_SYSENTER_compat) | 152 | SYM_CODE_END(entry_SYSENTER_compat) |
| 151 | 153 | ||
| 152 | /* | 154 | /* |
| @@ -198,6 +200,7 @@ SYM_CODE_END(entry_SYSENTER_compat) · 45 unmodified lines | |||
| 198 | */ | 200 | */ |
| 199 | SYM_CODE_START(entry_SYSCALL_compat) | 201 | SYM_CODE_START(entry_SYSCALL_compat) |
| 200 | UNWIND_HINT_EMPTY | 202 | UNWIND_HINT_EMPTY |
| 203 | ENDBR | ||
| 201 | /* Interrupts are off on entry. */ | 204 | /* Interrupts are off on entry. */ |
| 202 | swapgs | 205 | swapgs |
| 203 | 206 | ||
| @@ -211,6 +214,7 @@ SYM_CODE_START(entry_SYSCALL_compat) · 7 unmodified lines | |||
| 211 | movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp | 214 | movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp |
| 212 | 215 | ||
| 213 | SYM_INNER_LABEL(entry_SYSCALL_compat_safe_stack, SYM_L_GLOBAL) | 216 | SYM_INNER_LABEL(entry_SYSCALL_compat_safe_stack, SYM_L_GLOBAL) |
| 217 | ANNOTATE_NOENDBR | ||
| 214 | 218 | ||
| 215 | /* Construct struct pt_regs on stack */ | 219 | /* Construct struct pt_regs on stack */ |
| 216 | pushq $__USER32_DS /* pt_regs->ss */ | 220 | pushq $__USER32_DS /* pt_regs->ss */ |
| @@ -340,6 +344,7 @@ SYM_CODE_END(entry_SYSCALL_compat) · 123 unmodified lines | |||
| 340 | */ | 344 | */ |
| 341 | SYM_CODE_START(entry_INT80_compat) | 345 | SYM_CODE_START(entry_INT80_compat) |
| 342 | UNWIND_HINT_EMPTY | 346 | UNWIND_HINT_EMPTY |
| 347 | ENDBR | ||
| 343 | /* | 348 | /* |
| 344 | * Interrupts are off on entry. | 349 | * Interrupts are off on entry. |
| 345 | */ | 350 | */ |
| @@ -67,7 +67,7 @@ uapisyshdr-y += unistd_32.h unistd_64.h unistd_x32.h · 66 unmodified lines | |||
| 67 | syshdr-y += syscalls_32.h | 67 | syshdr-y += syscalls_32.h |
| 68 | syshdr-$(CONFIG_X86_64) += unistd_32_ia32.h unistd_64_x32.h | 68 | syshdr-$(CONFIG_X86_64) += unistd_32_ia32.h unistd_64_x32.h |
| 69 | syshdr-$(CONFIG_X86_64) += syscalls_64.h | 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 | syshdr-$(CONFIG_XEN) += xen-hypercalls.h | 71 | syshdr-$(CONFIG_XEN) += xen-hypercalls.h |
| 72 | 72 | ||
| 73 | uapisyshdr-y := $(addprefix $(uapi)/, $(uapisyshdr-y)) | 73 | uapisyshdr-y := $(addprefix $(uapi)/, $(uapisyshdr-y)) |
| @@ -76,6 +76,7 @@ extern int alternatives_patched; · 75 unmodified lines | |||
| 76 | extern void alternative_instructions(void); | 76 | extern void alternative_instructions(void); |
| 77 | extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end); | 77 | extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end); |
| 78 | extern void apply_retpolines(s32 *start, s32 *end); | 78 | extern void apply_retpolines(s32 *start, s32 *end); |
| 79 | extern void apply_ibt_endbr(s32 *start, s32 *end); | ||
| 79 | 80 | ||
| 80 | struct module; | 81 | struct module; |
| 81 | 82 | ||
| @@ -4,6 +4,7 @@ · 3 unmodified lines | |||
| 4 | 4 | ||
| 5 | #include <linux/stringify.h> | 5 | #include <linux/stringify.h> |
| 6 | #include <linux/instrumentation.h> | 6 | #include <linux/instrumentation.h> |
| 7 | #include <linux/objtool.h> | ||
| 7 | 8 | ||
| 8 | /* | 9 | /* |
| 9 | * Despite that some emulators terminate on UD2, we use it for WARN(). | 10 | * Despite that some emulators terminate on UD2, we use it for WARN(). |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | |||
| 7 | #include <linux/topology.h> | 7 | #include <linux/topology.h> |
| 8 | #include <linux/nodemask.h> | 8 | #include <linux/nodemask.h> |
| 9 | #include <linux/percpu.h> | 9 | #include <linux/percpu.h> |
| 10 | #include <asm/ibt.h> | ||
| 10 | 11 | ||
| 11 | #ifdef CONFIG_SMP | 12 | #ifdef CONFIG_SMP |
| 12 | 13 | ||
| @@ -72,4 +73,7 @@ void init_ia32_feat_ctl(struct cpuinfo_x86 *c); · 59 unmodified lines | |||
| 72 | #else | 73 | #else |
| 73 | static inline void init_ia32_feat_ctl(struct cpuinfo_x86 *c) {} | 74 | static inline void init_ia32_feat_ctl(struct cpuinfo_x86 *c) {} |
| 74 | #endif | 75 | #endif |
| 76 | |||
| 77 | extern __noendbr void cet_disable(void); | ||
| 78 | |||
| 75 | #endif /* _ASM_X86_CPU_H */ | 79 | #endif /* _ASM_X86_CPU_H */ |
| @@ -388,6 +388,7 @@ · 387 unmodified lines | |||
| 388 | #define X86_FEATURE_TSXLDTRK (18*32+16) /* TSX Suspend Load Address Tracking */ | 388 | #define X86_FEATURE_TSXLDTRK (18*32+16) /* TSX Suspend Load Address Tracking */ |
| 389 | #define X86_FEATURE_PCONFIG (18*32+18) /* Intel PCONFIG */ | 389 | #define X86_FEATURE_PCONFIG (18*32+18) /* Intel PCONFIG */ |
| 390 | #define X86_FEATURE_ARCH_LBR (18*32+19) /* Intel ARCH LBR */ | 390 | #define X86_FEATURE_ARCH_LBR (18*32+19) /* Intel ARCH LBR */ |
| 391 | #define X86_FEATURE_IBT (18*32+20) /* Indirect Branch Tracking */ | ||
| 391 | #define X86_FEATURE_AMX_BF16 (18*32+22) /* AMX bf16 Support */ | 392 | #define X86_FEATURE_AMX_BF16 (18*32+22) /* AMX bf16 Support */ |
| 392 | #define X86_FEATURE_AVX512_FP16 (18*32+23) /* AVX512 FP16 */ | 393 | #define X86_FEATURE_AVX512_FP16 (18*32+23) /* AVX512 FP16 */ |
| 393 | #define X86_FEATURE_AMX_TILE (18*32+24) /* AMX tile Support */ | 394 | #define X86_FEATURE_AMX_TILE (18*32+24) /* AMX tile Support */ |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | |||
| 7 | #include <asm/tlb.h> | 7 | #include <asm/tlb.h> |
| 8 | #include <asm/nospec-branch.h> | 8 | #include <asm/nospec-branch.h> |
| 9 | #include <asm/mmu_context.h> | 9 | #include <asm/mmu_context.h> |
| 10 | #include <asm/ibt.h> | ||
| 10 | #include <linux/build_bug.h> | 11 | #include <linux/build_bug.h> |
| 11 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
| 12 | #include <linux/pgtable.h> | 13 | #include <linux/pgtable.h> |
| @@ -120,8 +121,12 @@ extern asmlinkage u64 __efi_call(void *fp, ...); · 107 unmodified lines | |||
| 120 | efi_enter_mm(); \ | 121 | efi_enter_mm(); \ |
| 121 | }) | 122 | }) |
| 122 | 123 | ||
| 123 | #define arch_efi_call_virt(p, f, args...) \ | 124 | #define arch_efi_call_virt(p, f, args...) ({ \ |
| 124 | efi_call((void *)p->f, args) \ | 125 | u64 ret, ibt = ibt_save(); \ |
| 126 | ret = efi_call((void *)p->f, args); \ | ||
| 127 | ibt_restore(ibt); \ | ||
| 128 | ret; \ | ||
| 129 | }) | ||
| 125 | 130 | ||
| 126 | #define arch_efi_call_virt_teardown() \ | 131 | #define arch_efi_call_virt_teardown() \ |
| 127 | ({ \ | 132 | ({ \ |
| @@ -0,0 +1,105 @@ | |||
| 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 */ | ||
| @@ -5,6 +5,8 @@ · 4 unmodified lines | |||
| 5 | /* Interrupts/Exceptions */ | 5 | /* Interrupts/Exceptions */ |
| 6 | #include <asm/trapnr.h> | 6 | #include <asm/trapnr.h> |
| 7 | 7 | ||
| 8 | #define IDT_ALIGN (8 * (1 + HAS_KERNEL_IBT)) | ||
| 9 | |||
| 8 | #ifndef __ASSEMBLY__ | 10 | #ifndef __ASSEMBLY__ |
| 9 | #include <linux/entry-common.h> | 11 | #include <linux/entry-common.h> |
| 10 | #include <linux/hardirq.h> | 12 | #include <linux/hardirq.h> |
| @@ -480,7 +482,7 @@ __visible noinstr void func(struct pt_regs *regs, \ · 469 unmodified lines | |||
| 480 | 482 | ||
| 481 | /* | 483 | /* |
| 482 | * ASM code to emit the common vector entry stubs where each stub is | 484 | * ASM code to emit the common vector entry stubs where each stub is |
| 483 | * packed into 8 bytes. | 485 | * packed into IDT_ALIGN bytes. |
| 484 | * | 486 | * |
| 485 | * Note, that the 'pushq imm8' is emitted via '.byte 0x6a, vector' because | 487 | * Note, that the 'pushq imm8' is emitted via '.byte 0x6a, vector' because |
| 486 | * GCC treats the local vector variable as unsigned int and would expand | 488 | * GCC treats the local vector variable as unsigned int and would expand |
| @@ -492,33 +494,33 @@ __visible noinstr void func(struct pt_regs *regs, \ · 5 unmodified lines | |||
| 492 | * point is to mask off the bits above bit 7 because the push is sign | 494 | * point is to mask off the bits above bit 7 because the push is sign |
| 493 | * extending. | 495 | * extending. |
| 494 | */ | 496 | */ |
| 495 | .align 8 | 497 | .align IDT_ALIGN |
| 496 | SYM_CODE_START(irq_entries_start) | 498 | SYM_CODE_START(irq_entries_start) |
| 497 | vector=FIRST_EXTERNAL_VECTOR | 499 | vector=FIRST_EXTERNAL_VECTOR |
| 498 | .rept NR_EXTERNAL_VECTORS | 500 | .rept NR_EXTERNAL_VECTORS |
| 499 | UNWIND_HINT_IRET_REGS | 501 | UNWIND_HINT_IRET_REGS |
| 500 | 0 : | 502 | 0 : |
| 503 | ENDBR | ||
| 501 | .byte 0x6a, vector | 504 | .byte 0x6a, vector |
| 502 | jmp asm_common_interrupt | 505 | jmp asm_common_interrupt |
| 503 | nop | 506 | /* Ensure that the above is IDT_ALIGN bytes max */ |
| 504 | /* Ensure that the above is 8 bytes max */ | 507 | .fill 0b + IDT_ALIGN - ., 1, 0xcc |
| 505 | . = 0b + 8 | ||
| 506 | vector = vector+1 | 508 | vector = vector+1 |
| 507 | .endr | 509 | .endr |
| 508 | SYM_CODE_END(irq_entries_start) | 510 | SYM_CODE_END(irq_entries_start) |
| 509 | 511 | ||
| 510 | #ifdef CONFIG_X86_LOCAL_APIC | 512 | #ifdef CONFIG_X86_LOCAL_APIC |
| 511 | .align 8 | 513 | .align IDT_ALIGN |
| 512 | SYM_CODE_START(spurious_entries_start) | 514 | SYM_CODE_START(spurious_entries_start) |
| 513 | vector=FIRST_SYSTEM_VECTOR | 515 | vector=FIRST_SYSTEM_VECTOR |
| 514 | .rept NR_SYSTEM_VECTORS | 516 | .rept NR_SYSTEM_VECTORS |
| 515 | UNWIND_HINT_IRET_REGS | 517 | UNWIND_HINT_IRET_REGS |
| 516 | 0 : | 518 | 0 : |
| 519 | ENDBR | ||
| 517 | .byte 0x6a, vector | 520 | .byte 0x6a, vector |
| 518 | jmp asm_spurious_interrupt | 521 | jmp asm_spurious_interrupt |
| 519 | nop | 522 | /* Ensure that the above is IDT_ALIGN bytes max */ |
| 520 | /* Ensure that the above is 8 bytes max */ | 523 | .fill 0b + IDT_ALIGN - ., 1, 0xcc |
| 521 | . = 0b + 8 | ||
| 522 | vector = vector+1 | 524 | vector = vector+1 |
| 523 | .endr | 525 | .endr |
| 524 | SYM_CODE_END(spurious_entries_start) | 526 | SYM_CODE_END(spurious_entries_start) |
| @@ -615,6 +617,11 @@ DECLARE_IDTENTRY_DF(X86_TRAP_DF, exc_double_fault); · 90 unmodified lines | |||
| 615 | DECLARE_IDTENTRY_RAW_ERRORCODE(X86_TRAP_DF, xenpv_exc_double_fault); | 617 | DECLARE_IDTENTRY_RAW_ERRORCODE(X86_TRAP_DF, xenpv_exc_double_fault); |
| 616 | #endif | 618 | #endif |
| 617 | 619 | ||
| 620 | /* #CP */ | ||
| 621 | #ifdef CONFIG_X86_KERNEL_IBT | ||
| 622 | DECLARE_IDTENTRY_ERRORCODE(X86_TRAP_CP, exc_control_protection); | ||
| 623 | #endif | ||
| 624 | |||
| 618 | /* #VC */ | 625 | /* #VC */ |
| 619 | #ifdef CONFIG_AMD_MEM_ENCRYPT | 626 | #ifdef CONFIG_AMD_MEM_ENCRYPT |
| 620 | DECLARE_IDTENTRY_VC(X86_TRAP_VC, exc_vmm_communication); | 627 | DECLARE_IDTENTRY_VC(X86_TRAP_VC, exc_vmm_communication); |
| @@ -3,6 +3,7 @@ · 2 unmodified lines | |||
| 3 | #define _ASM_X86_IRQ_STACK_H | 3 | #define _ASM_X86_IRQ_STACK_H |
| 4 | 4 | ||
| 5 | #include <linux/ptrace.h> | 5 | #include <linux/ptrace.h> |
| 6 | #include <linux/objtool.h> | ||
| 6 | 7 | ||
| 7 | #include <asm/processor.h> | 8 | #include <asm/processor.h> |
| 8 | 9 | ||
| @@ -99,7 +100,8 @@ · 90 unmodified lines | |||
| 99 | } | 100 | } |
| 100 | 101 | ||
| 101 | #define ASM_CALL_ARG0 \ | 102 | #define ASM_CALL_ARG0 \ |
| 102 | "call %P[__func] \n" | 103 | "call %P[__func] \n" \ |
| 104 | ASM_REACHABLE | ||
| 103 | 105 | ||
| 104 | #define ASM_CALL_ARG1 \ | 106 | #define ASM_CALL_ARG1 \ |
| 105 | "movq %[arg1], %%rdi \n" \ | 107 | "movq %[arg1], %%rdi \n" \ |
| @@ -141,13 +141,8 @@ static __always_inline void arch_local_irq_restore(unsigned long flags) · 140 unmodified lines | |||
| 141 | #ifdef CONFIG_X86_64 | 141 | #ifdef CONFIG_X86_64 |
| 142 | #ifdef CONFIG_XEN_PV | 142 | #ifdef CONFIG_XEN_PV |
| 143 | #define SWAPGS ALTERNATIVE "swapgs", "", X86_FEATURE_XENPV | 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 | #else | 144 | #else |
| 149 | #define SWAPGS swapgs | 145 | #define SWAPGS swapgs |
| 150 | #define INTERRUPT_RETURN jmp native_iret | ||
| 151 | #endif | 146 | #endif |
| 152 | #endif | 147 | #endif |
| 153 | #endif /* !__ASSEMBLY__ */ | 148 | #endif /* !__ASSEMBLY__ */ |
| @@ -3,6 +3,7 @@ · 2 unmodified lines | |||
| 3 | #define _ASM_X86_LINKAGE_H | 3 | #define _ASM_X86_LINKAGE_H |
| 4 | 4 | ||
| 5 | #include <linux/stringify.h> | 5 | #include <linux/stringify.h> |
| 6 | #include <asm/ibt.h> | ||
| 6 | 7 | ||
| 7 | #undef notrace | 8 | #undef notrace |
| 8 | #define notrace __attribute__((no_instrument_function)) | 9 | #define notrace __attribute__((no_instrument_function)) |
| @@ -34,5 +35,35 @@ · 25 unmodified lines | |||
| 34 | 35 | ||
| 35 | #endif /* __ASSEMBLY__ */ | 36 | #endif /* __ASSEMBLY__ */ |
| 36 | 37 | ||
| 38 | /* SYM_FUNC_START -- use for global functions */ | ||
| 39 | #define SYM_FUNC_START(name) \ | ||
| 40 | SYM_START(name, SYM_L_GLOBAL, SYM_A_ALIGN) \ | ||
| 41 | ENDBR | ||
| 42 | |||
| 43 | /* SYM_FUNC_START_NOALIGN -- use for global functions, w/o alignment */ | ||
| 44 | #define SYM_FUNC_START_NOALIGN(name) \ | ||
| 45 | SYM_START(name, SYM_L_GLOBAL, SYM_A_NONE) \ | ||
| 46 | ENDBR | ||
| 47 | |||
| 48 | /* SYM_FUNC_START_LOCAL -- use for local functions */ | ||
| 49 | #define SYM_FUNC_START_LOCAL(name) \ | ||
| 50 | SYM_START(name, SYM_L_LOCAL, SYM_A_ALIGN) \ | ||
| 51 | ENDBR | ||
| 52 | |||
| 53 | /* SYM_FUNC_START_LOCAL_NOALIGN -- use for local functions, w/o alignment */ | ||
| 54 | #define SYM_FUNC_START_LOCAL_NOALIGN(name) \ | ||
| 55 | SYM_START(name, SYM_L_LOCAL, SYM_A_NONE) \ | ||
| 56 | ENDBR | ||
| 57 | |||
| 58 | /* SYM_FUNC_START_WEAK -- use for weak functions */ | ||
| 59 | #define SYM_FUNC_START_WEAK(name) \ | ||
| 60 | SYM_START(name, SYM_L_WEAK, SYM_A_ALIGN) \ | ||
| 61 | ENDBR | ||
| 62 | |||
| 63 | /* SYM_FUNC_START_WEAK_NOALIGN -- use for weak functions, w/o alignment */ | ||
| 64 | #define SYM_FUNC_START_WEAK_NOALIGN(name) \ | ||
| 65 | SYM_START(name, SYM_L_WEAK, SYM_A_NONE) \ | ||
| 66 | ENDBR | ||
| 67 | |||
| 37 | #endif /* _ASM_X86_LINKAGE_H */ | 68 | #endif /* _ASM_X86_LINKAGE_H */ |
| 38 | 69 | ||
| @@ -362,11 +362,29 @@ · 361 unmodified lines | |||
| 362 | #define MSR_ATOM_CORE_TURBO_RATIOS 0x0000066c | 362 | #define MSR_ATOM_CORE_TURBO_RATIOS 0x0000066c |
| 363 | #define MSR_ATOM_CORE_TURBO_VIDS 0x0000066d | 363 | #define MSR_ATOM_CORE_TURBO_VIDS 0x0000066d |
| 364 | 364 | ||
| 365 | |||
| 366 | #define MSR_CORE_PERF_LIMIT_REASONS 0x00000690 | 365 | #define MSR_CORE_PERF_LIMIT_REASONS 0x00000690 |
| 367 | #define MSR_GFX_PERF_LIMIT_REASONS 0x000006B0 | 366 | #define MSR_GFX_PERF_LIMIT_REASONS 0x000006B0 |
| 368 | #define MSR_RING_PERF_LIMIT_REASONS 0x000006B1 | 367 | #define MSR_RING_PERF_LIMIT_REASONS 0x000006B1 |
| 369 | 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 */ | ||
| 387 | |||
| 370 | /* Hardware P state interface */ | 388 | /* Hardware P state interface */ |
| 371 | #define MSR_PPERF 0x0000064e | 389 | #define MSR_PPERF 0x0000064e |
| 372 | #define MSR_PERF_LIMIT_REASONS 0x0000064f | 390 | #define MSR_PERF_LIMIT_REASONS 0x0000064f |
| @@ -666,6 +666,7 @@ bool __raw_callee_save___native_vcpu_is_preempted(long cpu); · 665 unmodified lines | |||
| 666 | ".globl " PV_THUNK_NAME(func) ";" \ | 666 | ".globl " PV_THUNK_NAME(func) ";" \ |
| 667 | ".type " PV_THUNK_NAME(func) ", @function;" \ | 667 | ".type " PV_THUNK_NAME(func) ", @function;" \ |
| 668 | PV_THUNK_NAME(func) ":" \ | 668 | PV_THUNK_NAME(func) ":" \ |
| 669 | ASM_ENDBR \ | ||
| 669 | FRAME_BEGIN \ | 670 | FRAME_BEGIN \ |
| 670 | PV_SAVE_ALL_CALLER_REGS \ | 671 | PV_SAVE_ALL_CALLER_REGS \ |
| 671 | "call " #func ";" \ | 672 | "call " #func ";" \ |
| @@ -272,7 +272,6 @@ struct paravirt_patch_template { · 271 unmodified lines | |||
| 272 | 272 | ||
| 273 | extern struct pv_info pv_info; | 273 | extern struct pv_info pv_info; |
| 274 | extern struct paravirt_patch_template pv_ops; | 274 | extern struct paravirt_patch_template pv_ops; |
| 275 | extern void (*paravirt_iret)(void); | ||
| 276 | 275 | ||
| 277 | #define PARAVIRT_PATCH(x) \ | 276 | #define PARAVIRT_PATCH(x) \ |
| 278 | (offsetof(struct paravirt_patch_template, x) / sizeof(void *)) | 277 | (offsetof(struct paravirt_patch_template, x) / sizeof(void *)) |
| @@ -837,7 +837,7 @@ bool xen_set_default_idle(void); · 836 unmodified lines | |||
| 837 | #define xen_set_default_idle 0 | 837 | #define xen_set_default_idle 0 |
| 838 | #endif | 838 | #endif |
| 839 | 839 | ||
| 840 | void stop_this_cpu(void *dummy); | 840 | void __noreturn stop_this_cpu(void *dummy); |
| 841 | void microcode_check(void); | 841 | void microcode_check(void); |
| 842 | 842 | ||
| 843 | enum l1tf_mitigations { | 843 | enum l1tf_mitigations { |
| @@ -2,6 +2,8 @@ · 1 unmodified line | |||
| 2 | #ifndef __ASM_QSPINLOCK_PARAVIRT_H | 2 | #ifndef __ASM_QSPINLOCK_PARAVIRT_H |
| 3 | #define __ASM_QSPINLOCK_PARAVIRT_H | 3 | #define __ASM_QSPINLOCK_PARAVIRT_H |
| 4 | 4 | ||
| 5 | #include <asm/ibt.h> | ||
| 6 | |||
| 5 | /* | 7 | /* |
| 6 | * For x86-64, PV_CALLEE_SAVE_REGS_THUNK() saves and restores 8 64-bit | 8 | * For x86-64, PV_CALLEE_SAVE_REGS_THUNK() saves and restores 8 64-bit |
| 7 | * registers. For i386, however, only 1 32-bit register needs to be saved | 9 | * registers. For i386, however, only 1 32-bit register needs to be saved |
| @@ -39,6 +41,7 @@ asm (".pushsection .text;" · 31 unmodified lines | |||
| 39 | ".type " PV_UNLOCK ", @function;" | 41 | ".type " PV_UNLOCK ", @function;" |
| 40 | ".align 4,0x90;" | 42 | ".align 4,0x90;" |
| 41 | PV_UNLOCK ": " | 43 | PV_UNLOCK ": " |
| 44 | ASM_ENDBR | ||
| 42 | FRAME_BEGIN | 45 | FRAME_BEGIN |
| 43 | "push %rdx;" | 46 | "push %rdx;" |
| 44 | "mov $0x1,%eax;" | 47 | "mov $0x1,%eax;" |
| @@ -4,6 +4,7 @@ · 3 unmodified lines | |||
| 4 | 4 | ||
| 5 | #include <linux/const.h> | 5 | #include <linux/const.h> |
| 6 | #include <asm/alternative.h> | 6 | #include <asm/alternative.h> |
| 7 | #include <asm/ibt.h> | ||
| 7 | 8 | ||
| 8 | /* | 9 | /* |
| 9 | * Constructor for a conventional segment GDT (or LDT) entry. | 10 | * Constructor for a conventional segment GDT (or LDT) entry. |
| @@ -275,7 +276,7 @@ static inline void vdso_read_cpunode(unsigned *cpu, unsigned *node) · 265 unmodified lines | |||
| 275 | * vector has no error code (two bytes), a 'push $vector_number' (two | 276 | * vector has no error code (two bytes), a 'push $vector_number' (two |
| 276 | * bytes), and a jump to the common entry code (up to five bytes). | 277 | * bytes), and a jump to the common entry code (up to five bytes). |
| 277 | */ | 278 | */ |
| 278 | #define EARLY_IDT_HANDLER_SIZE 9 | 279 | #define EARLY_IDT_HANDLER_SIZE (9 + ENDBR_INSN_SIZE) |
| 279 | 280 | ||
| 280 | /* | 281 | /* |
| 281 | * xen_early_idt_handler_array is for Xen pv guests: for each entry in | 282 | * xen_early_idt_handler_array is for Xen pv guests: for each entry in |
| @@ -283,7 +284,7 @@ static inline void vdso_read_cpunode(unsigned *cpu, unsigned *node) · 1 unmodified line | |||
| 283 | * pop %rcx; pop %r11; jmp early_idt_handler_array[i]; summing up to | 284 | * pop %rcx; pop %r11; jmp early_idt_handler_array[i]; summing up to |
| 284 | * max 8 bytes. | 285 | * max 8 bytes. |
| 285 | */ | 286 | */ |
| 286 | #define XEN_EARLY_IDT_HANDLER_SIZE 8 | 287 | #define XEN_EARLY_IDT_HANDLER_SIZE (8 + ENDBR_INSN_SIZE) |
| 287 | 288 | ||
| 288 | #ifndef __ASSEMBLY__ | 289 | #ifndef __ASSEMBLY__ |
| 289 | 290 | ||
| @@ -8,6 +8,7 @@ · 7 unmodified lines | |||
| 8 | 8 | ||
| 9 | #include <linux/linkage.h> | 9 | #include <linux/linkage.h> |
| 10 | #include <asm/page_types.h> | 10 | #include <asm/page_types.h> |
| 11 | #include <asm/ibt.h> | ||
| 11 | 12 | ||
| 12 | #ifdef __i386__ | 13 | #ifdef __i386__ |
| 13 | 14 | ||
| @@ -119,7 +120,7 @@ void *extend_brk(size_t size, size_t align); · 105 unmodified lines | |||
| 119 | * executable.) | 120 | * executable.) |
| 120 | */ | 121 | */ |
| 121 | #define RESERVE_BRK(name,sz) \ | 122 | #define RESERVE_BRK(name,sz) \ |
| 122 | static void __section(".discard.text") __used notrace \ | 123 | static void __section(".discard.text") __noendbr __used notrace \ |
| 123 | __brk_reservation_fn_##name##__(void) { \ | 124 | __brk_reservation_fn_##name##__(void) { \ |
| 124 | asm volatile ( \ | 125 | asm volatile ( \ |
| 125 | ".pushsection .brk_reservation,\"aw\",@nobits;" \ | 126 | ".pushsection .brk_reservation,\"aw\",@nobits;" \ |
| @@ -159,7 +159,7 @@ extern long __ia32_sys_ni_syscall(const struct pt_regs *regs); · 158 unmodified lines | |||
| 159 | #endif /* CONFIG_IA32_EMULATION */ | 159 | #endif /* CONFIG_IA32_EMULATION */ |
| 160 | 160 | ||
| 161 | 161 | ||
| 162 | #ifdef CONFIG_X86_X32 | 162 | #ifdef CONFIG_X86_X32_ABI |
| 163 | /* | 163 | /* |
| 164 | * For the x32 ABI, we need to create a stub for compat_sys_*() which is aware | 164 | * For the x32 ABI, we need to create a stub for compat_sys_*() which is aware |
| 165 | * of the x86-64-style parameter ordering of x32 syscalls. The syscalls common | 165 | * of the x86-64-style parameter ordering of x32 syscalls. The syscalls common |
| @@ -177,12 +177,12 @@ extern long __ia32_sys_ni_syscall(const struct pt_regs *regs); · 11 unmodified lines | |||
| 177 | 177 | ||
| 178 | #define __X32_COMPAT_SYS_NI(name) \ | 178 | #define __X32_COMPAT_SYS_NI(name) \ |
| 179 | __SYS_NI(x64, compat_sys_##name) | 179 | __SYS_NI(x64, compat_sys_##name) |
| 180 | #else /* CONFIG_X86_X32 */ | 180 | #else /* CONFIG_X86_X32_ABI */ |
| 181 | #define __X32_COMPAT_SYS_STUB0(name) | 181 | #define __X32_COMPAT_SYS_STUB0(name) |
| 182 | #define __X32_COMPAT_SYS_STUBx(x, name, ...) | 182 | #define __X32_COMPAT_SYS_STUBx(x, name, ...) |
| 183 | #define __X32_COMPAT_COND_SYSCALL(name) | 183 | #define __X32_COMPAT_COND_SYSCALL(name) |
| 184 | #define __X32_COMPAT_SYS_NI(name) | 184 | #define __X32_COMPAT_SYS_NI(name) |
| 185 | #endif /* CONFIG_X86_X32 */ | 185 | #endif /* CONFIG_X86_X32_ABI */ |
| 186 | 186 | ||
| 187 | 187 | ||
| 188 | #ifdef CONFIG_COMPAT | 188 | #ifdef CONFIG_COMPAT |
| @@ -97,24 +97,40 @@ union text_poke_insn { · 96 unmodified lines | |||
| 97 | }; | 97 | }; |
| 98 | 98 | ||
| 99 | static __always_inline | 99 | static __always_inline |
| 100 | void *text_gen_insn(u8 opcode, const void *addr, const void *dest) | 100 | void __text_gen_insn(void *buf, u8 opcode, const void *addr, const void *dest, int size) |
| 101 | { | 101 | { |
| 102 | static union text_poke_insn insn; /* per instance */ | 102 | union text_poke_insn *insn = buf; |
| 103 | int size = text_opcode_size(opcode); | 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); | ||
| 104 | 114 | ||
| 105 | insn.opcode = opcode; | 115 | insn->opcode = opcode; |
| 106 | 116 | ||
| 107 | if (size > 1) { | 117 | if (size > 1) { |
| 108 | insn.disp = (long)dest - (long)(addr + size); | 118 | insn->disp = (long)dest - (long)(addr + size); |
| 109 | if (size == 2) { | 119 | if (size == 2) { |
| 110 | /* | 120 | /* |
| 111 | * Ensure that for JMP9 the displacement | 121 | * Ensure that for JMP8 the displacement |
| 112 | * actually fits the signed byte. | 122 | * actually fits the signed byte. |
| 113 | */ | 123 | */ |
| 114 | BUG_ON((insn.disp >> 31) != (insn.disp >> 7)); | 124 | BUG_ON((insn->disp >> 31) != (insn->disp >> 7)); |
| 115 | } | 125 | } |
| 116 | } | 126 | } |
| 127 | } | ||
| 117 | 128 | ||
| 129 | static __always_inline | ||
| 130 | void *text_gen_insn(u8 opcode, const void *addr, const void *dest) | ||
| 131 | { | ||
| 132 | static union text_poke_insn insn; /* per instance */ | ||
| 133 | __text_gen_insn(&insn, opcode, addr, dest, text_opcode_size(opcode)); | ||
| 118 | return &insn.text; | 134 | return &insn.text; |
| 119 | } | 135 | } |
| 120 | 136 | ||
| @@ -18,6 +18,8 @@ void __init trap_init(void); · 17 unmodified lines | |||
| 18 | asmlinkage __visible noinstr struct pt_regs *vc_switch_off_ist(struct pt_regs *eregs); | 18 | asmlinkage __visible noinstr struct pt_regs *vc_switch_off_ist(struct pt_regs *eregs); |
| 19 | #endif | 19 | #endif |
| 20 | 20 | ||
| 21 | extern bool ibt_selftest(void); | ||
| 22 | |||
| 21 | #ifdef CONFIG_X86_F00F_BUG | 23 | #ifdef CONFIG_X86_F00F_BUG |
| 22 | /* For handling the FOOF bug */ | 24 | /* For handling the FOOF bug */ |
| 23 | void handle_invalid_op(struct pt_regs *regs); | 25 | void handle_invalid_op(struct pt_regs *regs); |
| @@ -37,7 +37,7 @@ struct vdso_image { · 36 unmodified lines | |||
| 37 | extern const struct vdso_image vdso_image_64; | 37 | extern const struct vdso_image vdso_image_64; |
| 38 | #endif | 38 | #endif |
| 39 | 39 | ||
| 40 | #ifdef CONFIG_X86_X32 | 40 | #ifdef CONFIG_X86_X32_ABI |
| 41 | extern const struct vdso_image vdso_image_x32; | 41 | extern const struct vdso_image vdso_image_x32; |
| 42 | #endif | 42 | #endif |
| 43 | 43 | ||
| @@ -130,6 +130,8 @@ · 129 unmodified lines | |||
| 130 | #define X86_CR4_SMAP _BITUL(X86_CR4_SMAP_BIT) | 130 | #define X86_CR4_SMAP _BITUL(X86_CR4_SMAP_BIT) |
| 131 | #define X86_CR4_PKE_BIT 22 /* enable Protection Keys support */ | 131 | #define X86_CR4_PKE_BIT 22 /* enable Protection Keys support */ |
| 132 | #define X86_CR4_PKE _BITUL(X86_CR4_PKE_BIT) | 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 | * x86-64 Task Priority Register, CR8 | 137 | * x86-64 Task Priority Register, CR8 |
| @@ -115,6 +115,7 @@ static void __init_or_module add_nops(void *insns, unsigned int len) · 114 unmodified lines | |||
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | extern s32 __retpoline_sites[], __retpoline_sites_end[]; | 117 | extern s32 __retpoline_sites[], __retpoline_sites_end[]; |
| 118 | extern s32 __ibt_endbr_seal[], __ibt_endbr_seal_end[]; | ||
| 118 | extern struct alt_instr __alt_instructions[], __alt_instructions_end[]; | 119 | extern struct alt_instr __alt_instructions[], __alt_instructions_end[]; |
| 119 | extern s32 __smp_locks[], __smp_locks_end[]; | 120 | extern s32 __smp_locks[], __smp_locks_end[]; |
| 120 | void text_poke_early(void *addr, const void *opcode, size_t len); | 121 | void text_poke_early(void *addr, const void *opcode, size_t len); |
| @@ -512,6 +513,42 @@ void __init_or_module noinline apply_retpolines(s32 *start, s32 *end) { } · 391 unmodified lines | |||
| 512 | 513 | ||
| 513 | #endif /* CONFIG_RETPOLINE && CONFIG_STACK_VALIDATION */ | 514 | #endif /* CONFIG_RETPOLINE && CONFIG_STACK_VALIDATION */ |
| 514 | 515 | ||
| 516 | #ifdef CONFIG_X86_KERNEL_IBT | ||
| 517 | |||
| 518 | /* | ||
| 519 | * Generated by: objtool --ibt | ||
| 520 | */ | ||
| 521 | void __init_or_module noinline apply_ibt_endbr(s32 *start, s32 *end) | ||
| 522 | { | ||
| 523 | s32 *s; | ||
| 524 | |||
| 525 | for (s = start; s < end; s++) { | ||
| 526 | u32 endbr, poison = gen_endbr_poison(); | ||
| 527 | void *addr = (void *)s + *s; | ||
| 528 | |||
| 529 | if (WARN_ON_ONCE(get_kernel_nofault(endbr, addr))) | ||
| 530 | continue; | ||
| 531 | |||
| 532 | if (WARN_ON_ONCE(!is_endbr(endbr))) | ||
| 533 | continue; | ||
| 534 | |||
| 535 | DPRINTK("ENDBR at: %pS (%px)", addr, addr); | ||
| 536 | |||
| 537 | /* | ||
| 538 | * When we have IBT, the lack of ENDBR will trigger #CP | ||
| 539 | */ | ||
| 540 | DUMP_BYTES(((u8*)addr), 4, "%px: orig: ", addr); | ||
| 541 | DUMP_BYTES(((u8*)&poison), 4, "%px: repl: ", addr); | ||
| 542 | text_poke_early(addr, &poison, 4); | ||
| 543 | } | ||
| 544 | } | ||
| 545 | |||
| 546 | #else | ||
| 547 | |||
| 548 | void __init_or_module noinline apply_ibt_endbr(s32 *start, s32 *end) { } | ||
| 549 | |||
| 550 | #endif /* CONFIG_X86_KERNEL_IBT */ | ||
| 551 | |||
| 515 | #ifdef CONFIG_SMP | 552 | #ifdef CONFIG_SMP |
| 516 | static void alternatives_smp_lock(const s32 *start, const s32 *end, | 553 | static void alternatives_smp_lock(const s32 *start, const s32 *end, |
| 517 | u8 *text, u8 *text_end) | 554 | u8 *text, u8 *text_end) |
| @@ -713,34 +750,39 @@ asm ( · 195 unmodified lines | |||
| 713 | " .pushsection .init.text, \"ax\", @progbits\n" | 750 | " .pushsection .init.text, \"ax\", @progbits\n" |
| 714 | " .type int3_magic, @function\n" | 751 | " .type int3_magic, @function\n" |
| 715 | "int3_magic:\n" | 752 | "int3_magic:\n" |
| 753 | ANNOTATE_NOENDBR | ||
| 716 | " movl $1, (%" _ASM_ARG1 ")\n" | 754 | " movl $1, (%" _ASM_ARG1 ")\n" |
| 717 | ASM_RET | 755 | ASM_RET |
| 718 | " .size int3_magic, .-int3_magic\n" | 756 | " .size int3_magic, .-int3_magic\n" |
| 719 | " .popsection\n" | 757 | " .popsection\n" |
| 720 | ); | 758 | ); |
| 721 | 759 | ||
| 722 | extern __initdata unsigned long int3_selftest_ip; /* defined in asm below */ | 760 | extern void int3_selftest_ip(void); /* defined in asm below */ |
| 723 | 761 | ||
| 724 | static int __init | 762 | static int __init |
| 725 | int3_exception_notify(struct notifier_block *self, unsigned long val, void *data) | 763 | int3_exception_notify(struct notifier_block *self, unsigned long val, void *data) |
| 726 | { | 764 | { |
| 765 | unsigned long selftest = (unsigned long)&int3_selftest_ip; | ||
| 727 | struct die_args *args = data; | 766 | struct die_args *args = data; |
| 728 | struct pt_regs *regs = args->regs; | 767 | struct pt_regs *regs = args->regs; |
| 729 | 768 | ||
| 769 | OPTIMIZER_HIDE_VAR(selftest); | ||
| 770 | |||
| 730 | if (!regs || user_mode(regs)) | 771 | if (!regs || user_mode(regs)) |
| 731 | return NOTIFY_DONE; | 772 | return NOTIFY_DONE; |
| 732 | 773 | ||
| 733 | if (val != DIE_INT3) | 774 | if (val != DIE_INT3) |
| 734 | return NOTIFY_DONE; | 775 | return NOTIFY_DONE; |
| 735 | 776 | ||
| 736 | if (regs->ip - INT3_INSN_SIZE != int3_selftest_ip) | 777 | if (regs->ip - INT3_INSN_SIZE != selftest) |
| 737 | return NOTIFY_DONE; | 778 | return NOTIFY_DONE; |
| 738 | 779 | ||
| 739 | int3_emulate_call(regs, (unsigned long)&int3_magic); | 780 | int3_emulate_call(regs, (unsigned long)&int3_magic); |
| 740 | return NOTIFY_STOP; | 781 | return NOTIFY_STOP; |
| 741 | } | 782 | } |
| 742 | 783 | ||
| 743 | static void __init int3_selftest(void) | 784 | /* Must be noinline to ensure uniqueness of int3_selftest_ip. */ |
| 785 | static noinline void __init int3_selftest(void) | ||
| 744 | { | 786 | { |
| 745 | static __initdata struct notifier_block int3_exception_nb = { | 787 | static __initdata struct notifier_block int3_exception_nb = { |
| 746 | .notifier_call = int3_exception_notify, | 788 | .notifier_call = int3_exception_notify, |
| @@ -753,18 +795,12 @@ static void __init int3_selftest(void) · 6 unmodified lines | |||
| 753 | /* | 795 | /* |
| 754 | * Basically: int3_magic(&val); but really complicated :-) | 796 | * Basically: int3_magic(&val); but really complicated :-) |
| 755 | * | 797 | * |
| 756 | * Stick the address of the INT3 instruction into int3_selftest_ip, | 798 | * INT3 padded with NOP to CALL_INSN_SIZE. The int3_exception_nb |
| 757 | * then trigger the INT3, padded with NOPs to match a CALL instruction | 799 | * notifier above will emulate CALL for us. |
| 758 | * length. | ||
| 759 | */ | 800 | */ |
| 760 | asm volatile ("1: int3; nop; nop; nop; nop\n\t" | 801 | asm volatile ("int3_selftest_ip:\n\t" |
| 761 | ".pushsection .init.data,\"aw\"\n\t" | 802 | ANNOTATE_NOENDBR |
| 762 | ".align " __ASM_SEL(4, 8) "\n\t" | 803 | " int3; nop; nop; nop; nop\n\t" |
| 763 | ".type int3_selftest_ip, @object\n\t" | ||
| 764 | ".size int3_selftest_ip, " __ASM_SEL(4, 8) "\n\t" | ||
| 765 | "int3_selftest_ip:\n\t" | ||
| 766 | __ASM_SEL(.long, .quad) " 1b\n\t" | ||
| 767 | ".popsection\n\t" | ||
| 768 | : ASM_CALL_CONSTRAINT | 804 | : ASM_CALL_CONSTRAINT |
| 769 | : __ASM_SEL_RAW(a, D) (&val) | 805 | : __ASM_SEL_RAW(a, D) (&val) |
| 770 | : "memory"); | 806 | : "memory"); |
| @@ -831,6 +867,8 @@ void __init alternative_instructions(void) · 60 unmodified lines | |||
| 831 | */ | 867 | */ |
| 832 | apply_alternatives(__alt_instructions, __alt_instructions_end); | 868 | apply_alternatives(__alt_instructions, __alt_instructions_end); |
| 833 | 869 | ||
| 870 | apply_ibt_endbr(__ibt_endbr_seal, __ibt_endbr_seal_end); | ||
| 871 | |||
| 834 | #ifdef CONFIG_SMP | 872 | #ifdef CONFIG_SMP |
| 835 | /* Patch to UP if other cpus not imminent. */ | 873 | /* Patch to UP if other cpus not imminent. */ |
| 836 | if (!noreplace_smp && (num_present_cpus() == 1 || setup_max_cpus <= 1)) { | 874 | if (!noreplace_smp && (num_present_cpus() == 1 || setup_max_cpus <= 1)) { |
| @@ -232,6 +232,7 @@ · 231 unmodified lines | |||
| 232 | #include <asm/paravirt.h> | 232 | #include <asm/paravirt.h> |
| 233 | #include <asm/reboot.h> | 233 | #include <asm/reboot.h> |
| 234 | #include <asm/nospec-branch.h> | 234 | #include <asm/nospec-branch.h> |
| 235 | #include <asm/ibt.h> | ||
| 235 | 236 | ||
| 236 | #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT) | 237 | #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT) |
| 237 | extern int (*console_blank_hook)(int); | 238 | extern int (*console_blank_hook)(int); |
| @@ -598,6 +599,7 @@ static long __apm_bios_call(void *_call) · 360 unmodified lines | |||
| 598 | struct desc_struct save_desc_40; | 599 | struct desc_struct save_desc_40; |
| 599 | struct desc_struct *gdt; | 600 | struct desc_struct *gdt; |
| 600 | struct apm_bios_call *call = _call; | 601 | struct apm_bios_call *call = _call; |
| 602 | u64 ibt; | ||
| 601 | 603 | ||
| 602 | cpu = get_cpu(); | 604 | cpu = get_cpu(); |
| 603 | BUG_ON(cpu != 0); | 605 | BUG_ON(cpu != 0); |
| @@ -607,11 +609,13 @@ static long __apm_bios_call(void *_call) · 3 unmodified lines | |||
| 607 | 609 | ||
| 608 | apm_irq_save(flags); | 610 | apm_irq_save(flags); |
| 609 | firmware_restrict_branch_speculation_start(); | 611 | firmware_restrict_branch_speculation_start(); |
| 612 | ibt = ibt_save(); | ||
| 610 | APM_DO_SAVE_SEGS; | 613 | APM_DO_SAVE_SEGS; |
| 611 | apm_bios_call_asm(call->func, call->ebx, call->ecx, | 614 | apm_bios_call_asm(call->func, call->ebx, call->ecx, |
| 612 | &call->eax, &call->ebx, &call->ecx, &call->edx, | 615 | &call->eax, &call->ebx, &call->ecx, &call->edx, |
| 613 | &call->esi); | 616 | &call->esi); |
| 614 | APM_DO_RESTORE_SEGS; | 617 | APM_DO_RESTORE_SEGS; |
| 618 | ibt_restore(ibt); | ||
| 615 | firmware_restrict_branch_speculation_end(); | 619 | firmware_restrict_branch_speculation_end(); |
| 616 | apm_irq_restore(flags); | 620 | apm_irq_restore(flags); |
| 617 | gdt[0x40 / 8] = save_desc_40; | 621 | gdt[0x40 / 8] = save_desc_40; |
| @@ -676,6 +680,7 @@ static long __apm_bios_call_simple(void *_call) · 58 unmodified lines | |||
| 676 | struct desc_struct save_desc_40; | 680 | struct desc_struct save_desc_40; |
| 677 | struct desc_struct *gdt; | 681 | struct desc_struct *gdt; |
| 678 | struct apm_bios_call *call = _call; | 682 | struct apm_bios_call *call = _call; |
| 683 | u64 ibt; | ||
| 679 | 684 | ||
| 680 | cpu = get_cpu(); | 685 | cpu = get_cpu(); |
| 681 | BUG_ON(cpu != 0); | 686 | BUG_ON(cpu != 0); |
| @@ -685,10 +690,12 @@ static long __apm_bios_call_simple(void *_call) · 3 unmodified lines | |||
| 685 | 690 | ||
| 686 | apm_irq_save(flags); | 691 | apm_irq_save(flags); |
| 687 | firmware_restrict_branch_speculation_start(); | 692 | firmware_restrict_branch_speculation_start(); |
| 693 | ibt = ibt_save(); | ||
| 688 | APM_DO_SAVE_SEGS; | 694 | APM_DO_SAVE_SEGS; |
| 689 | error = apm_bios_call_simple_asm(call->func, call->ebx, call->ecx, | 695 | error = apm_bios_call_simple_asm(call->func, call->ebx, call->ecx, |
| 690 | &call->eax); | 696 | &call->eax); |
| 691 | APM_DO_RESTORE_SEGS; | 697 | APM_DO_RESTORE_SEGS; |
| 698 | ibt_restore(ibt); | ||
| 692 | firmware_restrict_branch_speculation_end(); | 699 | firmware_restrict_branch_speculation_end(); |
| 693 | apm_irq_restore(flags); | 700 | apm_irq_restore(flags); |
| 694 | gdt[0x40 / 8] = save_desc_40; | 701 | gdt[0x40 / 8] = save_desc_40; |
| @@ -59,6 +59,7 @@ · 58 unmodified lines | |||
| 59 | #include <asm/cpu_device_id.h> | 59 | #include <asm/cpu_device_id.h> |
| 60 | #include <asm/uv/uv.h> | 60 | #include <asm/uv/uv.h> |
| 61 | #include <asm/sigframe.h> | 61 | #include <asm/sigframe.h> |
| 62 | #include <asm/traps.h> | ||
| 62 | 63 | ||
| 63 | #include "cpu.h" | 64 | #include "cpu.h" |
| 64 | 65 | ||
| @@ -438,7 +439,8 @@ out: · 373 unmodified lines | |||
| 438 | 439 | ||
| 439 | /* These bits should not change their value after CPU init is finished. */ | 440 | /* These bits should not change their value after CPU init is finished. */ |
| 440 | static const unsigned long cr4_pinned_mask = | 441 | static const unsigned long cr4_pinned_mask = |
| 441 | X86_CR4_SMEP | X86_CR4_SMAP | X86_CR4_UMIP | X86_CR4_FSGSBASE; | 442 | X86_CR4_SMEP | X86_CR4_SMAP | X86_CR4_UMIP | |
| 443 | X86_CR4_FSGSBASE | X86_CR4_CET; | ||
| 442 | static DEFINE_STATIC_KEY_FALSE_RO(cr_pinning); | 444 | static DEFINE_STATIC_KEY_FALSE_RO(cr_pinning); |
| 443 | static unsigned long cr4_pinned_bits __ro_after_init; | 445 | static unsigned long cr4_pinned_bits __ro_after_init; |
| 444 | 446 | ||
| @@ -592,6 +594,58 @@ static __init int setup_disable_pku(char *arg) · 147 unmodified lines | |||
| 592 | __setup("nopku", setup_disable_pku); | 594 | __setup("nopku", setup_disable_pku); |
| 593 | #endif /* CONFIG_X86_64 */ | 595 | #endif /* CONFIG_X86_64 */ |
| 594 | 596 | ||
| 597 | #ifdef CONFIG_X86_KERNEL_IBT | ||
| 598 | |||
| 599 | __noendbr u64 ibt_save(void) | ||
| 600 | { | ||
| 601 | u64 msr = 0; | ||
| 602 | |||
| 603 | if (cpu_feature_enabled(X86_FEATURE_IBT)) { | ||
| 604 | rdmsrl(MSR_IA32_S_CET, msr); | ||
| 605 | wrmsrl(MSR_IA32_S_CET, msr & ~CET_ENDBR_EN); | ||
| 606 | } | ||
| 607 | |||
| 608 | return msr; | ||
| 609 | } | ||
| 610 | |||
| 611 | __noendbr void ibt_restore(u64 save) | ||
| 612 | { | ||
| 613 | u64 msr; | ||
| 614 | |||
| 615 | if (cpu_feature_enabled(X86_FEATURE_IBT)) { | ||
| 616 | rdmsrl(MSR_IA32_S_CET, msr); | ||
| 617 | msr &= ~CET_ENDBR_EN; | ||
| 618 | msr |= (save & CET_ENDBR_EN); | ||
| 619 | wrmsrl(MSR_IA32_S_CET, msr); | ||
| 620 | } | ||
| 621 | } | ||
| 622 | |||
| 623 | #endif | ||
| 624 | |||
| 625 | static __always_inline void setup_cet(struct cpuinfo_x86 *c) | ||
| 626 | { | ||
| 627 | u64 msr = CET_ENDBR_EN; | ||
| 628 | |||
| 629 | if (!HAS_KERNEL_IBT || | ||
| 630 | !cpu_feature_enabled(X86_FEATURE_IBT)) | ||
| 631 | return; | ||
| 632 | |||
| 633 | wrmsrl(MSR_IA32_S_CET, msr); | ||
| 634 | cr4_set_bits(X86_CR4_CET); | ||
| 635 | |||
| 636 | if (!ibt_selftest()) { | ||
| 637 | pr_err("IBT selftest: Failed!\n"); | ||
| 638 | setup_clear_cpu_cap(X86_FEATURE_IBT); | ||
| 639 | return; | ||
| 640 | } | ||
| 641 | } | ||
| 642 | |||
| 643 | __noendbr void cet_disable(void) | ||
| 644 | { | ||
| 645 | if (cpu_feature_enabled(X86_FEATURE_IBT)) | ||
| 646 | wrmsrl(MSR_IA32_S_CET, 0); | ||
| 647 | } | ||
| 648 | |||
| 595 | /* | 649 | /* |
| 596 | * Some CPU features depend on higher CPUID levels, which may not always | 650 | * Some CPU features depend on higher CPUID levels, which may not always |
| 597 | * be available due to CPUID level capping or broken virtualization | 651 | * be available due to CPUID level capping or broken virtualization |
| @@ -1709,6 +1763,7 @@ static void identify_cpu(struct cpuinfo_x86 *c) · 1111 unmodified lines | |||
| 1709 | 1763 | ||
| 1710 | x86_init_rdrand(c); | 1764 | x86_init_rdrand(c); |
| 1711 | setup_pku(c); | 1765 | setup_pku(c); |
| 1766 | setup_cet(c); | ||
| 1712 | 1767 | ||
| 1713 | /* | 1768 | /* |
| 1714 | * Clear/Set all flags overridden by options, need do it | 1769 | * Clear/Set all flags overridden by options, need do it |
| @@ -1777,6 +1832,8 @@ void enable_sep_cpu(void) · 62 unmodified lines | |||
| 1777 | void __init identify_boot_cpu(void) | 1832 | void __init identify_boot_cpu(void) |
| 1778 | { | 1833 | { |
| 1779 | identify_cpu(&boot_cpu_data); | 1834 | identify_cpu(&boot_cpu_data); |
| 1835 | if (HAS_KERNEL_IBT && cpu_feature_enabled(X86_FEATURE_IBT)) | ||
| 1836 | pr_info("CET detected: Indirect Branch Tracking enabled\n"); | ||
| 1780 | #ifdef CONFIG_X86_32 | 1837 | #ifdef CONFIG_X86_32 |
| 1781 | sysenter_setup(); | 1838 | sysenter_setup(); |
| 1782 | enable_sep_cpu(); | 1839 | enable_sep_cpu(); |
| @@ -316,12 +316,12 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size) · 315 unmodified lines | |||
| 316 | unsigned long offset; | 316 | unsigned long offset; |
| 317 | unsigned long npages; | 317 | unsigned long npages; |
| 318 | unsigned long size; | 318 | unsigned long size; |
| 319 | unsigned long retq; | ||
| 320 | unsigned long *ptr; | 319 | unsigned long *ptr; |
| 321 | void *trampoline; | 320 | void *trampoline; |
| 322 | void *ip; | 321 | void *ip; |
| 323 | /* 48 8b 15 <offset> is movq <offset>(%rip), %rdx */ | 322 | /* 48 8b 15 <offset> is movq <offset>(%rip), %rdx */ |
| 324 | unsigned const char op_ref[] = { 0x48, 0x8b, 0x15 }; | 323 | unsigned const char op_ref[] = { 0x48, 0x8b, 0x15 }; |
| 324 | unsigned const char retq[] = { RET_INSN_OPCODE, INT3_INSN_OPCODE }; | ||
| 325 | union ftrace_op_code_union op_ptr; | 325 | union ftrace_op_code_union op_ptr; |
| 326 | int ret; | 326 | int ret; |
| 327 | 327 | ||
| @@ -359,12 +359,7 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size) · 31 unmodified lines | |||
| 359 | goto fail; | 359 | goto fail; |
| 360 | 360 | ||
| 361 | ip = trampoline + size; | 361 | ip = trampoline + size; |
| 362 | 362 | memcpy(ip, retq, RET_SIZE); | |
| 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; | ||
| 368 | 363 | ||
| 369 | /* No need to test direct calls on created trampolines */ | 364 | /* No need to test direct calls on created trampolines */ |
| 370 | if (ops->flags & FTRACE_OPS_FL_SAVE_REGS) { | 365 | if (ops->flags & FTRACE_OPS_FL_SAVE_REGS) { |
| @@ -145,6 +145,7 @@ SYM_FUNC_START(ftrace_caller) · 144 unmodified lines | |||
| 145 | movq %rcx, RSP(%rsp) | 145 | movq %rcx, RSP(%rsp) |
| 146 | 146 | ||
| 147 | SYM_INNER_LABEL(ftrace_caller_op_ptr, SYM_L_GLOBAL) | 147 | SYM_INNER_LABEL(ftrace_caller_op_ptr, SYM_L_GLOBAL) |
| 148 | ANNOTATE_NOENDBR | ||
| 148 | /* Load the ftrace_ops into the 3rd parameter */ | 149 | /* Load the ftrace_ops into the 3rd parameter */ |
| 149 | movq function_trace_op(%rip), %rdx | 150 | movq function_trace_op(%rip), %rdx |
| 150 | 151 | ||
| @@ -155,6 +156,7 @@ SYM_INNER_LABEL(ftrace_caller_op_ptr, SYM_L_GLOBAL) · 4 unmodified lines | |||
| 155 | movq $0, CS(%rsp) | 156 | movq $0, CS(%rsp) |
| 156 | 157 | ||
| 157 | SYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL) | 158 | SYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL) |
| 159 | ANNOTATE_NOENDBR | ||
| 158 | call ftrace_stub | 160 | call ftrace_stub |
| 159 | 161 | ||
| 160 | /* Handlers can change the RIP */ | 162 | /* Handlers can change the RIP */ |
| @@ -169,6 +171,7 @@ SYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL) · 8 unmodified lines | |||
| 169 | * layout here. | 171 | * layout here. |
| 170 | */ | 172 | */ |
| 171 | SYM_INNER_LABEL(ftrace_caller_end, SYM_L_GLOBAL) | 173 | SYM_INNER_LABEL(ftrace_caller_end, SYM_L_GLOBAL) |
| 174 | ANNOTATE_NOENDBR | ||
| 172 | 175 | ||
| 173 | jmp ftrace_epilogue | 176 | jmp ftrace_epilogue |
| 174 | SYM_FUNC_END(ftrace_caller); | 177 | SYM_FUNC_END(ftrace_caller); |
| @@ -176,10 +179,10 @@ SYM_FUNC_END(ftrace_caller); · 1 unmodified line | |||
| 176 | SYM_FUNC_START(ftrace_epilogue) | 179 | SYM_FUNC_START(ftrace_epilogue) |
| 177 | /* | 180 | /* |
| 178 | * This is weak to keep gas from relaxing the jumps. | 181 | * This is weak to keep gas from relaxing the jumps. |
| 179 | * It is also used to copy the RET for trampolines. | ||
| 180 | */ | 182 | */ |
| 181 | SYM_INNER_LABEL_ALIGN(ftrace_stub, SYM_L_WEAK) | 183 | SYM_INNER_LABEL_ALIGN(ftrace_stub, SYM_L_WEAK) |
| 182 | UNWIND_HINT_FUNC | 184 | UNWIND_HINT_FUNC |
| 185 | ENDBR | ||
| 183 | RET | 186 | RET |
| 184 | SYM_FUNC_END(ftrace_epilogue) | 187 | SYM_FUNC_END(ftrace_epilogue) |
| 185 | 188 | ||
| @@ -192,6 +195,7 @@ SYM_FUNC_START(ftrace_regs_caller) · 6 unmodified lines | |||
| 192 | /* save_mcount_regs fills in first two parameters */ | 195 | /* save_mcount_regs fills in first two parameters */ |
| 193 | 196 | ||
| 194 | SYM_INNER_LABEL(ftrace_regs_caller_op_ptr, SYM_L_GLOBAL) | 197 | SYM_INNER_LABEL(ftrace_regs_caller_op_ptr, SYM_L_GLOBAL) |
| 198 | ANNOTATE_NOENDBR | ||
| 195 | /* Load the ftrace_ops into the 3rd parameter */ | 199 | /* Load the ftrace_ops into the 3rd parameter */ |
| 196 | movq function_trace_op(%rip), %rdx | 200 | movq function_trace_op(%rip), %rdx |
| 197 | 201 | ||
| @@ -221,6 +225,7 @@ SYM_INNER_LABEL(ftrace_regs_caller_op_ptr, SYM_L_GLOBAL) · 23 unmodified lines | |||
| 221 | leaq (%rsp), %rcx | 225 | leaq (%rsp), %rcx |
| 222 | 226 | ||
| 223 | SYM_INNER_LABEL(ftrace_regs_call, SYM_L_GLOBAL) | 227 | SYM_INNER_LABEL(ftrace_regs_call, SYM_L_GLOBAL) |
| 228 | ANNOTATE_NOENDBR | ||
| 224 | call ftrace_stub | 229 | call ftrace_stub |
| 225 | 230 | ||
| 226 | /* Copy flags back to SS, to restore them */ | 231 | /* Copy flags back to SS, to restore them */ |
| @@ -248,6 +253,7 @@ SYM_INNER_LABEL(ftrace_regs_call, SYM_L_GLOBAL) · 21 unmodified lines | |||
| 248 | */ | 253 | */ |
| 249 | testq %rax, %rax | 254 | testq %rax, %rax |
| 250 | SYM_INNER_LABEL(ftrace_regs_caller_jmp, SYM_L_GLOBAL) | 255 | SYM_INNER_LABEL(ftrace_regs_caller_jmp, SYM_L_GLOBAL) |
| 256 | ANNOTATE_NOENDBR | ||
| 251 | jnz 1f | 257 | jnz 1f |
| 252 | 258 | ||
| 253 | restore_mcount_regs | 259 | restore_mcount_regs |
| @@ -261,6 +267,7 @@ SYM_INNER_LABEL(ftrace_regs_caller_jmp, SYM_L_GLOBAL) · 7 unmodified lines | |||
| 261 | * to the return. | 267 | * to the return. |
| 262 | */ | 268 | */ |
| 263 | SYM_INNER_LABEL(ftrace_regs_caller_end, SYM_L_GLOBAL) | 269 | SYM_INNER_LABEL(ftrace_regs_caller_end, SYM_L_GLOBAL) |
| 270 | ANNOTATE_NOENDBR | ||
| 264 | jmp ftrace_epilogue | 271 | jmp ftrace_epilogue |
| 265 | 272 | ||
| 266 | /* Swap the flags with orig_rax */ | 273 | /* Swap the flags with orig_rax */ |
| @@ -284,6 +291,7 @@ SYM_FUNC_START(__fentry__) · 17 unmodified lines | |||
| 284 | jnz trace | 291 | jnz trace |
| 285 | 292 | ||
| 286 | SYM_INNER_LABEL(ftrace_stub, SYM_L_GLOBAL) | 293 | SYM_INNER_LABEL(ftrace_stub, SYM_L_GLOBAL) |
| 294 | ENDBR | ||
| 287 | RET | 295 | RET |
| 288 | 296 | ||
| 289 | trace: | 297 | trace: |
| @@ -307,7 +315,7 @@ EXPORT_SYMBOL(__fentry__) · 17 unmodified lines | |||
| 307 | 315 | ||
| 308 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 316 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
| 309 | SYM_FUNC_START(return_to_handler) | 317 | SYM_FUNC_START(return_to_handler) |
| 310 | subq $24, %rsp | 318 | subq $16, %rsp |
| 311 | 319 | ||
| 312 | /* Save the return values */ | 320 | /* Save the return values */ |
| 313 | movq %rax, (%rsp) | 321 | movq %rax, (%rsp) |
| @@ -319,7 +327,19 @@ SYM_FUNC_START(return_to_handler) · 5 unmodified lines | |||
| 319 | movq %rax, %rdi | 327 | movq %rax, %rdi |
| 320 | movq 8(%rsp), %rdx | 328 | movq 8(%rsp), %rdx |
| 321 | movq (%rsp), %rax | 329 | movq (%rsp), %rax |
| 322 | addq $24, %rsp | 330 | |
| 323 | JMP_NOSPEC rdi | 331 | addq $16, %rsp |
| 332 | /* | ||
| 333 | * Jump back to the old return address. This cannot be JMP_NOSPEC rdi | ||
| 334 | * since IBT would demand that contain ENDBR, which simply isn't so for | ||
| 335 | * return addresses. Use a retpoline here to keep the RSB balanced. | ||
| 336 | */ | ||
| 337 | ANNOTATE_INTRA_FUNCTION_CALL | ||
| 338 | call .Ldo_rop | ||
| 339 | int3 | ||
| 340 | .Ldo_rop: | ||
| 341 | mov %rdi, (%rsp) | ||
| 342 | UNWIND_HINT_FUNC | ||
| 343 | RET | ||
| 324 | SYM_FUNC_END(return_to_handler) | 344 | SYM_FUNC_END(return_to_handler) |
| 325 | #endif | 345 | #endif |
| @@ -99,6 +99,7 @@ SYM_CODE_END(startup_64) · 98 unmodified lines | |||
| 99 | 99 | ||
| 100 | SYM_CODE_START(secondary_startup_64) | 100 | SYM_CODE_START(secondary_startup_64) |
| 101 | UNWIND_HINT_EMPTY | 101 | UNWIND_HINT_EMPTY |
| 102 | ANNOTATE_NOENDBR | ||
| 102 | /* | 103 | /* |
| 103 | * At this point the CPU runs in 64bit mode CS.L = 1 CS.D = 0, | 104 | * At this point the CPU runs in 64bit mode CS.L = 1 CS.D = 0, |
| 104 | * and someone has loaded a mapped page table. | 105 | * and someone has loaded a mapped page table. |
| @@ -127,6 +128,7 @@ SYM_CODE_START(secondary_startup_64) · 22 unmodified lines | |||
| 127 | */ | 128 | */ |
| 128 | SYM_INNER_LABEL(secondary_startup_64_no_verify, SYM_L_GLOBAL) | 129 | SYM_INNER_LABEL(secondary_startup_64_no_verify, SYM_L_GLOBAL) |
| 129 | UNWIND_HINT_EMPTY | 130 | UNWIND_HINT_EMPTY |
| 131 | ANNOTATE_NOENDBR | ||
| 130 | 132 | ||
| 131 | /* | 133 | /* |
| 132 | * Retrieve the modifier (SME encryption mask if SME is active) to be | 134 | * Retrieve the modifier (SME encryption mask if SME is active) to be |
| @@ -192,6 +194,7 @@ SYM_INNER_LABEL(secondary_startup_64_no_verify, SYM_L_GLOBAL) · 59 unmodified lines | |||
| 192 | jmp *%rax | 194 | jmp *%rax |
| 193 | 1: | 195 | 1: |
| 194 | UNWIND_HINT_EMPTY | 196 | UNWIND_HINT_EMPTY |
| 197 | ANNOTATE_NOENDBR // above | ||
| 195 | 198 | ||
| 196 | /* | 199 | /* |
| 197 | * We must switch to a new descriptor in kernel space for the GDT | 200 | * We must switch to a new descriptor in kernel space for the GDT |
| @@ -299,6 +302,7 @@ SYM_INNER_LABEL(secondary_startup_64_no_verify, SYM_L_GLOBAL) · 101 unmodified lines | |||
| 299 | pushq %rax # target address in negative space | 302 | pushq %rax # target address in negative space |
| 300 | lretq | 303 | lretq |
| 301 | .Lafter_lret: | 304 | .Lafter_lret: |
| 305 | ANNOTATE_NOENDBR | ||
| 302 | SYM_CODE_END(secondary_startup_64) | 306 | SYM_CODE_END(secondary_startup_64) |
| 303 | 307 | ||
| 304 | #include "verify_cpu.S" | 308 | #include "verify_cpu.S" |
| @@ -328,6 +332,7 @@ SYM_CODE_END(start_cpu0) · 23 unmodified lines | |||
| 328 | */ | 332 | */ |
| 329 | SYM_CODE_START_NOALIGN(vc_boot_ghcb) | 333 | SYM_CODE_START_NOALIGN(vc_boot_ghcb) |
| 330 | UNWIND_HINT_IRET_REGS offset=8 | 334 | UNWIND_HINT_IRET_REGS offset=8 |
| 335 | ENDBR | ||
| 331 | 336 | ||
| 332 | /* Build pt_regs */ | 337 | /* Build pt_regs */ |
| 333 | PUSH_AND_CLEAR_REGS | 338 | PUSH_AND_CLEAR_REGS |
| @@ -345,7 +350,6 @@ SYM_CODE_START_NOALIGN(vc_boot_ghcb) · 11 unmodified lines | |||
| 345 | /* Remove Error Code */ | 350 | /* Remove Error Code */ |
| 346 | addq $8, %rsp | 351 | addq $8, %rsp |
| 347 | 352 | ||
| 348 | /* Pure iret required here - don't use INTERRUPT_RETURN */ | ||
| 349 | iretq | 353 | iretq |
| 350 | SYM_CODE_END(vc_boot_ghcb) | 354 | SYM_CODE_END(vc_boot_ghcb) |
| 351 | #endif | 355 | #endif |
| @@ -372,9 +376,11 @@ SYM_CODE_START(early_idt_handler_array) · 20 unmodified lines | |||
| 372 | .rept NUM_EXCEPTION_VECTORS | 376 | .rept NUM_EXCEPTION_VECTORS |
| 373 | .if ((EXCEPTION_ERRCODE_MASK >> i) & 1) == 0 | 377 | .if ((EXCEPTION_ERRCODE_MASK >> i) & 1) == 0 |
| 374 | UNWIND_HINT_IRET_REGS | 378 | UNWIND_HINT_IRET_REGS |
| 379 | ENDBR | ||
| 375 | pushq $0 # Dummy error code, to make stack frame uniform | 380 | pushq $0 # Dummy error code, to make stack frame uniform |
| 376 | .else | 381 | .else |
| 377 | UNWIND_HINT_IRET_REGS offset=8 | 382 | UNWIND_HINT_IRET_REGS offset=8 |
| 383 | ENDBR | ||
| 378 | .endif | 384 | .endif |
| 379 | pushq $i # 72(%rsp) Vector number | 385 | pushq $i # 72(%rsp) Vector number |
| 380 | jmp early_idt_handler_common | 386 | jmp early_idt_handler_common |
| @@ -382,10 +388,11 @@ SYM_CODE_START(early_idt_handler_array) · 1 unmodified line | |||
| 382 | i = i + 1 | 388 | i = i + 1 |
| 383 | .fill early_idt_handler_array + i*EARLY_IDT_HANDLER_SIZE - ., 1, 0xcc | 389 | .fill early_idt_handler_array + i*EARLY_IDT_HANDLER_SIZE - ., 1, 0xcc |
| 384 | .endr | 390 | .endr |
| 385 | UNWIND_HINT_IRET_REGS offset=16 | ||
| 386 | SYM_CODE_END(early_idt_handler_array) | 391 | SYM_CODE_END(early_idt_handler_array) |
| 392 | ANNOTATE_NOENDBR // early_idt_handler_array[NUM_EXCEPTION_VECTORS] | ||
| 387 | 393 | ||
| 388 | SYM_CODE_START_LOCAL(early_idt_handler_common) | 394 | SYM_CODE_START_LOCAL(early_idt_handler_common) |
| 395 | UNWIND_HINT_IRET_REGS offset=16 | ||
| 389 | /* | 396 | /* |
| 390 | * The stack is the hardware frame, an error code or zero, and the | 397 | * The stack is the hardware frame, an error code or zero, and the |
| 391 | * vector number. | 398 | * vector number. |
| @@ -426,11 +433,14 @@ SYM_CODE_END(early_idt_handler_common) · 34 unmodified lines | |||
| 426 | * early_idt_handler_array can't be used because it returns via the | 433 | * early_idt_handler_array can't be used because it returns via the |
| 427 | * paravirtualized INTERRUPT_RETURN and pv-ops don't work that early. | 434 | * paravirtualized INTERRUPT_RETURN and pv-ops don't work that early. |
| 428 | * | 435 | * |
| 436 | * XXX it does, fix this. | ||
| 437 | * | ||
| 429 | * This handler will end up in the .init.text section and not be | 438 | * This handler will end up in the .init.text section and not be |
| 430 | * available to boot secondary CPUs. | 439 | * available to boot secondary CPUs. |
| 431 | */ | 440 | */ |
| 432 | SYM_CODE_START_NOALIGN(vc_no_ghcb) | 441 | SYM_CODE_START_NOALIGN(vc_no_ghcb) |
| 433 | UNWIND_HINT_IRET_REGS offset=8 | 442 | UNWIND_HINT_IRET_REGS offset=8 |
| 443 | ENDBR | ||
| 434 | 444 | ||
| 435 | /* Build pt_regs */ | 445 | /* Build pt_regs */ |
| 436 | PUSH_AND_CLEAR_REGS | 446 | PUSH_AND_CLEAR_REGS |
| @@ -10,6 +10,7 @@ · 9 unmodified lines | |||
| 10 | #include <asm/proto.h> | 10 | #include <asm/proto.h> |
| 11 | #include <asm/desc.h> | 11 | #include <asm/desc.h> |
| 12 | #include <asm/hw_irq.h> | 12 | #include <asm/hw_irq.h> |
| 13 | #include <asm/idtentry.h> | ||
| 13 | 14 | ||
| 14 | #define DPL0 0x0 | 15 | #define DPL0 0x0 |
| 15 | #define DPL3 0x3 | 16 | #define DPL3 0x3 |
| @@ -103,6 +104,10 @@ static const __initconst struct idt_data def_idts[] = { · 87 unmodified lines | |||
| 103 | ISTG(X86_TRAP_MC, asm_exc_machine_check, IST_INDEX_MCE), | 104 | ISTG(X86_TRAP_MC, asm_exc_machine_check, IST_INDEX_MCE), |
| 104 | #endif | 105 | #endif |
| 105 | 106 | ||
| 107 | #ifdef CONFIG_X86_KERNEL_IBT | ||
| 108 | INTG(X86_TRAP_CP, asm_exc_control_protection), | ||
| 109 | #endif | ||
| 110 | |||
| 106 | #ifdef CONFIG_AMD_MEM_ENCRYPT | 111 | #ifdef CONFIG_AMD_MEM_ENCRYPT |
| 107 | ISTG(X86_TRAP_VC, asm_exc_vmm_communication, IST_INDEX_VC), | 112 | ISTG(X86_TRAP_VC, asm_exc_vmm_communication, IST_INDEX_VC), |
| 108 | #endif | 113 | #endif |
| @@ -272,7 +277,7 @@ void __init idt_setup_apic_and_irq_gates(void) · 163 unmodified lines | |||
| 272 | idt_setup_from_table(idt_table, apic_idts, ARRAY_SIZE(apic_idts), true); | 277 | idt_setup_from_table(idt_table, apic_idts, ARRAY_SIZE(apic_idts), true); |
| 273 | 278 | ||
| 274 | for_each_clear_bit_from(i, system_vectors, FIRST_SYSTEM_VECTOR) { | 279 | for_each_clear_bit_from(i, system_vectors, FIRST_SYSTEM_VECTOR) { |
| 275 | entry = irq_entries_start + 8 * (i - FIRST_EXTERNAL_VECTOR); | 280 | entry = irq_entries_start + IDT_ALIGN * (i - FIRST_EXTERNAL_VECTOR); |
| 276 | set_intr_gate(i, entry); | 281 | set_intr_gate(i, entry); |
| 277 | } | 282 | } |
| 278 | 283 | ||
| @@ -283,7 +288,7 @@ void __init idt_setup_apic_and_irq_gates(void) · 4 unmodified lines | |||
| 283 | * system_vectors bitmap. Otherwise they show up in | 288 | * system_vectors bitmap. Otherwise they show up in |
| 284 | * /proc/interrupts. | 289 | * /proc/interrupts. |
| 285 | */ | 290 | */ |
| 286 | entry = spurious_entries_start + 8 * (i - FIRST_SYSTEM_VECTOR); | 291 | entry = spurious_entries_start + IDT_ALIGN * (i - FIRST_SYSTEM_VECTOR); |
| 287 | set_intr_gate(i, entry); | 292 | set_intr_gate(i, entry); |
| 288 | } | 293 | } |
| 289 | #endif | 294 | #endif |
| @@ -52,6 +52,7 @@ · 51 unmodified lines | |||
| 52 | #include <asm/insn.h> | 52 | #include <asm/insn.h> |
| 53 | #include <asm/debugreg.h> | 53 | #include <asm/debugreg.h> |
| 54 | #include <asm/set_memory.h> | 54 | #include <asm/set_memory.h> |
| 55 | #include <asm/ibt.h> | ||
| 55 | 56 | ||
| 56 | #include "common.h" | 57 | #include "common.h" |
| 57 | 58 | ||
| @@ -193,17 +194,10 @@ static unsigned long · 135 unmodified lines | |||
| 193 | __recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr) | 194 | __recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr) |
| 194 | { | 195 | { |
| 195 | struct kprobe *kp; | 196 | struct kprobe *kp; |
| 196 | unsigned long faddr; | 197 | bool faddr; |
| 197 | 198 | ||
| 198 | kp = get_kprobe((void *)addr); | 199 | kp = get_kprobe((void *)addr); |
| 199 | faddr = ftrace_location(addr); | 200 | faddr = ftrace_location(addr) == addr; |
| 200 | /* | ||
| 201 | * Addresses inside the ftrace location are refused by | ||
| 202 | * arch_check_ftrace_location(). Something went terribly wrong | ||
| 203 | * if such an address is checked here. | ||
| 204 | */ | ||
| 205 | if (WARN_ON(faddr && faddr != addr)) | ||
| 206 | return 0UL; | ||
| 207 | /* | 201 | /* |
| 208 | * Use the current code if it is not modified by Kprobe | 202 | * Use the current code if it is not modified by Kprobe |
| 209 | * and it cannot be modified by ftrace. | 203 | * and it cannot be modified by ftrace. |
| @@ -301,6 +295,22 @@ static int can_probe(unsigned long paddr) · 91 unmodified lines | |||
| 301 | return (addr == paddr); | 295 | return (addr == paddr); |
| 302 | } | 296 | } |
| 303 | 297 | ||
| 298 | /* If x86 supports IBT (ENDBR) it must be skipped. */ | ||
| 299 | kprobe_opcode_t *arch_adjust_kprobe_addr(unsigned long addr, unsigned long offset, | ||
| 300 | bool *on_func_entry) | ||
| 301 | { | ||
| 302 | if (is_endbr(*(u32 *)addr)) { | ||
| 303 | *on_func_entry = !offset || offset == 4; | ||
| 304 | if (*on_func_entry) | ||
| 305 | offset = 4; | ||
| 306 | |||
| 307 | } else { | ||
| 308 | *on_func_entry = !offset; | ||
| 309 | } | ||
| 310 | |||
| 311 | return (kprobe_opcode_t *)(addr + offset); | ||
| 312 | } | ||
| 313 | |||
| 304 | /* | 314 | /* |
| 305 | * Copy an instruction with recovering modified instruction by kprobes | 315 | * Copy an instruction with recovering modified instruction by kprobes |
| 306 | * and adjust the displacement if the instruction uses the %rip-relative | 316 | * and adjust the displacement if the instruction uses the %rip-relative |
| @@ -1023,6 +1033,7 @@ asm( · 716 unmodified lines | |||
| 1023 | ".type __kretprobe_trampoline, @function\n" | 1033 | ".type __kretprobe_trampoline, @function\n" |
| 1024 | "__kretprobe_trampoline:\n" | 1034 | "__kretprobe_trampoline:\n" |
| 1025 | #ifdef CONFIG_X86_64 | 1035 | #ifdef CONFIG_X86_64 |
| 1036 | ANNOTATE_NOENDBR | ||
| 1026 | /* Push a fake return address to tell the unwinder it's a kretprobe. */ | 1037 | /* Push a fake return address to tell the unwinder it's a kretprobe. */ |
| 1027 | " pushq $__kretprobe_trampoline\n" | 1038 | " pushq $__kretprobe_trampoline\n" |
| 1028 | UNWIND_HINT_FUNC | 1039 | UNWIND_HINT_FUNC |
| @@ -1029,10 +1029,11 @@ asm( · 1028 unmodified lines | |||
| 1029 | ".global __raw_callee_save___kvm_vcpu_is_preempted;" | 1029 | ".global __raw_callee_save___kvm_vcpu_is_preempted;" |
| 1030 | ".type __raw_callee_save___kvm_vcpu_is_preempted, @function;" | 1030 | ".type __raw_callee_save___kvm_vcpu_is_preempted, @function;" |
| 1031 | "__raw_callee_save___kvm_vcpu_is_preempted:" | 1031 | "__raw_callee_save___kvm_vcpu_is_preempted:" |
| 1032 | ASM_ENDBR | ||
| 1032 | "movq __per_cpu_offset(,%rdi,8), %rax;" | 1033 | "movq __per_cpu_offset(,%rdi,8), %rax;" |
| 1033 | "cmpb $0, " __stringify(KVM_STEAL_TIME_preempted) "+steal_time(%rax);" | 1034 | "cmpb $0, " __stringify(KVM_STEAL_TIME_preempted) "+steal_time(%rax);" |
| 1034 | "setne %al;" | 1035 | "setne %al;" |
| 1035 | "ret;" | 1036 | ASM_RET |
| 1036 | ".size __raw_callee_save___kvm_vcpu_is_preempted, .-__raw_callee_save___kvm_vcpu_is_preempted;" | 1037 | ".size __raw_callee_save___kvm_vcpu_is_preempted, .-__raw_callee_save___kvm_vcpu_is_preempted;" |
| 1037 | ".popsection"); | 1038 | ".popsection"); |
| 1038 | 1039 | ||
| @@ -27,6 +27,7 @@ · 26 unmodified lines | |||
| 27 | #include <asm/kexec-bzimage64.h> | 27 | #include <asm/kexec-bzimage64.h> |
| 28 | #include <asm/setup.h> | 28 | #include <asm/setup.h> |
| 29 | #include <asm/set_memory.h> | 29 | #include <asm/set_memory.h> |
| 30 | #include <asm/cpu.h> | ||
| 30 | 31 | ||
| 31 | #ifdef CONFIG_ACPI | 32 | #ifdef CONFIG_ACPI |
| 32 | /* | 33 | /* |
| @@ -310,6 +311,7 @@ void machine_kexec(struct kimage *image) · 277 unmodified lines | |||
| 310 | /* Interrupts aren't acceptable while we reboot */ | 311 | /* Interrupts aren't acceptable while we reboot */ |
| 311 | local_irq_disable(); | 312 | local_irq_disable(); |
| 312 | hw_breakpoint_disable(); | 313 | hw_breakpoint_disable(); |
| 314 | cet_disable(); | ||
| 313 | 315 | ||
| 314 | if (image->preserve_context) { | 316 | if (image->preserve_context) { |
| 315 | #ifdef CONFIG_X86_IO_APIC | 317 | #ifdef CONFIG_X86_IO_APIC |
| @@ -325,7 +327,7 @@ void machine_kexec(struct kimage *image) · 9 unmodified lines | |||
| 325 | } | 327 | } |
| 326 | 328 | ||
| 327 | control_page = page_address(image->control_code_page) + PAGE_SIZE; | 329 | control_page = page_address(image->control_code_page) + PAGE_SIZE; |
| 328 | memcpy(control_page, relocate_kernel, KEXEC_CONTROL_CODE_MAX_SIZE); | 330 | __memcpy(control_page, relocate_kernel, KEXEC_CONTROL_CODE_MAX_SIZE); |
| 329 | 331 | ||
| 330 | page_list[PA_CONTROL_PAGE] = virt_to_phys(control_page); | 332 | page_list[PA_CONTROL_PAGE] = virt_to_phys(control_page); |
| 331 | page_list[VA_CONTROL_PAGE] = (unsigned long)control_page; | 333 | page_list[VA_CONTROL_PAGE] = (unsigned long)control_page; |
| @@ -253,7 +253,7 @@ int module_finalize(const Elf_Ehdr *hdr, · 252 unmodified lines | |||
| 253 | { | 253 | { |
| 254 | const Elf_Shdr *s, *text = NULL, *alt = NULL, *locks = NULL, | 254 | const Elf_Shdr *s, *text = NULL, *alt = NULL, *locks = NULL, |
| 255 | *para = NULL, *orc = NULL, *orc_ip = NULL, | 255 | *para = NULL, *orc = NULL, *orc_ip = NULL, |
| 256 | *retpolines = NULL; | 256 | *retpolines = NULL, *ibt_endbr = NULL; |
| 257 | char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; | 257 | char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; |
| 258 | 258 | ||
| 259 | for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { | 259 | for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { |
| @@ -271,6 +271,8 @@ int module_finalize(const Elf_Ehdr *hdr, · 11 unmodified lines | |||
| 271 | orc_ip = s; | 271 | orc_ip = s; |
| 272 | if (!strcmp(".retpoline_sites", secstrings + s->sh_name)) | 272 | if (!strcmp(".retpoline_sites", secstrings + s->sh_name)) |
| 273 | retpolines = s; | 273 | retpolines = s; |
| 274 | if (!strcmp(".ibt_endbr_seal", secstrings + s->sh_name)) | ||
| 275 | ibt_endbr = s; | ||
| 274 | } | 276 | } |
| 275 | 277 | ||
| 276 | /* | 278 | /* |
| @@ -290,6 +292,10 @@ int module_finalize(const Elf_Ehdr *hdr, · 13 unmodified lines | |||
| 290 | void *aseg = (void *)alt->sh_addr; | 292 | void *aseg = (void *)alt->sh_addr; |
| 291 | apply_alternatives(aseg, aseg + alt->sh_size); | 293 | apply_alternatives(aseg, aseg + alt->sh_size); |
| 292 | } | 294 | } |
| 295 | if (ibt_endbr) { | ||
| 296 | void *iseg = (void *)ibt_endbr->sh_addr; | ||
| 297 | apply_ibt_endbr(iseg, iseg + ibt_endbr->sh_size); | ||
| 298 | } | ||
| 293 | if (locks && text) { | 299 | if (locks && text) { |
| 294 | void *lseg = (void *)locks->sh_addr; | 300 | void *lseg = (void *)locks->sh_addr; |
| 295 | void *tseg = (void *)text->sh_addr; | 301 | void *tseg = (void *)text->sh_addr; |
| @@ -41,6 +41,7 @@ extern void _paravirt_nop(void); · 40 unmodified lines | |||
| 41 | asm (".pushsection .entry.text, \"ax\"\n" | 41 | asm (".pushsection .entry.text, \"ax\"\n" |
| 42 | ".global _paravirt_nop\n" | 42 | ".global _paravirt_nop\n" |
| 43 | "_paravirt_nop:\n\t" | 43 | "_paravirt_nop:\n\t" |
| 44 | ASM_ENDBR | ||
| 44 | ASM_RET | 45 | ASM_RET |
| 45 | ".size _paravirt_nop, . - _paravirt_nop\n\t" | 46 | ".size _paravirt_nop, . - _paravirt_nop\n\t" |
| 46 | ".type _paravirt_nop, @function\n\t" | 47 | ".type _paravirt_nop, @function\n\t" |
| @@ -50,6 +51,7 @@ asm (".pushsection .entry.text, \"ax\"\n" · 3 unmodified lines | |||
| 50 | asm (".pushsection .entry.text, \"ax\"\n" | 51 | asm (".pushsection .entry.text, \"ax\"\n" |
| 51 | ".global paravirt_ret0\n" | 52 | ".global paravirt_ret0\n" |
| 52 | "paravirt_ret0:\n\t" | 53 | "paravirt_ret0:\n\t" |
| 54 | ASM_ENDBR | ||
| 53 | "xor %" _ASM_AX ", %" _ASM_AX ";\n\t" | 55 | "xor %" _ASM_AX ", %" _ASM_AX ";\n\t" |
| 54 | ASM_RET | 56 | ASM_RET |
| 55 | ".size paravirt_ret0, . - paravirt_ret0\n\t" | 57 | ".size paravirt_ret0, . - paravirt_ret0\n\t" |
| @@ -69,29 +71,12 @@ noinstr void paravirt_BUG(void) · 13 unmodified lines | |||
| 69 | BUG(); | 71 | BUG(); |
| 70 | } | 72 | } |
| 71 | 73 | ||
| 72 | struct branch { | ||
| 73 | unsigned char opcode; | ||
| 74 | u32 delta; | ||
| 75 | } __attribute__((packed)); | ||
| 76 | |||
| 77 | static unsigned paravirt_patch_call(void *insn_buff, const void *target, | 74 | static unsigned paravirt_patch_call(void *insn_buff, const void *target, |
| 78 | unsigned long addr, unsigned len) | 75 | unsigned long addr, unsigned len) |
| 79 | { | 76 | { |
| 80 | const int call_len = 5; | 77 | __text_gen_insn(insn_buff, CALL_INSN_OPCODE, |
| 81 | struct branch *b = insn_buff; | 78 | (void *)addr, target, CALL_INSN_SIZE); |
| 82 | unsigned long delta = (unsigned long)target - (addr+call_len); | 79 | return CALL_INSN_SIZE; |
| 83 | |||
| 84 | if (len < call_len) { | ||
| 85 | pr_warn("paravirt: Failed to patch indirect CALL at %ps\n", (void *)addr); | ||
| 86 | /* Kernel might not be viable if patching fails, bail out: */ | ||
| 87 | BUG_ON(1); | ||
| 88 | } | ||
| 89 | |||
| 90 | b->opcode = 0xe8; /* call */ | ||
| 91 | b->delta = delta; | ||
| 92 | BUILD_BUG_ON(sizeof(*b) != call_len); | ||
| 93 | |||
| 94 | return call_len; | ||
| 95 | } | 80 | } |
| 96 | 81 | ||
| 97 | #ifdef CONFIG_PARAVIRT_XXL | 82 | #ifdef CONFIG_PARAVIRT_XXL |
| @@ -149,8 +134,6 @@ void paravirt_set_sched_clock(u64 (*func)(void)) · 51 unmodified lines | |||
| 149 | } | 134 | } |
| 150 | 135 | ||
| 151 | /* These are in entry.S */ | 136 | /* These are in entry.S */ |
| 152 | extern void native_iret(void); | ||
| 153 | |||
| 154 | static struct resource reserve_ioports = { | 137 | static struct resource reserve_ioports = { |
| 155 | .start = 0, | 138 | .start = 0, |
| 156 | .end = IO_SPACE_LIMIT, | 139 | .end = IO_SPACE_LIMIT, |
| @@ -414,8 +397,6 @@ struct paravirt_patch_template pv_ops = { · 257 unmodified lines | |||
| 414 | 397 | ||
| 415 | #ifdef CONFIG_PARAVIRT_XXL | 398 | #ifdef CONFIG_PARAVIRT_XXL |
| 416 | NOKPROBE_SYMBOL(native_load_idt); | 399 | NOKPROBE_SYMBOL(native_load_idt); |
| 417 | |||
| 418 | void (*paravirt_iret)(void) = native_iret; | ||
| 419 | #endif | 400 | #endif |
| 420 | 401 | ||
| 421 | EXPORT_SYMBOL(pv_ops); | 402 | EXPORT_SYMBOL(pv_ops); |
| @@ -747,7 +747,7 @@ bool xen_set_default_idle(void) · 746 unmodified lines | |||
| 747 | } | 747 | } |
| 748 | #endif | 748 | #endif |
| 749 | 749 | ||
| 750 | void stop_this_cpu(void *dummy) | 750 | void __noreturn stop_this_cpu(void *dummy) |
| 751 | { | 751 | { |
| 752 | local_irq_disable(); | 752 | local_irq_disable(); |
| 753 | /* | 753 | /* |
| @@ -681,7 +681,7 @@ void set_personality_64bit(void) · 680 unmodified lines | |||
| 681 | 681 | ||
| 682 | static void __set_personality_x32(void) | 682 | static void __set_personality_x32(void) |
| 683 | { | 683 | { |
| 684 | #ifdef CONFIG_X86_X32 | 684 | #ifdef CONFIG_X86_X32_ABI |
| 685 | if (current->mm) | 685 | if (current->mm) |
| 686 | current->mm->context.flags = 0; | 686 | current->mm->context.flags = 0; |
| 687 | 687 | ||
| @@ -42,6 +42,7 @@ · 41 unmodified lines | |||
| 42 | .code64 | 42 | .code64 |
| 43 | SYM_CODE_START_NOALIGN(relocate_kernel) | 43 | SYM_CODE_START_NOALIGN(relocate_kernel) |
| 44 | UNWIND_HINT_EMPTY | 44 | UNWIND_HINT_EMPTY |
| 45 | ANNOTATE_NOENDBR | ||
| 45 | /* | 46 | /* |
| 46 | * %rdi indirection_page | 47 | * %rdi indirection_page |
| 47 | * %rsi page_list | 48 | * %rsi page_list |
| @@ -114,6 +115,14 @@ SYM_CODE_START_LOCAL_NOALIGN(identity_mapped) · 66 unmodified lines | |||
| 114 | /* store the start address on the stack */ | 115 | /* store the start address on the stack */ |
| 115 | pushq %rdx | 116 | pushq %rdx |
| 116 | 117 | ||
| 118 | /* | ||
| 119 | * Clear X86_CR4_CET (if it was set) such that we can clear CR0_WP | ||
| 120 | * below. | ||
| 121 | */ | ||
| 122 | movq %cr4, %rax | ||
| 123 | andq $~(X86_CR4_CET), %rax | ||
| 124 | movq %rax, %cr4 | ||
| 125 | |||
| 117 | /* | 126 | /* |
| 118 | * Set cr0 to a known state: | 127 | * Set cr0 to a known state: |
| 119 | * - Paging enabled | 128 | * - Paging enabled |
| @@ -215,6 +224,7 @@ SYM_CODE_END(identity_mapped) · 95 unmodified lines | |||
| 215 | 224 | ||
| 216 | SYM_CODE_START_LOCAL_NOALIGN(virtual_mapped) | 225 | SYM_CODE_START_LOCAL_NOALIGN(virtual_mapped) |
| 217 | UNWIND_HINT_EMPTY | 226 | UNWIND_HINT_EMPTY |
| 227 | ANNOTATE_NOENDBR // RET target, above | ||
| 218 | movq RSP(%r8), %rsp | 228 | movq RSP(%r8), %rsp |
| 219 | movq CR4(%r8), %rax | 229 | movq CR4(%r8), %rax |
| 220 | movq %rax, %cr4 | 230 | movq %rax, %cr4 |
| @@ -210,6 +210,81 @@ DEFINE_IDTENTRY(exc_overflow) · 209 unmodified lines | |||
| 210 | do_error_trap(regs, 0, "overflow", X86_TRAP_OF, SIGSEGV, 0, NULL); | 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 | #ifdef CONFIG_X86_F00F_BUG | 288 | #ifdef CONFIG_X86_F00F_BUG |
| 214 | void handle_invalid_op(struct pt_regs *regs) | 289 | void handle_invalid_op(struct pt_regs *regs) |
| 215 | #else | 290 | #else |
| @@ -285,6 +285,15 @@ SECTIONS · 284 unmodified lines | |||
| 285 | } | 285 | } |
| 286 | #endif | 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 | * struct alt_inst entries. From the header (alternative.h): | 298 | * struct alt_inst entries. From the header (alternative.h): |
| 290 | * "Alternative instructions for different CPU types or capabilities" | 299 | * "Alternative instructions for different CPU types or capabilities" |
| @@ -24,6 +24,7 @@ · 23 unmodified lines | |||
| 24 | #include <linux/stringify.h> | 24 | #include <linux/stringify.h> |
| 25 | #include <asm/debugreg.h> | 25 | #include <asm/debugreg.h> |
| 26 | #include <asm/nospec-branch.h> | 26 | #include <asm/nospec-branch.h> |
| 27 | #include <asm/ibt.h> | ||
| 27 | 28 | ||
| 28 | #include "x86.h" | 29 | #include "x86.h" |
| 29 | #include "tss.h" | 30 | #include "tss.h" |
| @@ -189,7 +190,7 @@ · 159 unmodified lines | |||
| 189 | #define X16(x...) X8(x), X8(x) | 190 | #define X16(x...) X8(x), X8(x) |
| 190 | 191 | ||
| 191 | #define NR_FASTOP (ilog2(sizeof(ulong)) + 1) | 192 | #define NR_FASTOP (ilog2(sizeof(ulong)) + 1) |
| 192 | #define FASTOP_SIZE 8 | 193 | #define FASTOP_SIZE (8 * (1 + HAS_KERNEL_IBT)) |
| 193 | 194 | ||
| 194 | struct opcode { | 195 | struct opcode { |
| 195 | u64 flags; | 196 | u64 flags; |
| @@ -311,7 +312,8 @@ static int fastop(struct x86_emulate_ctxt *ctxt, fastop_t fop); · 115 unmodified lines | |||
| 311 | #define __FOP_FUNC(name) \ | 312 | #define __FOP_FUNC(name) \ |
| 312 | ".align " __stringify(FASTOP_SIZE) " \n\t" \ | 313 | ".align " __stringify(FASTOP_SIZE) " \n\t" \ |
| 313 | ".type " name ", @function \n\t" \ | 314 | ".type " name ", @function \n\t" \ |
| 314 | name ":\n\t" | 315 | name ":\n\t" \ |
| 316 | ASM_ENDBR | ||
| 315 | 317 | ||
| 316 | #define FOP_FUNC(name) \ | 318 | #define FOP_FUNC(name) \ |
| 317 | __FOP_FUNC(#name) | 319 | __FOP_FUNC(#name) |
| @@ -433,21 +435,23 @@ static int fastop(struct x86_emulate_ctxt *ctxt, fastop_t fop); · 115 unmodified lines | |||
| 433 | /* | 435 | /* |
| 434 | * Depending on .config the SETcc functions look like: | 436 | * Depending on .config the SETcc functions look like: |
| 435 | * | 437 | * |
| 438 | * ENDBR [4 bytes; CONFIG_X86_KERNEL_IBT] | ||
| 436 | * SETcc %al [3 bytes] | 439 | * SETcc %al [3 bytes] |
| 437 | * RET [1 byte] | 440 | * RET [1 byte] |
| 438 | * INT3 [1 byte; CONFIG_SLS] | 441 | * INT3 [1 byte; CONFIG_SLS] |
| 439 | * | 442 | * |
| 440 | * Which gives possible sizes 4 or 5. When rounded up to the | 443 | * Which gives possible sizes 4, 5, 8 or 9. When rounded up to the |
| 441 | * next power-of-two alignment they become 4 or 8. | 444 | * next power-of-two alignment they become 4, 8 or 16 resp. |
| 442 | */ | 445 | */ |
| 443 | #define SETCC_LENGTH (4 + IS_ENABLED(CONFIG_SLS)) | 446 | #define SETCC_LENGTH (ENDBR_INSN_SIZE + 4 + IS_ENABLED(CONFIG_SLS)) |
| 444 | #define SETCC_ALIGN (4 << IS_ENABLED(CONFIG_SLS)) | 447 | #define SETCC_ALIGN (4 << IS_ENABLED(CONFIG_SLS) << HAS_KERNEL_IBT) |
| 445 | static_assert(SETCC_LENGTH <= SETCC_ALIGN); | 448 | static_assert(SETCC_LENGTH <= SETCC_ALIGN); |
| 446 | 449 | ||
| 447 | #define FOP_SETCC(op) \ | 450 | #define FOP_SETCC(op) \ |
| 448 | ".align " __stringify(SETCC_ALIGN) " \n\t" \ | 451 | ".align " __stringify(SETCC_ALIGN) " \n\t" \ |
| 449 | ".type " #op ", @function \n\t" \ | 452 | ".type " #op ", @function \n\t" \ |
| 450 | #op ": \n\t" \ | 453 | #op ": \n\t" \ |
| 454 | ASM_ENDBR \ | ||
| 451 | #op " %al \n\t" \ | 455 | #op " %al \n\t" \ |
| 452 | __FOP_RET(#op) | 456 | __FOP_RET(#op) |
| 453 | 457 | ||
| @@ -3,6 +3,7 @@ · 2 unmodified lines | |||
| 3 | #include <linux/linkage.h> | 3 | #include <linux/linkage.h> |
| 4 | #include <linux/error-injection.h> | 4 | #include <linux/error-injection.h> |
| 5 | #include <linux/kprobes.h> | 5 | #include <linux/kprobes.h> |
| 6 | #include <linux/objtool.h> | ||
| 6 | 7 | ||
| 7 | asmlinkage void just_return_func(void); | 8 | asmlinkage void just_return_func(void); |
| 8 | 9 | ||
| @@ -11,6 +12,7 @@ asm( · 2 unmodified lines | |||
| 11 | ".type just_return_func, @function\n" | 12 | ".type just_return_func, @function\n" |
| 12 | ".globl just_return_func\n" | 13 | ".globl just_return_func\n" |
| 13 | "just_return_func:\n" | 14 | "just_return_func:\n" |
| 15 | ANNOTATE_NOENDBR | ||
| 14 | ASM_RET | 16 | ASM_RET |
| 15 | ".size just_return_func, .-just_return_func\n" | 17 | ".size just_return_func, .-just_return_func\n" |
| 16 | ); | 18 | ); |
| @@ -55,6 +55,7 @@ SYM_INNER_LABEL(__x86_indirect_thunk_\reg, SYM_L_GLOBAL) · 54 unmodified lines | |||
| 55 | 55 | ||
| 56 | .align RETPOLINE_THUNK_SIZE | 56 | .align RETPOLINE_THUNK_SIZE |
| 57 | SYM_CODE_START(__x86_indirect_thunk_array) | 57 | SYM_CODE_START(__x86_indirect_thunk_array) |
| 58 | ANNOTATE_NOENDBR // apply_retpolines | ||
| 58 | 59 | ||
| 59 | #define GEN(reg) THUNK reg | 60 | #define GEN(reg) THUNK reg |
| 60 | #include <asm/GEN-for-each-reg.h> | 61 | #include <asm/GEN-for-each-reg.h> |
| @@ -46,6 +46,12 @@ static u8 *emit_code(u8 *ptr, u32 bytes, unsigned int len) · 45 unmodified lines | |||
| 46 | #define EMIT4_off32(b1, b2, b3, b4, off) \ | 46 | #define EMIT4_off32(b1, b2, b3, b4, off) \ |
| 47 | do { EMIT4(b1, b2, b3, b4); EMIT(off, 4); } while (0) | 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 | static bool is_imm8(int value) | 55 | static bool is_imm8(int value) |
| 50 | { | 56 | { |
| 51 | return value <= 127 && value >= -128; | 57 | return value <= 127 && value >= -128; |
| @@ -241,7 +247,7 @@ struct jit_context { · 189 unmodified lines | |||
| 241 | /* Number of bytes emit_patch() needs to generate instructions */ | 247 | /* Number of bytes emit_patch() needs to generate instructions */ |
| 242 | #define X86_PATCH_SIZE 5 | 248 | #define X86_PATCH_SIZE 5 |
| 243 | /* Number of bytes that will be skipped on tailcall */ | 249 | /* Number of bytes that will be skipped on tailcall */ |
| 244 | #define X86_TAIL_CALL_OFFSET 11 | 250 | #define X86_TAIL_CALL_OFFSET (11 + ENDBR_INSN_SIZE) |
| 245 | 251 | ||
| 246 | static void push_callee_regs(u8 **pprog, bool *callee_regs_used) | 252 | static void push_callee_regs(u8 **pprog, bool *callee_regs_used) |
| 247 | { | 253 | { |
| @@ -286,6 +292,7 @@ static void emit_prologue(u8 **pprog, u32 stack_depth, bool ebpf_from_cbpf, · 38 unmodified lines | |||
| 286 | /* BPF trampoline can be made to work without these nops, | 292 | /* BPF trampoline can be made to work without these nops, |
| 287 | * but let's waste 5 bytes for now and optimize later | 293 | * but let's waste 5 bytes for now and optimize later |
| 288 | */ | 294 | */ |
| 295 | EMIT_ENDBR(); | ||
| 289 | memcpy(prog, x86_nops[5], X86_PATCH_SIZE); | 296 | memcpy(prog, x86_nops[5], X86_PATCH_SIZE); |
| 290 | prog += X86_PATCH_SIZE; | 297 | prog += X86_PATCH_SIZE; |
| 291 | if (!ebpf_from_cbpf) { | 298 | if (!ebpf_from_cbpf) { |
| @@ -296,6 +303,10 @@ static void emit_prologue(u8 **pprog, u32 stack_depth, bool ebpf_from_cbpf, · 4 unmodified lines | |||
| 296 | } | 303 | } |
| 297 | EMIT1(0x55); /* push rbp */ | 304 | EMIT1(0x55); /* push rbp */ |
| 298 | EMIT3(0x48, 0x89, 0xE5); /* mov rbp, rsp */ | 305 | EMIT3(0x48, 0x89, 0xE5); /* mov rbp, rsp */ |
| 306 | |||
| 307 | /* X86_TAIL_CALL_OFFSET is here */ | ||
| 308 | EMIT_ENDBR(); | ||
| 309 | |||
| 299 | /* sub rsp, rounded_stack_depth */ | 310 | /* sub rsp, rounded_stack_depth */ |
| 300 | if (stack_depth) | 311 | if (stack_depth) |
| 301 | EMIT3_off32(0x48, 0x81, 0xEC, round_up(stack_depth, 8)); | 312 | EMIT3_off32(0x48, 0x81, 0xEC, round_up(stack_depth, 8)); |
| @@ -380,6 +391,13 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t, · 78 unmodified lines | |||
| 380 | /* BPF poking in modules is not supported */ | 391 | /* BPF poking in modules is not supported */ |
| 381 | return -EINVAL; | 392 | return -EINVAL; |
| 382 | 393 | ||
| 394 | /* | ||
| 395 | * See emit_prologue(), for IBT builds the trampoline hook is preceded | ||
| 396 | * with an ENDBR instruction. | ||
| 397 | */ | ||
| 398 | if (is_endbr(*(u32 *)ip)) | ||
| 399 | ip += ENDBR_INSN_SIZE; | ||
| 400 | |||
| 383 | return __bpf_arch_text_poke(ip, t, old_addr, new_addr); | 401 | return __bpf_arch_text_poke(ip, t, old_addr, new_addr); |
| 384 | } | 402 | } |
| 385 | 403 | ||
| @@ -2013,14 +2031,18 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *i · 1627 unmodified lines | |||
| 2013 | 2031 | ||
| 2014 | ip_off = stack_size; | 2032 | ip_off = stack_size; |
| 2015 | 2033 | ||
| 2016 | if (flags & BPF_TRAMP_F_SKIP_FRAME) | 2034 | if (flags & BPF_TRAMP_F_SKIP_FRAME) { |
| 2017 | /* skip patched call instruction and point orig_call to actual | 2035 | /* skip patched call instruction and point orig_call to actual |
| 2018 | * body of the kernel function. | 2036 | * body of the kernel function. |
| 2019 | */ | 2037 | */ |
| 2038 | if (is_endbr(*(u32 *)orig_call)) | ||
| 2039 | orig_call += ENDBR_INSN_SIZE; | ||
| 2020 | orig_call += X86_PATCH_SIZE; | 2040 | orig_call += X86_PATCH_SIZE; |
| 2041 | } | ||
| 2021 | 2042 | ||
| 2022 | prog = image; | 2043 | prog = image; |
| 2023 | 2044 | ||
| 2045 | EMIT_ENDBR(); | ||
| 2024 | EMIT1(0x55); /* push rbp */ | 2046 | EMIT1(0x55); /* push rbp */ |
| 2025 | EMIT3(0x48, 0x89, 0xE5); /* mov rbp, rsp */ | 2047 | EMIT3(0x48, 0x89, 0xE5); /* mov rbp, rsp */ |
| 2026 | EMIT4(0x48, 0x83, 0xEC, stack_size); /* sub rsp, stack_size */ | 2048 | EMIT4(0x48, 0x83, 0xEC, stack_size); /* sub rsp, stack_size */ |
| @@ -1,5 +1,4 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
| 2 | OBJECT_FILES_NON_STANDARD_efi_thunk_$(BITS).o := y | ||
| 3 | KASAN_SANITIZE := n | 2 | KASAN_SANITIZE := n |
| 4 | GCOV_PROFILE := n | 3 | GCOV_PROFILE := n |
| 5 | 4 | ||
| @@ -20,12 +20,14 @@ · 19 unmodified lines | |||
| 20 | */ | 20 | */ |
| 21 | 21 | ||
| 22 | #include <linux/linkage.h> | 22 | #include <linux/linkage.h> |
| 23 | #include <linux/objtool.h> | ||
| 23 | #include <asm/page_types.h> | 24 | #include <asm/page_types.h> |
| 24 | #include <asm/segment.h> | 25 | #include <asm/segment.h> |
| 25 | 26 | ||
| 26 | .text | 27 | .text |
| 27 | .code64 | 28 | .code64 |
| 28 | SYM_CODE_START(__efi64_thunk) | 29 | SYM_FUNC_START(__efi64_thunk) |
| 30 | STACK_FRAME_NON_STANDARD __efi64_thunk | ||
| 29 | push %rbp | 31 | push %rbp |
| 30 | push %rbx | 32 | push %rbx |
| 31 | 33 | ||
| @@ -79,7 +81,7 @@ SYM_CODE_START(__efi64_thunk) · 47 unmodified lines | |||
| 79 | 2: pushl $__KERNEL_CS | 81 | 2: pushl $__KERNEL_CS |
| 80 | pushl %ebp | 82 | pushl %ebp |
| 81 | lret | 83 | lret |
| 82 | SYM_CODE_END(__efi64_thunk) | 84 | SYM_FUNC_END(__efi64_thunk) |
| 83 | 85 | ||
| 84 | .bss | 86 | .bss |
| 85 | .balign 8 | 87 | .balign 8 |
| @@ -624,6 +624,9 @@ static struct trap_array_entry trap_array[] = { · 623 unmodified lines | |||
| 624 | TRAP_ENTRY(exc_coprocessor_error, false ), | 624 | TRAP_ENTRY(exc_coprocessor_error, false ), |
| 625 | TRAP_ENTRY(exc_alignment_check, false ), | 625 | TRAP_ENTRY(exc_alignment_check, false ), |
| 626 | TRAP_ENTRY(exc_simd_coprocessor_error, false ), | 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 | static bool __ref get_trap_addr(void **addr, unsigned int ist) | 632 | static bool __ref get_trap_addr(void **addr, unsigned int ist) |
| @@ -1177,6 +1180,8 @@ static void __init xen_domu_set_legacy_features(void) · 547 unmodified lines | |||
| 1177 | x86_platform.legacy.rtc = 0; | 1180 | x86_platform.legacy.rtc = 0; |
| 1178 | } | 1181 | } |
| 1179 | 1182 | ||
| 1183 | extern void early_xen_iret_patch(void); | ||
| 1184 | |||
| 1180 | /* First C function to be called on Xen boot */ | 1185 | /* First C function to be called on Xen boot */ |
| 1181 | asmlinkage __visible void __init xen_start_kernel(void) | 1186 | asmlinkage __visible void __init xen_start_kernel(void) |
| 1182 | { | 1187 | { |
| @@ -1187,6 +1192,10 @@ asmlinkage __visible void __init xen_start_kernel(void) · 4 unmodified lines | |||
| 1187 | if (!xen_start_info) | 1192 | if (!xen_start_info) |
| 1188 | return; | 1193 | return; |
| 1189 | 1194 | ||
| 1195 | __text_gen_insn(&early_xen_iret_patch, | ||
| 1196 | JMP32_INSN_OPCODE, &early_xen_iret_patch, &xen_iret, | ||
| 1197 | JMP32_INSN_SIZE); | ||
| 1198 | |||
| 1190 | xen_domain_type = XEN_PV_DOMAIN; | 1199 | xen_domain_type = XEN_PV_DOMAIN; |
| 1191 | xen_start_flags = xen_start_info->flags; | 1200 | xen_start_flags = xen_start_info->flags; |
| 1192 | 1201 | ||
| @@ -1195,7 +1204,6 @@ asmlinkage __visible void __init xen_start_kernel(void) · 2 unmodified lines | |||
| 1195 | /* Install Xen paravirt ops */ | 1204 | /* Install Xen paravirt ops */ |
| 1196 | pv_info = xen_info; | 1205 | pv_info = xen_info; |
| 1197 | pv_ops.cpu = xen_cpu_ops.cpu; | 1206 | pv_ops.cpu = xen_cpu_ops.cpu; |
| 1198 | paravirt_iret = xen_iret; | ||
| 1199 | xen_init_irq_ops(); | 1207 | xen_init_irq_ops(); |
| 1200 | 1208 | ||
| 1201 | /* | 1209 | /* |
| @@ -122,6 +122,7 @@ SYM_FUNC_END(xen_read_cr2_direct); · 121 unmodified lines | |||
| 122 | .macro xen_pv_trap name | 122 | .macro xen_pv_trap name |
| 123 | SYM_CODE_START(xen_\name) | 123 | SYM_CODE_START(xen_\name) |
| 124 | UNWIND_HINT_EMPTY | 124 | UNWIND_HINT_EMPTY |
| 125 | ENDBR | ||
| 125 | pop %rcx | 126 | pop %rcx |
| 126 | pop %r11 | 127 | pop %r11 |
| 127 | jmp \name | 128 | jmp \name |
| @@ -147,6 +148,9 @@ xen_pv_trap asm_exc_page_fault · 19 unmodified lines | |||
| 147 | xen_pv_trap asm_exc_spurious_interrupt_bug | 148 | xen_pv_trap asm_exc_spurious_interrupt_bug |
| 148 | xen_pv_trap asm_exc_coprocessor_error | 149 | xen_pv_trap asm_exc_coprocessor_error |
| 149 | xen_pv_trap asm_exc_alignment_check | 150 | xen_pv_trap asm_exc_alignment_check |
| 151 | #ifdef CONFIG_X86_KERNEL_IBT | ||
| 152 | xen_pv_trap asm_exc_control_protection | ||
| 153 | #endif | ||
| 150 | #ifdef CONFIG_X86_MCE | 154 | #ifdef CONFIG_X86_MCE |
| 151 | xen_pv_trap asm_xenpv_exc_machine_check | 155 | xen_pv_trap asm_xenpv_exc_machine_check |
| 152 | #endif /* CONFIG_X86_MCE */ | 156 | #endif /* CONFIG_X86_MCE */ |
| @@ -162,6 +166,7 @@ SYM_CODE_START(xen_early_idt_handler_array) · 9 unmodified lines | |||
| 162 | i = 0 | 166 | i = 0 |
| 163 | .rept NUM_EXCEPTION_VECTORS | 167 | .rept NUM_EXCEPTION_VECTORS |
| 164 | UNWIND_HINT_EMPTY | 168 | UNWIND_HINT_EMPTY |
| 169 | ENDBR | ||
| 165 | pop %rcx | 170 | pop %rcx |
| 166 | pop %r11 | 171 | pop %r11 |
| 167 | jmp early_idt_handler_array + i*EARLY_IDT_HANDLER_SIZE | 172 | jmp early_idt_handler_array + i*EARLY_IDT_HANDLER_SIZE |
| @@ -189,6 +194,7 @@ hypercall_iret = hypercall_page + __HYPERVISOR_iret * 32 · 21 unmodified lines | |||
| 189 | */ | 194 | */ |
| 190 | SYM_CODE_START(xen_iret) | 195 | SYM_CODE_START(xen_iret) |
| 191 | UNWIND_HINT_EMPTY | 196 | UNWIND_HINT_EMPTY |
| 197 | ANNOTATE_NOENDBR | ||
| 192 | pushq $0 | 198 | pushq $0 |
| 193 | jmp hypercall_iret | 199 | jmp hypercall_iret |
| 194 | SYM_CODE_END(xen_iret) | 200 | SYM_CODE_END(xen_iret) |
| @@ -230,6 +236,7 @@ SYM_CODE_END(xenpv_restore_regs_and_return_to_usermode) · 35 unmodified lines | |||
| 230 | /* Normal 64-bit system call target */ | 236 | /* Normal 64-bit system call target */ |
| 231 | SYM_CODE_START(xen_syscall_target) | 237 | SYM_CODE_START(xen_syscall_target) |
| 232 | UNWIND_HINT_EMPTY | 238 | UNWIND_HINT_EMPTY |
| 239 | ENDBR | ||
| 233 | popq %rcx | 240 | popq %rcx |
| 234 | popq %r11 | 241 | popq %r11 |
| 235 | 242 | ||
| @@ -249,6 +256,7 @@ SYM_CODE_END(xen_syscall_target) · 13 unmodified lines | |||
| 249 | /* 32-bit compat syscall target */ | 256 | /* 32-bit compat syscall target */ |
| 250 | SYM_CODE_START(xen_syscall32_target) | 257 | SYM_CODE_START(xen_syscall32_target) |
| 251 | UNWIND_HINT_EMPTY | 258 | UNWIND_HINT_EMPTY |
| 259 | ENDBR | ||
| 252 | popq %rcx | 260 | popq %rcx |
| 253 | popq %r11 | 261 | popq %r11 |
| 254 | 262 | ||
| @@ -266,6 +274,7 @@ SYM_CODE_END(xen_syscall32_target) · 11 unmodified lines | |||
| 266 | /* 32-bit compat sysenter target */ | 274 | /* 32-bit compat sysenter target */ |
| 267 | SYM_CODE_START(xen_sysenter_target) | 275 | SYM_CODE_START(xen_sysenter_target) |
| 268 | UNWIND_HINT_EMPTY | 276 | UNWIND_HINT_EMPTY |
| 277 | ENDBR | ||
| 269 | /* | 278 | /* |
| 270 | * NB: Xen is polite and clears TF from EFLAGS for us. This means | 279 | * NB: Xen is polite and clears TF from EFLAGS for us. This means |
| 271 | * that we don't need to guard against single step exceptions here. | 280 | * that we don't need to guard against single step exceptions here. |
| @@ -289,6 +298,7 @@ SYM_CODE_END(xen_sysenter_target) · 17 unmodified lines | |||
| 289 | SYM_CODE_START(xen_syscall32_target) | 298 | SYM_CODE_START(xen_syscall32_target) |
| 290 | SYM_CODE_START(xen_sysenter_target) | 299 | SYM_CODE_START(xen_sysenter_target) |
| 291 | UNWIND_HINT_EMPTY | 300 | UNWIND_HINT_EMPTY |
| 301 | ENDBR | ||
| 292 | lea 16(%rsp), %rsp /* strip %rcx, %r11 */ | 302 | lea 16(%rsp), %rsp /* strip %rcx, %r11 */ |
| 293 | mov $-ENOSYS, %rax | 303 | mov $-ENOSYS, %rax |
| 294 | pushq $0 | 304 | pushq $0 |
| @@ -25,8 +25,12 @@ · 24 unmodified lines | |||
| 25 | SYM_CODE_START(hypercall_page) | 25 | SYM_CODE_START(hypercall_page) |
| 26 | .rept (PAGE_SIZE / 32) | 26 | .rept (PAGE_SIZE / 32) |
| 27 | UNWIND_HINT_FUNC | 27 | UNWIND_HINT_FUNC |
| 28 | .skip 31, 0x90 | 28 | ANNOTATE_NOENDBR |
| 29 | RET | 29 | ret |
| 30 | /* | ||
| 31 | * Xen will write the hypercall page, and sort out ENDBR. | ||
| 32 | */ | ||
| 33 | .skip 31, 0xcc | ||
| 30 | .endr | 34 | .endr |
| 31 | 35 | ||
| 32 | #define HYPERCALL(n) \ | 36 | #define HYPERCALL(n) \ |
| @@ -74,6 +78,7 @@ SYM_CODE_END(startup_xen) · 41 unmodified lines | |||
| 74 | .pushsection .text | 78 | .pushsection .text |
| 75 | SYM_CODE_START(asm_cpu_bringup_and_idle) | 79 | SYM_CODE_START(asm_cpu_bringup_and_idle) |
| 76 | UNWIND_HINT_EMPTY | 80 | UNWIND_HINT_EMPTY |
| 81 | ENDBR | ||
| 77 | 82 | ||
| 78 | call cpu_bringup_and_idle | 83 | call cpu_bringup_and_idle |
| 79 | SYM_CODE_END(asm_cpu_bringup_and_idle) | 84 | SYM_CODE_END(asm_cpu_bringup_and_idle) |
| @@ -170,7 +170,7 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, · 169 unmodified lines | |||
| 170 | #else | 170 | #else |
| 171 | if (flags & FUSE_IOCTL_COMPAT) { | 171 | if (flags & FUSE_IOCTL_COMPAT) { |
| 172 | inarg.flags |= FUSE_IOCTL_32BIT; | 172 | inarg.flags |= FUSE_IOCTL_32BIT; |
| 173 | #ifdef CONFIG_X86_X32 | 173 | #ifdef CONFIG_X86_X32_ABI |
| 174 | if (in_x32_syscall()) | 174 | if (in_x32_syscall()) |
| 175 | inarg.flags |= FUSE_IOCTL_COMPAT_X32; | 175 | inarg.flags |= FUSE_IOCTL_COMPAT_X32; |
| 176 | #endif | 176 | #endif |
| @@ -217,7 +217,7 @@ xfs_compat_ioc_fsbulkstat( · 216 unmodified lines | |||
| 217 | inumbers_fmt_pf inumbers_func = xfs_fsinumbers_fmt_compat; | 217 | inumbers_fmt_pf inumbers_func = xfs_fsinumbers_fmt_compat; |
| 218 | bulkstat_one_fmt_pf bs_one_func = xfs_fsbulkstat_one_fmt_compat; | 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 | if (in_x32_syscall()) { | 221 | if (in_x32_syscall()) { |
| 222 | /* | 222 | /* |
| 223 | * ... but on x32 the input xfs_fsop_bulkreq has pointers | 223 | * ... but on x32 the input xfs_fsop_bulkreq has pointers |
| @@ -394,6 +394,7 @@ · 393 unmodified lines | |||
| 394 | KEEP(*(__jump_table)) \ | 394 | KEEP(*(__jump_table)) \ |
| 395 | __stop___jump_table = .; | 395 | __stop___jump_table = .; |
| 396 | 396 | ||
| 397 | #ifdef CONFIG_HAVE_STATIC_CALL_INLINE | ||
| 397 | #define STATIC_CALL_DATA \ | 398 | #define STATIC_CALL_DATA \ |
| 398 | . = ALIGN(8); \ | 399 | . = ALIGN(8); \ |
| 399 | __start_static_call_sites = .; \ | 400 | __start_static_call_sites = .; \ |
| @@ -402,6 +403,9 @@ · 2 unmodified lines | |||
| 402 | __start_static_call_tramp_key = .; \ | 403 | __start_static_call_tramp_key = .; \ |
| 403 | KEEP(*(.static_call_tramp_key)) \ | 404 | KEEP(*(.static_call_tramp_key)) \ |
| 404 | __stop_static_call_tramp_key = .; | 405 | __stop_static_call_tramp_key = .; |
| 406 | #else | ||
| 407 | #define STATIC_CALL_DATA | ||
| 408 | #endif | ||
| 405 | 409 | ||
| 406 | /* | 410 | /* |
| 407 | * Allow architectures to handle ro_after_init data on their | 411 | * Allow architectures to handle ro_after_init data on their |
| @@ -34,8 +34,17 @@ static inline void cfi_module_remove(struct module *mod, unsigned long base_addr · 33 unmodified lines | |||
| 34 | 34 | ||
| 35 | #else /* !CONFIG_CFI_CLANG */ | 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 | #endif /* CONFIG_CFI_CLANG */ | 44 | #endif /* CONFIG_CFI_CLANG */ |
| 40 | 45 | ||
| 46 | #ifndef __CFI_ADDRESSABLE | ||
| 47 | #define __CFI_ADDRESSABLE(fn, __attr) | ||
| 48 | #endif | ||
| 49 | |||
| 41 | #endif /* _LINUX_CFI_H */ | 50 | #endif /* _LINUX_CFI_H */ |
| @@ -125,18 +125,11 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val, · 124 unmodified lines | |||
| 125 | }) | 125 | }) |
| 126 | #define annotate_unreachable() __annotate_unreachable(__COUNTER__) | 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 | /* Annotate a C jump table to allow objtool to follow the code flow */ | 128 | /* Annotate a C jump table to allow objtool to follow the code flow */ |
| 135 | #define __annotate_jump_table __section(".rodata..c_jump_table") | 129 | #define __annotate_jump_table __section(".rodata..c_jump_table") |
| 136 | 130 | ||
| 137 | #else | 131 | #else |
| 138 | #define annotate_unreachable() | 132 | #define annotate_unreachable() |
| 139 | # define ASM_REACHABLE | ||
| 140 | #define __annotate_jump_table | 133 | #define __annotate_jump_table |
| 141 | #endif | 134 | #endif |
| 142 | 135 | ||
| @@ -176,7 +176,7 @@ extern int set_cred_ucounts(struct cred *); · 175 unmodified lines | |||
| 176 | * check for validity of credentials | 176 | * check for validity of credentials |
| 177 | */ | 177 | */ |
| 178 | #ifdef CONFIG_DEBUG_CREDENTIALS | 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 | extern void __validate_process_creds(struct task_struct *, | 180 | extern void __validate_process_creds(struct task_struct *, |
| 181 | const char *, unsigned); | 181 | const char *, unsigned); |
| 182 | 182 | ||
| @@ -265,7 +265,6 @@ extern int arch_init_kprobes(void); · 264 unmodified lines | |||
| 265 | extern void kprobes_inc_nmissed_count(struct kprobe *p); | 265 | extern void kprobes_inc_nmissed_count(struct kprobe *p); |
| 266 | extern bool arch_within_kprobe_blacklist(unsigned long addr); | 266 | extern bool arch_within_kprobe_blacklist(unsigned long addr); |
| 267 | extern int arch_populate_kprobe_blacklist(void); | 267 | extern int arch_populate_kprobe_blacklist(void); |
| 268 | extern bool arch_kprobe_on_func_entry(unsigned long offset); | ||
| 269 | extern int kprobe_on_func_entry(kprobe_opcode_t *addr, const char *sym, unsigned long offset); | 268 | extern int kprobe_on_func_entry(kprobe_opcode_t *addr, const char *sym, unsigned long offset); |
| 270 | 269 | ||
| 271 | extern bool within_kprobe_blacklist(unsigned long addr); | 270 | extern bool within_kprobe_blacklist(unsigned long addr); |
| @@ -384,6 +383,8 @@ static inline struct kprobe_ctlblk *get_kprobe_ctlblk(void) · 112 unmodified lines | |||
| 384 | } | 383 | } |
| 385 | 384 | ||
| 386 | kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset); | 385 | kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset); |
| 386 | kprobe_opcode_t *arch_adjust_kprobe_addr(unsigned long addr, unsigned long offset, bool *on_func_entry); | ||
| 387 | |||
| 387 | int register_kprobe(struct kprobe *p); | 388 | int register_kprobe(struct kprobe *p); |
| 388 | void unregister_kprobe(struct kprobe *p); | 389 | void unregister_kprobe(struct kprobe *p); |
| 389 | int register_kprobes(struct kprobe **kps, int num); | 390 | int register_kprobes(struct kprobe **kps, int num); |
| @@ -77,6 +77,18 @@ struct unwind_hint { · 76 unmodified lines | |||
| 77 | #define STACK_FRAME_NON_STANDARD_FP(func) | 77 | #define STACK_FRAME_NON_STANDARD_FP(func) |
| 78 | #endif | 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 | #else /* __ASSEMBLY__ */ | 92 | #else /* __ASSEMBLY__ */ |
| 81 | 93 | ||
| 82 | /* | 94 | /* |
| @@ -129,6 +141,20 @@ struct unwind_hint { · 46 unmodified lines | |||
| 129 | .popsection | 141 | .popsection |
| 130 | .endm | 142 | .endm |
| 131 | 143 | ||
| 144 | .macro ANNOTATE_NOENDBR | ||
| 145 | .Lhere_\@: | ||
| 146 | .pushsection .discard.noendbr | ||
| 147 | .quad .Lhere_\@ | ||
| 148 | .popsection | ||
| 149 | .endm | ||
| 150 | |||
| 151 | .macro REACHABLE | ||
| 152 | .Lhere_\@: | ||
| 153 | .pushsection .discard.reachable | ||
| 154 | .long .Lhere_\@ - . | ||
| 155 | .popsection | ||
| 156 | .endm | ||
| 157 | |||
| 132 | #endif /* __ASSEMBLY__ */ | 158 | #endif /* __ASSEMBLY__ */ |
| 133 | 159 | ||
| 134 | #else /* !CONFIG_STACK_VALIDATION */ | 160 | #else /* !CONFIG_STACK_VALIDATION */ |
| @@ -139,12 +165,18 @@ struct unwind_hint { · 4 unmodified lines | |||
| 139 | "\n\t" | 165 | "\n\t" |
| 140 | #define STACK_FRAME_NON_STANDARD(func) | 166 | #define STACK_FRAME_NON_STANDARD(func) |
| 141 | #define STACK_FRAME_NON_STANDARD_FP(func) | 167 | #define STACK_FRAME_NON_STANDARD_FP(func) |
| 168 | #define ANNOTATE_NOENDBR | ||
| 169 | #define ASM_REACHABLE | ||
| 142 | #else | 170 | #else |
| 143 | #define ANNOTATE_INTRA_FUNCTION_CALL | 171 | #define ANNOTATE_INTRA_FUNCTION_CALL |
| 144 | .macro UNWIND_HINT sp_reg:req sp_offset=0 type:req end=0 | 172 | .macro UNWIND_HINT sp_reg:req sp_offset=0 type:req end=0 |
| 145 | .endm | 173 | .endm |
| 146 | .macro STACK_FRAME_NON_STANDARD func:req | 174 | .macro STACK_FRAME_NON_STANDARD func:req |
| 147 | .endm | 175 | .endm |
| 176 | .macro ANNOTATE_NOENDBR | ||
| 177 | .endm | ||
| 178 | .macro REACHABLE | ||
| 179 | .endm | ||
| 148 | #endif | 180 | #endif |
| 149 | 181 | ||
| 150 | #endif /* CONFIG_STACK_VALIDATION */ | 182 | #endif /* CONFIG_STACK_VALIDATION */ |
| @@ -79,7 +79,7 @@ static inline void exit_thread(struct task_struct *tsk) · 78 unmodified lines | |||
| 79 | { | 79 | { |
| 80 | } | 80 | } |
| 81 | #endif | 81 | #endif |
| 82 | extern void do_group_exit(int); | 82 | extern __noreturn void do_group_exit(int); |
| 83 | 83 | ||
| 84 | extern void exit_files(struct task_struct *); | 84 | extern void exit_files(struct task_struct *); |
| 85 | extern void exit_itimers(struct signal_struct *); | 85 | extern void exit_itimers(struct signal_struct *); |
| @@ -117,18 +117,6 @@ static void bpf_trampoline_module_put(struct bpf_trampoline *tr) · 116 unmodified lines | |||
| 117 | tr->mod = NULL; | 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 | static int unregister_fentry(struct bpf_trampoline *tr, void *old_addr) | 120 | static int unregister_fentry(struct bpf_trampoline *tr, void *old_addr) |
| 133 | { | 121 | { |
| 134 | void *ip = tr->func.addr; | 122 | void *ip = tr->func.addr; |
| @@ -160,12 +148,12 @@ static int modify_fentry(struct bpf_trampoline *tr, void *old_addr, void *new_ad · 25 unmodified lines | |||
| 160 | static int register_fentry(struct bpf_trampoline *tr, void *new_addr) | 148 | static int register_fentry(struct bpf_trampoline *tr, void *new_addr) |
| 161 | { | 149 | { |
| 162 | void *ip = tr->func.addr; | 150 | void *ip = tr->func.addr; |
| 151 | unsigned long faddr; | ||
| 163 | int ret; | 152 | int ret; |
| 164 | 153 | ||
| 165 | ret = is_ftrace_location(ip); | 154 | faddr = ftrace_location((unsigned long)ip); |
| 166 | if (ret < 0) | 155 | if (faddr) |
| 167 | return ret; | 156 | tr->func.ftrace_managed = true; |
| 168 | tr->func.ftrace_managed = ret; | ||
| 169 | 157 | ||
| 170 | if (bpf_trampoline_module_get(tr)) | 158 | if (bpf_trampoline_module_get(tr)) |
| 171 | return -ENOENT; | 159 | return -ENOENT; |
| @@ -870,7 +870,7 @@ static void dump_invalid_creds(const struct cred *cred, const char *label, · 869 unmodified lines | |||
| 870 | /* | 870 | /* |
| 871 | * report use of invalid credentials | 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 | printk(KERN_ERR "CRED: Invalid credentials\n"); | 875 | printk(KERN_ERR "CRED: Invalid credentials\n"); |
| 876 | printk(KERN_ERR "CRED: At %s:%u\n", file, line); | 876 | printk(KERN_ERR "CRED: At %s:%u\n", file, line); |
| @@ -895,7 +895,7 @@ SYSCALL_DEFINE1(exit, int, error_code) · 894 unmodified lines | |||
| 895 | * Take down every thread in the group. This is called by fatal signals | 895 | * Take down every thread in the group. This is called by fatal signals |
| 896 | * as well as by sys_exit_group (below). | 896 | * as well as by sys_exit_group (below). |
| 897 | */ | 897 | */ |
| 898 | void | 898 | void __noreturn |
| 899 | do_group_exit(int exit_code) | 899 | do_group_exit(int exit_code) |
| 900 | { | 900 | { |
| 901 | struct signal_struct *sig = current->signal; | 901 | struct signal_struct *sig = current->signal; |
| @@ -1488,25 +1488,69 @@ bool within_kprobe_blacklist(unsigned long addr) · 1487 unmodified lines | |||
| 1488 | return false; | 1488 | return false; |
| 1489 | } | 1489 | } |
| 1490 | 1490 | ||
| 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 | |||
| 1491 | /* | 1513 | /* |
| 1492 | * If 'symbol_name' is specified, look it up and add the 'offset' | 1514 | * If 'symbol_name' is specified, look it up and add the 'offset' |
| 1493 | * to it. This way, we can specify a relative address to a symbol. | 1515 | * to it. This way, we can specify a relative address to a symbol. |
| 1494 | * This returns encoded errors if it fails to look up symbol or invalid | 1516 | * This returns encoded errors if it fails to look up symbol or invalid |
| 1495 | * combination of parameters. | 1517 | * combination of parameters. |
| 1496 | */ | 1518 | */ |
| 1497 | static kprobe_opcode_t *_kprobe_addr(kprobe_opcode_t *addr, | 1519 | static kprobe_opcode_t * |
| 1498 | const char *symbol_name, unsigned int offset) | 1520 | _kprobe_addr(kprobe_opcode_t *addr, const char *symbol_name, |
| 1521 | unsigned long offset, bool *on_func_entry) | ||
| 1499 | { | 1522 | { |
| 1500 | if ((symbol_name && addr) || (!symbol_name && !addr)) | 1523 | if ((symbol_name && addr) || (!symbol_name && !addr)) |
| 1501 | goto invalid; | 1524 | goto invalid; |
| 1502 | 1525 | ||
| 1503 | if (symbol_name) { | 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 | addr = kprobe_lookup_name(symbol_name, offset); | 1534 | addr = kprobe_lookup_name(symbol_name, offset); |
| 1505 | if (!addr) | 1535 | if (!addr) |
| 1506 | return ERR_PTR(-ENOENT); | 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 | if (addr) | 1554 | if (addr) |
| 1511 | return addr; | 1555 | return addr; |
| 1512 | 1556 | ||
| @@ -1516,7 +1560,8 @@ invalid: · 3 unmodified lines | |||
| 1516 | 1560 | ||
| 1517 | static kprobe_opcode_t *kprobe_addr(struct kprobe *p) | 1561 | static kprobe_opcode_t *kprobe_addr(struct kprobe *p) |
| 1518 | { | 1562 | { |
| 1519 | return _kprobe_addr(p->addr, p->symbol_name, p->offset); | 1563 | bool on_func_entry; |
| 1564 | return _kprobe_addr(p->addr, p->symbol_name, p->offset, &on_func_entry); | ||
| 1520 | } | 1565 | } |
| 1521 | 1566 | ||
| 1522 | /* | 1567 | /* |
| @@ -1562,14 +1607,10 @@ static inline int warn_kprobe_rereg(struct kprobe *p) · 39 unmodified lines | |||
| 1562 | 1607 | ||
| 1563 | static int check_ftrace_location(struct kprobe *p) | 1608 | static int check_ftrace_location(struct kprobe *p) |
| 1564 | { | 1609 | { |
| 1565 | unsigned long ftrace_addr; | 1610 | unsigned long addr = (unsigned long)p->addr; |
| 1566 | 1611 | ||
| 1567 | ftrace_addr = ftrace_location((unsigned long)p->addr); | 1612 | if (ftrace_location(addr) == addr) { |
| 1568 | if (ftrace_addr) { | ||
| 1569 | #ifdef CONFIG_KPROBES_ON_FTRACE | 1613 | #ifdef CONFIG_KPROBES_ON_FTRACE |
| 1570 | /* Given address is not on the instruction boundary */ | ||
| 1571 | if ((unsigned long)p->addr != ftrace_addr) | ||
| 1572 | return -EILSEQ; | ||
| 1573 | p->flags |= KPROBE_FLAG_FTRACE; | 1614 | p->flags |= KPROBE_FLAG_FTRACE; |
| 1574 | #else /* !CONFIG_KPROBES_ON_FTRACE */ | 1615 | #else /* !CONFIG_KPROBES_ON_FTRACE */ |
| 1575 | return -EINVAL; | 1616 | return -EINVAL; |
| @@ -2047,11 +2088,6 @@ static int pre_handler_kretprobe(struct kprobe *p, struct pt_regs *regs) · 471 unmodified lines | |||
| 2047 | } | 2088 | } |
| 2048 | NOKPROBE_SYMBOL(pre_handler_kretprobe); | 2089 | NOKPROBE_SYMBOL(pre_handler_kretprobe); |
| 2049 | 2090 | ||
| 2050 | bool __weak arch_kprobe_on_func_entry(unsigned long offset) | ||
| 2051 | { | ||
| 2052 | return !offset; | ||
| 2053 | } | ||
| 2054 | |||
| 2055 | /** | 2091 | /** |
| 2056 | * kprobe_on_func_entry() -- check whether given address is function entry | 2092 | * kprobe_on_func_entry() -- check whether given address is function entry |
| 2057 | * @addr: Target address | 2093 | * @addr: Target address |
| @@ -2067,15 +2103,13 @@ bool __weak arch_kprobe_on_func_entry(unsigned long offset) · 9 unmodified lines | |||
| 2067 | */ | 2103 | */ |
| 2068 | int kprobe_on_func_entry(kprobe_opcode_t *addr, const char *sym, unsigned long offset) | 2104 | int kprobe_on_func_entry(kprobe_opcode_t *addr, const char *sym, unsigned long offset) |
| 2069 | { | 2105 | { |
| 2070 | kprobe_opcode_t *kp_addr = _kprobe_addr(addr, sym, offset); | 2106 | bool on_func_entry; |
| 2107 | kprobe_opcode_t *kp_addr = _kprobe_addr(addr, sym, offset, &on_func_entry); | ||
| 2071 | 2108 | ||
| 2072 | if (IS_ERR(kp_addr)) | 2109 | if (IS_ERR(kp_addr)) |
| 2073 | return PTR_ERR(kp_addr); | 2110 | return PTR_ERR(kp_addr); |
| 2074 | 2111 | ||
| 2075 | if (!kallsyms_lookup_size_offset((unsigned long)kp_addr, NULL, &offset)) | 2112 | if (!on_func_entry) |
| 2076 | return -ENOENT; | ||
| 2077 | |||
| 2078 | if (!arch_kprobe_on_func_entry(offset)) | ||
| 2079 | return -EINVAL; | 2113 | return -EINVAL; |
| 2080 | 2114 | ||
| 2081 | return 0; | 2115 | return 0; |
| @@ -124,19 +124,6 @@ unlock: · 123 unmodified lines | |||
| 124 | ftrace_test_recursion_unlock(bit); | 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 | static void klp_unpatch_func(struct klp_func *func) | 127 | static void klp_unpatch_func(struct klp_func *func) |
| 141 | { | 128 | { |
| 142 | struct klp_ops *ops; | 129 | struct klp_ops *ops; |
| @@ -153,8 +140,7 @@ static void klp_unpatch_func(struct klp_func *func) · 10 unmodified lines | |||
| 153 | if (list_is_singular(&ops->func_stack)) { | 140 | if (list_is_singular(&ops->func_stack)) { |
| 154 | unsigned long ftrace_loc; | 141 | unsigned long ftrace_loc; |
| 155 | 142 | ||
| 156 | ftrace_loc = | 143 | ftrace_loc = ftrace_location((unsigned long)func->old_func); |
| 157 | klp_get_ftrace_location((unsigned long)func->old_func); | ||
| 158 | if (WARN_ON(!ftrace_loc)) | 144 | if (WARN_ON(!ftrace_loc)) |
| 159 | return; | 145 | return; |
| 160 | 146 | ||
| @@ -186,8 +172,7 @@ static int klp_patch_func(struct klp_func *func) · 25 unmodified lines | |||
| 186 | if (!ops) { | 172 | if (!ops) { |
| 187 | unsigned long ftrace_loc; | 173 | unsigned long ftrace_loc; |
| 188 | 174 | ||
| 189 | ftrace_loc = | 175 | ftrace_loc = ftrace_location((unsigned long)func->old_func); |
| 190 | klp_get_ftrace_location((unsigned long)func->old_func); | ||
| 191 | if (!ftrace_loc) { | 176 | if (!ftrace_loc) { |
| 192 | pr_err("failed to find location for function '%s'\n", | 177 | pr_err("failed to find location for function '%s'\n", |
| 193 | func->old_name); | 178 | func->old_name); |
| @@ -1568,17 +1568,34 @@ unsigned long ftrace_location_range(unsigned long start, unsigned long end) · 1567 unmodified lines | |||
| 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 | * @ip: the instruction pointer to check | 1572 | * @ip: the instruction pointer to check |
| 1573 | * | 1573 | * |
| 1574 | * Returns rec->ip if @ip given is a pointer to a ftrace location. | 1574 | * If @ip matches the ftrace location, return @ip. |
| 1575 | * That is, the instruction that is either a NOP or call to | 1575 | * If @ip matches sym+0, return sym's ftrace location. |
| 1576 | * the function tracer. It checks the ftrace internal tables to | 1576 | * Otherwise, return 0. |
| 1577 | * determine if the address belongs or not. | ||
| 1578 | */ | 1577 | */ |
| 1579 | unsigned long ftrace_location(unsigned long ip) | 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 | /** |
| @@ -4962,7 +4979,8 @@ __ftrace_match_addr(struct ftrace_hash *hash, unsigned long ip, int remove) · 3377 unmodified lines | |||
| 4962 | { | 4979 | { |
| 4963 | struct ftrace_func_entry *entry; | 4980 | struct ftrace_func_entry *entry; |
| 4964 | 4981 | ||
| 4965 | if (!ftrace_location(ip)) | 4982 | ip = ftrace_location(ip); |
| 4983 | if (!ip) | ||
| 4966 | return -EINVAL; | 4984 | return -EINVAL; |
| 4967 | 4985 | ||
| 4968 | if (remove) { | 4986 | if (remove) { |
| @@ -5131,11 +5149,16 @@ int register_ftrace_direct(unsigned long ip, unsigned long addr) · 162 unmodified lines | |||
| 5131 | struct ftrace_func_entry *entry; | 5149 | struct ftrace_func_entry *entry; |
| 5132 | struct ftrace_hash *free_hash = NULL; | 5150 | struct ftrace_hash *free_hash = NULL; |
| 5133 | struct dyn_ftrace *rec; | 5151 | struct dyn_ftrace *rec; |
| 5134 | int ret = -EBUSY; | 5152 | int ret = -ENODEV; |
| 5135 | 5153 | ||
| 5136 | mutex_lock(&direct_mutex); | 5154 | mutex_lock(&direct_mutex); |
| 5137 | 5155 | ||
| 5156 | ip = ftrace_location(ip); | ||
| 5157 | if (!ip) | ||
| 5158 | goto out_unlock; | ||
| 5159 | |||
| 5138 | /* See if there's a direct function at @ip already */ | 5160 | /* See if there's a direct function at @ip already */ |
| 5161 | ret = -EBUSY; | ||
| 5139 | if (ftrace_find_rec_direct(ip)) | 5162 | if (ftrace_find_rec_direct(ip)) |
| 5140 | goto out_unlock; | 5163 | goto out_unlock; |
| 5141 | 5164 | ||
| @@ -5243,6 +5266,10 @@ int unregister_ftrace_direct(unsigned long ip, unsigned long addr) · 101 unmodified lines | |||
| 5243 | 5266 | ||
| 5244 | mutex_lock(&direct_mutex); | 5267 | mutex_lock(&direct_mutex); |
| 5245 | 5268 | ||
| 5269 | ip = ftrace_location(ip); | ||
| 5270 | if (!ip) | ||
| 5271 | goto out_unlock; | ||
| 5272 | |||
| 5246 | entry = find_direct_entry(&ip, NULL); | 5273 | entry = find_direct_entry(&ip, NULL); |
| 5247 | if (!entry) | 5274 | if (!entry) |
| 5248 | goto out_unlock; | 5275 | goto out_unlock; |
| @@ -5375,6 +5402,11 @@ int modify_ftrace_direct(unsigned long ip, · 126 unmodified lines | |||
| 5375 | mutex_lock(&direct_mutex); | 5402 | mutex_lock(&direct_mutex); |
| 5376 | 5403 | ||
| 5377 | mutex_lock(&ftrace_lock); | 5404 | mutex_lock(&ftrace_lock); |
| 5405 | |||
| 5406 | ip = ftrace_location(ip); | ||
| 5407 | if (!ip) | ||
| 5408 | goto out_unlock; | ||
| 5409 | |||
| 5378 | entry = find_direct_entry(&ip, &rec); | 5410 | entry = find_direct_entry(&ip, &rec); |
| 5379 | if (!entry) | 5411 | if (!entry) |
| 5380 | goto out_unlock; | 5412 | goto out_unlock; |
| @@ -24,20 +24,25 @@ static unsigned long my_ip = (unsigned long)schedule; · 23 unmodified lines | |||
| 24 | 24 | ||
| 25 | #ifdef CONFIG_X86_64 | 25 | #ifdef CONFIG_X86_64 |
| 26 | 26 | ||
| 27 | #include <asm/ibt.h> | ||
| 28 | |||
| 27 | asm ( | 29 | asm ( |
| 28 | " .pushsection .text, \"ax\", @progbits\n" | 30 | " .pushsection .text, \"ax\", @progbits\n" |
| 29 | " .type my_tramp1, @function\n" | 31 | " .type my_tramp1, @function\n" |
| 30 | " .globl my_tramp1\n" | 32 | " .globl my_tramp1\n" |
| 31 | " my_tramp1:" | 33 | " my_tramp1:" |
| 34 | ASM_ENDBR | ||
| 32 | " pushq %rbp\n" | 35 | " pushq %rbp\n" |
| 33 | " movq %rsp, %rbp\n" | 36 | " movq %rsp, %rbp\n" |
| 34 | " call my_direct_func1\n" | 37 | " call my_direct_func1\n" |
| 35 | " leave\n" | 38 | " leave\n" |
| 36 | " .size my_tramp1, .-my_tramp1\n" | 39 | " .size my_tramp1, .-my_tramp1\n" |
| 37 | ASM_RET | 40 | ASM_RET |
| 41 | |||
| 38 | " .type my_tramp2, @function\n" | 42 | " .type my_tramp2, @function\n" |
| 39 | " .globl my_tramp2\n" | 43 | " .globl my_tramp2\n" |
| 40 | " my_tramp2:" | 44 | " my_tramp2:" |
| 45 | ASM_ENDBR | ||
| 41 | " pushq %rbp\n" | 46 | " pushq %rbp\n" |
| 42 | " movq %rsp, %rbp\n" | 47 | " movq %rsp, %rbp\n" |
| 43 | " call my_direct_func2\n" | 48 | " call my_direct_func2\n" |
| @@ -22,11 +22,14 @@ extern void my_tramp2(void *); · 21 unmodified lines | |||
| 22 | 22 | ||
| 23 | #ifdef CONFIG_X86_64 | 23 | #ifdef CONFIG_X86_64 |
| 24 | 24 | ||
| 25 | #include <asm/ibt.h> | ||
| 26 | |||
| 25 | asm ( | 27 | asm ( |
| 26 | " .pushsection .text, \"ax\", @progbits\n" | 28 | " .pushsection .text, \"ax\", @progbits\n" |
| 27 | " .type my_tramp1, @function\n" | 29 | " .type my_tramp1, @function\n" |
| 28 | " .globl my_tramp1\n" | 30 | " .globl my_tramp1\n" |
| 29 | " my_tramp1:" | 31 | " my_tramp1:" |
| 32 | ASM_ENDBR | ||
| 30 | " pushq %rbp\n" | 33 | " pushq %rbp\n" |
| 31 | " movq %rsp, %rbp\n" | 34 | " movq %rsp, %rbp\n" |
| 32 | " pushq %rdi\n" | 35 | " pushq %rdi\n" |
| @@ -34,12 +37,13 @@ asm ( · 1 unmodified line | |||
| 34 | " call my_direct_func1\n" | 37 | " call my_direct_func1\n" |
| 35 | " popq %rdi\n" | 38 | " popq %rdi\n" |
| 36 | " leave\n" | 39 | " leave\n" |
| 37 | " ret\n" | 40 | ASM_RET |
| 38 | " .size my_tramp1, .-my_tramp1\n" | 41 | " .size my_tramp1, .-my_tramp1\n" |
| 42 | |||
| 39 | " .type my_tramp2, @function\n" | 43 | " .type my_tramp2, @function\n" |
| 40 | "\n" | ||
| 41 | " .globl my_tramp2\n" | 44 | " .globl my_tramp2\n" |
| 42 | " my_tramp2:" | 45 | " my_tramp2:" |
| 46 | ASM_ENDBR | ||
| 43 | " pushq %rbp\n" | 47 | " pushq %rbp\n" |
| 44 | " movq %rsp, %rbp\n" | 48 | " movq %rsp, %rbp\n" |
| 45 | " pushq %rdi\n" | 49 | " pushq %rdi\n" |
| @@ -47,7 +51,7 @@ asm ( · 1 unmodified line | |||
| 47 | " call my_direct_func2\n" | 51 | " call my_direct_func2\n" |
| 48 | " popq %rdi\n" | 52 | " popq %rdi\n" |
| 49 | " leave\n" | 53 | " leave\n" |
| 50 | " ret\n" | 54 | ASM_RET |
| 51 | " .size my_tramp2, .-my_tramp2\n" | 55 | " .size my_tramp2, .-my_tramp2\n" |
| 52 | " .popsection\n" | 56 | " .popsection\n" |
| 53 | ); | 57 | ); |
| @@ -17,11 +17,14 @@ extern void my_tramp(void *); · 16 unmodified lines | |||
| 17 | 17 | ||
| 18 | #ifdef CONFIG_X86_64 | 18 | #ifdef CONFIG_X86_64 |
| 19 | 19 | ||
| 20 | #include <asm/ibt.h> | ||
| 21 | |||
| 20 | asm ( | 22 | asm ( |
| 21 | " .pushsection .text, \"ax\", @progbits\n" | 23 | " .pushsection .text, \"ax\", @progbits\n" |
| 22 | " .type my_tramp, @function\n" | 24 | " .type my_tramp, @function\n" |
| 23 | " .globl my_tramp\n" | 25 | " .globl my_tramp\n" |
| 24 | " my_tramp:" | 26 | " my_tramp:" |
| 27 | ASM_ENDBR | ||
| 25 | " pushq %rbp\n" | 28 | " pushq %rbp\n" |
| 26 | " movq %rsp, %rbp\n" | 29 | " movq %rsp, %rbp\n" |
| 27 | " pushq %rdi\n" | 30 | " pushq %rdi\n" |
| @@ -29,7 +32,7 @@ asm ( · 1 unmodified line | |||
| 29 | " call my_direct_func\n" | 32 | " call my_direct_func\n" |
| 30 | " popq %rdi\n" | 33 | " popq %rdi\n" |
| 31 | " leave\n" | 34 | " leave\n" |
| 32 | " ret\n" | 35 | ASM_RET |
| 33 | " .size my_tramp, .-my_tramp\n" | 36 | " .size my_tramp, .-my_tramp\n" |
| 34 | " .popsection\n" | 37 | " .popsection\n" |
| 35 | ); | 38 | ); |
| @@ -19,11 +19,14 @@ extern void my_tramp(void *); · 18 unmodified lines | |||
| 19 | 19 | ||
| 20 | #ifdef CONFIG_X86_64 | 20 | #ifdef CONFIG_X86_64 |
| 21 | 21 | ||
| 22 | #include <asm/ibt.h> | ||
| 23 | |||
| 22 | asm ( | 24 | asm ( |
| 23 | " .pushsection .text, \"ax\", @progbits\n" | 25 | " .pushsection .text, \"ax\", @progbits\n" |
| 24 | " .type my_tramp, @function\n" | 26 | " .type my_tramp, @function\n" |
| 25 | " .globl my_tramp\n" | 27 | " .globl my_tramp\n" |
| 26 | " my_tramp:" | 28 | " my_tramp:" |
| 29 | ASM_ENDBR | ||
| 27 | " pushq %rbp\n" | 30 | " pushq %rbp\n" |
| 28 | " movq %rsp, %rbp\n" | 31 | " movq %rsp, %rbp\n" |
| 29 | " pushq %rdi\n" | 32 | " pushq %rdi\n" |
| @@ -16,11 +16,14 @@ extern void my_tramp(void *); · 15 unmodified lines | |||
| 16 | 16 | ||
| 17 | #ifdef CONFIG_X86_64 | 17 | #ifdef CONFIG_X86_64 |
| 18 | 18 | ||
| 19 | #include <asm/ibt.h> | ||
| 20 | |||
| 19 | asm ( | 21 | asm ( |
| 20 | " .pushsection .text, \"ax\", @progbits\n" | 22 | " .pushsection .text, \"ax\", @progbits\n" |
| 21 | " .type my_tramp, @function\n" | 23 | " .type my_tramp, @function\n" |
| 22 | " .globl my_tramp\n" | 24 | " .globl my_tramp\n" |
| 23 | " my_tramp:" | 25 | " my_tramp:" |
| 26 | ASM_ENDBR | ||
| 24 | " pushq %rbp\n" | 27 | " pushq %rbp\n" |
| 25 | " movq %rsp, %rbp\n" | 28 | " movq %rsp, %rbp\n" |
| 26 | " pushq %rdi\n" | 29 | " pushq %rdi\n" |
| @@ -88,8 +88,8 @@ endif · 87 unmodified lines | |||
| 88 | 88 | ||
| 89 | targets-for-modules := $(patsubst %.o, %.mod, $(filter %.o, $(obj-m))) | 89 | targets-for-modules := $(patsubst %.o, %.mod, $(filter %.o, $(obj-m))) |
| 90 | 90 | ||
| 91 | ifdef CONFIG_LTO_CLANG | 91 | ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),) |
| 92 | targets-for-modules += $(patsubst %.o, %.lto.o, $(filter %.o, $(obj-m))) | 92 | targets-for-modules += $(patsubst %.o, %.prelink.o, $(filter %.o, $(obj-m))) |
| 93 | endif | 93 | endif |
| 94 | 94 | ||
| 95 | ifdef need-modorder | 95 | ifdef need-modorder |
| @@ -230,6 +230,7 @@ objtool := $(objtree)/tools/objtool/objtool · 134 unmodified lines | |||
| 230 | objtool_args = \ | 230 | objtool_args = \ |
| 231 | $(if $(CONFIG_UNWINDER_ORC),orc generate,check) \ | 231 | $(if $(CONFIG_UNWINDER_ORC),orc generate,check) \ |
| 232 | $(if $(part-of-module), --module) \ | 232 | $(if $(part-of-module), --module) \ |
| 233 | $(if $(CONFIG_X86_KERNEL_IBT), --lto --ibt) \ | ||
| 233 | $(if $(CONFIG_FRAME_POINTER),, --no-fp) \ | 234 | $(if $(CONFIG_FRAME_POINTER),, --no-fp) \ |
| 234 | $(if $(CONFIG_GCOV_KERNEL)$(CONFIG_LTO_CLANG), --no-unreachable)\ | 235 | $(if $(CONFIG_GCOV_KERNEL)$(CONFIG_LTO_CLANG), --no-unreachable)\ |
| 235 | $(if $(CONFIG_RETPOLINE), --retpoline) \ | 236 | $(if $(CONFIG_RETPOLINE), --retpoline) \ |
| @@ -242,7 +243,7 @@ cmd_gen_objtooldep = $(if $(objtool-enabled), { echo ; echo '$@: $$(wildcard $(o · 6 unmodified lines | |||
| 242 | 243 | ||
| 243 | endif # CONFIG_STACK_VALIDATION | 244 | endif # CONFIG_STACK_VALIDATION |
| 244 | 245 | ||
| 245 | ifdef CONFIG_LTO_CLANG | 246 | ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),) |
| 246 | 247 | ||
| 247 | # Skip objtool for LLVM bitcode | 248 | # Skip objtool for LLVM bitcode |
| 248 | $(obj)/%.o: objtool-enabled := | 249 | $(obj)/%.o: objtool-enabled := |
| @@ -288,24 +289,24 @@ $(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE · 39 unmodified lines | |||
| 288 | $(call if_changed_rule,cc_o_c) | 289 | $(call if_changed_rule,cc_o_c) |
| 289 | $(call cmd,force_checksrc) | 290 | $(call cmd,force_checksrc) |
| 290 | 291 | ||
| 291 | ifdef CONFIG_LTO_CLANG | 292 | ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),) |
| 292 | # Module .o files may contain LLVM bitcode, compile them into native code | 293 | # Module .o files may contain LLVM bitcode, compile them into native code |
| 293 | # before ELF processing | 294 | # before ELF processing |
| 294 | quiet_cmd_cc_lto_link_modules = LTO [M] $@ | 295 | quiet_cmd_cc_prelink_modules = LD [M] $@ |
| 295 | cmd_cc_lto_link_modules = \ | 296 | cmd_cc_prelink_modules = \ |
| 296 | $(LD) $(ld_flags) -r -o $@ \ | 297 | $(LD) $(ld_flags) -r -o $@ \ |
| 297 | $(shell [ -s $(@:.lto.o=.o.symversions) ] && \ | 298 | $(shell [ -s $(@:.prelink.o=.o.symversions) ] && \ |
| 298 | echo -T $(@:.lto.o=.o.symversions)) \ | 299 | echo -T $(@:.prelink.o=.o.symversions)) \ |
| 299 | --whole-archive $(filter-out FORCE,$^) \ | 300 | --whole-archive $(filter-out FORCE,$^) \ |
| 300 | $(cmd_objtool) | 301 | $(cmd_objtool) |
| 301 | 302 | ||
| 302 | # objtool was skipped for LLVM bitcode, run it now that we have compiled | 303 | # objtool was skipped for LLVM bitcode, run it now that we have compiled |
| 303 | # modules into native code | 304 | # modules into native code |
| 304 | $(obj)/%.lto.o: objtool-enabled = y | 305 | $(obj)/%.prelink.o: objtool-enabled = y |
| 305 | $(obj)/%.lto.o: part-of-module := y | 306 | $(obj)/%.prelink.o: part-of-module := y |
| 306 | 307 | ||
| 307 | $(obj)/%.lto.o: $(obj)/%.o FORCE | 308 | $(obj)/%.prelink.o: $(obj)/%.o FORCE |
| 308 | $(call if_changed,cc_lto_link_modules) | 309 | $(call if_changed,cc_prelink_modules) |
| 309 | endif | 310 | endif |
| 310 | 311 | ||
| 311 | cmd_mod = { \ | 312 | cmd_mod = { \ |
| @@ -469,7 +470,7 @@ $(obj)/lib.a: $(lib-y) FORCE · 157 unmodified lines | |||
| 469 | # Do not replace $(filter %.o,^) with $(real-prereqs). When a single object | 470 | # Do not replace $(filter %.o,^) with $(real-prereqs). When a single object |
| 470 | # module is turned into a multi object module, $^ will contain header file | 471 | # module is turned into a multi object module, $^ will contain header file |
| 471 | # dependencies recorded in the .*.cmd file. | 472 | # dependencies recorded in the .*.cmd file. |
| 472 | ifdef CONFIG_LTO_CLANG | 473 | ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),) |
| 473 | quiet_cmd_link_multi-m = AR [M] $@ | 474 | quiet_cmd_link_multi-m = AR [M] $@ |
| 474 | cmd_link_multi-m = \ | 475 | cmd_link_multi-m = \ |
| 475 | $(cmd_update_lto_symversions); \ | 476 | $(cmd_update_lto_symversions); \ |
| @@ -225,11 +225,11 @@ dtc_cpp_flags = -Wp,-MMD,$(depfile).pre.tmp -nostdinc \ · 224 unmodified lines | |||
| 225 | $(addprefix -I,$(DTC_INCLUDE)) \ | 225 | $(addprefix -I,$(DTC_INCLUDE)) \ |
| 226 | -undef -D__DTS__ | 226 | -undef -D__DTS__ |
| 227 | 227 | ||
| 228 | ifeq ($(CONFIG_LTO_CLANG),y) | 228 | ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),) |
| 229 | # With CONFIG_LTO_CLANG, .o files in modules might be LLVM bitcode, so we | 229 | # With CONFIG_LTO_CLANG, .o files in modules might be LLVM bitcode, so we |
| 230 | # need to run LTO to compile them into native code (.lto.o) before further | 230 | # need to run LTO to compile them into native code (.lto.o) before further |
| 231 | # processing. | 231 | # processing. |
| 232 | mod-prelink-ext := .lto | 232 | mod-prelink-ext := .prelink |
| 233 | endif | 233 | endif |
| 234 | 234 | ||
| 235 | # Useful for describing the dependency of composite objects | 235 | # Useful for describing the dependency of composite objects |
| @@ -108,14 +108,20 @@ objtool_link() · 107 unmodified lines | |||
| 108 | local objtoolcmd; | 108 | local objtoolcmd; |
| 109 | local objtoolopt; | 109 | local objtoolopt; |
| 110 | 110 | ||
| 111 | if is_enabled CONFIG_LTO_CLANG && is_enabled CONFIG_STACK_VALIDATION; then | 111 | if is_enabled CONFIG_STACK_VALIDATION && \ |
| 112 | ( is_enabled CONFIG_LTO_CLANG || is_enabled CONFIG_X86_KERNEL_IBT ); then | ||
| 113 | |||
| 112 | # Don't perform vmlinux validation unless explicitly requested, | 114 | # Don't perform vmlinux validation unless explicitly requested, |
| 113 | # but run objtool on vmlinux.o now that we have an object file. | 115 | # but run objtool on vmlinux.o now that we have an object file. |
| 114 | if is_enabled CONFIG_UNWINDER_ORC; then | 116 | if is_enabled CONFIG_UNWINDER_ORC; then |
| 115 | objtoolcmd="orc generate" | 117 | objtoolcmd="orc generate" |
| 116 | fi | 118 | fi |
| 117 | 119 | ||
| 118 | objtoolopt="${objtoolopt} --duplicate" | 120 | objtoolopt="${objtoolopt} --lto" |
| 121 | |||
| 122 | if is_enabled CONFIG_X86_KERNEL_IBT; then | ||
| 123 | objtoolopt="${objtoolopt} --ibt" | ||
| 124 | fi | ||
| 119 | 125 | ||
| 120 | if is_enabled CONFIG_FTRACE_MCOUNT_USE_OBJTOOL; then | 126 | if is_enabled CONFIG_FTRACE_MCOUNT_USE_OBJTOOL; then |
| 121 | objtoolopt="${objtoolopt} --mcount" | 127 | objtoolopt="${objtoolopt} --mcount" |
| @@ -168,7 +174,7 @@ vmlinux_link() · 46 unmodified lines | |||
| 168 | # skip output file argument | 174 | # skip output file argument |
| 169 | shift | 175 | shift |
| 170 | 176 | ||
| 171 | if is_enabled CONFIG_LTO_CLANG; then | 177 | if is_enabled CONFIG_LTO_CLANG || is_enabled CONFIG_X86_KERNEL_IBT; then |
| 172 | # Use vmlinux.o instead of performing the slow LTO link again. | 178 | # Use vmlinux.o instead of performing the slow LTO link again. |
| 173 | objs=vmlinux.o | 179 | objs=vmlinux.o |
| 174 | libs= | 180 | libs= |
| @@ -1996,9 +1996,9 @@ static char *remove_dot(char *s) · 1995 unmodified lines | |||
| 1996 | if (m && (s[n + m] == '.' || s[n + m] == 0)) | 1996 | if (m && (s[n + m] == '.' || s[n + m] == 0)) |
| 1997 | s[n] = 0; | 1997 | s[n] = 0; |
| 1998 | 1998 | ||
| 1999 | /* strip trailing .lto */ | 1999 | /* strip trailing .prelink */ |
| 2000 | if (strends(s, ".lto")) | 2000 | if (strends(s, ".prelink")) |
| 2001 | s[strlen(s) - 4] = '\0'; | 2001 | s[strlen(s) - 8] = '\0'; |
| 2002 | } | 2002 | } |
| 2003 | return s; | 2003 | return s; |
| 2004 | } | 2004 | } |
| @@ -2022,9 +2022,9 @@ static void read_symbols(const char *modname) · 17 unmodified lines | |||
| 2022 | /* strip trailing .o */ | 2022 | /* strip trailing .o */ |
| 2023 | tmp = NOFAIL(strdup(modname)); | 2023 | tmp = NOFAIL(strdup(modname)); |
| 2024 | tmp[strlen(tmp) - 2] = '\0'; | 2024 | tmp[strlen(tmp) - 2] = '\0'; |
| 2025 | /* strip trailing .lto */ | 2025 | /* strip trailing .prelink */ |
| 2026 | if (strends(tmp, ".lto")) | 2026 | if (strends(tmp, ".prelink")) |
| 2027 | tmp[strlen(tmp) - 4] = '\0'; | 2027 | tmp[strlen(tmp) - 8] = '\0'; |
| 2028 | mod = new_module(tmp); | 2028 | mod = new_module(tmp); |
| 2029 | free(tmp); | 2029 | free(tmp); |
| 2030 | } | 2030 | } |
| @@ -150,7 +150,7 @@ struct snd_ctl_elem_value32 { · 149 unmodified lines | |||
| 150 | unsigned char reserved[128]; | 150 | unsigned char reserved[128]; |
| 151 | }; | 151 | }; |
| 152 | 152 | ||
| 153 | #ifdef CONFIG_X86_X32 | 153 | #ifdef CONFIG_X86_X32_ABI |
| 154 | /* x32 has a different alignment for 64bit values from ia32 */ | 154 | /* x32 has a different alignment for 64bit values from ia32 */ |
| 155 | struct snd_ctl_elem_value_x32 { | 155 | struct snd_ctl_elem_value_x32 { |
| 156 | struct snd_ctl_elem_id id; | 156 | struct snd_ctl_elem_id id; |
| @@ -162,7 +162,7 @@ struct snd_ctl_elem_value_x32 { · 5 unmodified lines | |||
| 162 | } value; | 162 | } value; |
| 163 | unsigned char reserved[128]; | 163 | unsigned char reserved[128]; |
| 164 | }; | 164 | }; |
| 165 | #endif /* CONFIG_X86_X32 */ | 165 | #endif /* CONFIG_X86_X32_ABI */ |
| 166 | 166 | ||
| 167 | /* get the value type and count of the control */ | 167 | /* get the value type and count of the control */ |
| 168 | static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id, | 168 | static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id, |
| @@ -347,7 +347,7 @@ static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file, · 178 unmodified lines | |||
| 347 | return ctl_elem_write_user(file, data32, &data32->value); | 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 | static int snd_ctl_elem_read_user_x32(struct snd_card *card, | 351 | static int snd_ctl_elem_read_user_x32(struct snd_card *card, |
| 352 | struct snd_ctl_elem_value_x32 __user *data32) | 352 | struct snd_ctl_elem_value_x32 __user *data32) |
| 353 | { | 353 | { |
| @@ -359,7 +359,7 @@ static int snd_ctl_elem_write_user_x32(struct snd_ctl_file *file, · 5 unmodified lines | |||
| 359 | { | 359 | { |
| 360 | return ctl_elem_write_user(file, data32, &data32->value); | 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 | /* add or replace a user control */ | 364 | /* add or replace a user control */ |
| 365 | static int snd_ctl_elem_add_compat(struct snd_ctl_file *file, | 365 | static int snd_ctl_elem_add_compat(struct snd_ctl_file *file, |
| @@ -418,10 +418,10 @@ enum { · 52 unmodified lines | |||
| 418 | SNDRV_CTL_IOCTL_ELEM_WRITE32 = _IOWR('U', 0x13, struct snd_ctl_elem_value32), | 418 | SNDRV_CTL_IOCTL_ELEM_WRITE32 = _IOWR('U', 0x13, struct snd_ctl_elem_value32), |
| 419 | SNDRV_CTL_IOCTL_ELEM_ADD32 = _IOWR('U', 0x17, struct snd_ctl_elem_info32), | 419 | SNDRV_CTL_IOCTL_ELEM_ADD32 = _IOWR('U', 0x17, struct snd_ctl_elem_info32), |
| 420 | SNDRV_CTL_IOCTL_ELEM_REPLACE32 = _IOWR('U', 0x18, struct snd_ctl_elem_info32), | 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 | SNDRV_CTL_IOCTL_ELEM_READ_X32 = _IOWR('U', 0x12, struct snd_ctl_elem_value_x32), | 422 | SNDRV_CTL_IOCTL_ELEM_READ_X32 = _IOWR('U', 0x12, struct snd_ctl_elem_value_x32), |
| 423 | SNDRV_CTL_IOCTL_ELEM_WRITE_X32 = _IOWR('U', 0x13, struct snd_ctl_elem_value_x32), | 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 | static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) | 427 | static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) |
| @@ -460,12 +460,12 @@ static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, uns · 32 unmodified lines | |||
| 460 | return snd_ctl_elem_add_compat(ctl, argp, 0); | 460 | return snd_ctl_elem_add_compat(ctl, argp, 0); |
| 461 | case SNDRV_CTL_IOCTL_ELEM_REPLACE32: | 461 | case SNDRV_CTL_IOCTL_ELEM_REPLACE32: |
| 462 | return snd_ctl_elem_add_compat(ctl, argp, 1); | 462 | return snd_ctl_elem_add_compat(ctl, argp, 1); |
| 463 | #ifdef CONFIG_X86_X32 | 463 | #ifdef CONFIG_X86_X32_ABI |
| 464 | case SNDRV_CTL_IOCTL_ELEM_READ_X32: | 464 | case SNDRV_CTL_IOCTL_ELEM_READ_X32: |
| 465 | return snd_ctl_elem_read_user_x32(ctl->card, argp); | 465 | return snd_ctl_elem_read_user_x32(ctl->card, argp); |
| 466 | case SNDRV_CTL_IOCTL_ELEM_WRITE_X32: | 466 | case SNDRV_CTL_IOCTL_ELEM_WRITE_X32: |
| 467 | return snd_ctl_elem_write_user_x32(ctl, argp); | 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 | down_read(&snd_ioctl_rwsem); | 471 | down_read(&snd_ioctl_rwsem); |
| @@ -147,13 +147,13 @@ static int snd_pcm_ioctl_channel_info_compat(struct snd_pcm_substream *substream · 146 unmodified lines | |||
| 147 | return err; | 147 | return err; |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | #ifdef CONFIG_X86_X32 | 150 | #ifdef CONFIG_X86_X32_ABI |
| 151 | /* X32 ABI has the same struct as x86-64 for snd_pcm_channel_info */ | 151 | /* X32 ABI has the same struct as x86-64 for snd_pcm_channel_info */ |
| 152 | static int snd_pcm_channel_info_user(struct snd_pcm_substream *substream, | 152 | static int snd_pcm_channel_info_user(struct snd_pcm_substream *substream, |
| 153 | struct snd_pcm_channel_info __user *src); | 153 | struct snd_pcm_channel_info __user *src); |
| 154 | #define snd_pcm_ioctl_channel_info_x32(s, p) \ | 154 | #define snd_pcm_ioctl_channel_info_x32(s, p) \ |
| 155 | snd_pcm_channel_info_user(s, p) | 155 | snd_pcm_channel_info_user(s, p) |
| 156 | #endif /* CONFIG_X86_X32 */ | 156 | #endif /* CONFIG_X86_X32_ABI */ |
| 157 | 157 | ||
| 158 | struct compat_snd_pcm_status64 { | 158 | struct compat_snd_pcm_status64 { |
| 159 | snd_pcm_state_t state; | 159 | snd_pcm_state_t state; |
| @@ -375,7 +375,7 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream, · 215 unmodified lines | |||
| 375 | return err; | 375 | return err; |
| 376 | } | 376 | } |
| 377 | 377 | ||
| 378 | #ifdef CONFIG_X86_X32 | 378 | #ifdef CONFIG_X86_X32_ABI |
| 379 | /* X32 ABI has 64bit timespec and 64bit alignment */ | 379 | /* X32 ABI has 64bit timespec and 64bit alignment */ |
| 380 | struct snd_pcm_mmap_status_x32 { | 380 | struct snd_pcm_mmap_status_x32 { |
| 381 | snd_pcm_state_t state; | 381 | snd_pcm_state_t state; |
| @@ -468,7 +468,7 @@ static int snd_pcm_ioctl_sync_ptr_x32(struct snd_pcm_substream *substream, · 86 unmodified lines | |||
| 468 | 468 | ||
| 469 | return 0; | 469 | return 0; |
| 470 | } | 470 | } |
| 471 | #endif /* CONFIG_X86_X32 */ | 471 | #endif /* CONFIG_X86_X32_ABI */ |
| 472 | 472 | ||
| 473 | #ifdef __BIG_ENDIAN | 473 | #ifdef __BIG_ENDIAN |
| 474 | typedef char __pad_before_u32[4]; | 474 | typedef char __pad_before_u32[4]; |
| @@ -560,10 +560,10 @@ enum { · 85 unmodified lines | |||
| 560 | SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct snd_xfern32), | 560 | SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct snd_xfern32), |
| 561 | SNDRV_PCM_IOCTL_STATUS_COMPAT64 = _IOR('A', 0x20, struct compat_snd_pcm_status64), | 561 | SNDRV_PCM_IOCTL_STATUS_COMPAT64 = _IOR('A', 0x20, struct compat_snd_pcm_status64), |
| 562 | SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT64 = _IOWR('A', 0x24, struct compat_snd_pcm_status64), | 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 | SNDRV_PCM_IOCTL_CHANNEL_INFO_X32 = _IOR('A', 0x32, struct snd_pcm_channel_info), | 564 | SNDRV_PCM_IOCTL_CHANNEL_INFO_X32 = _IOR('A', 0x32, struct snd_pcm_channel_info), |
| 565 | SNDRV_PCM_IOCTL_SYNC_PTR_X32 = _IOWR('A', 0x23, struct snd_pcm_sync_ptr_x32), | 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 | static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) | 569 | static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) |
| @@ -607,10 +607,10 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l · 37 unmodified lines | |||
| 607 | case __SNDRV_PCM_IOCTL_SYNC_PTR32: | 607 | case __SNDRV_PCM_IOCTL_SYNC_PTR32: |
| 608 | return snd_pcm_common_ioctl(file, substream, cmd, argp); | 608 | return snd_pcm_common_ioctl(file, substream, cmd, argp); |
| 609 | case __SNDRV_PCM_IOCTL_SYNC_PTR64: | 609 | case __SNDRV_PCM_IOCTL_SYNC_PTR64: |
| 610 | #ifdef CONFIG_X86_X32 | 610 | #ifdef CONFIG_X86_X32_ABI |
| 611 | if (in_x32_syscall()) | 611 | if (in_x32_syscall()) |
| 612 | return snd_pcm_ioctl_sync_ptr_x32(substream, argp); | 612 | return snd_pcm_ioctl_sync_ptr_x32(substream, argp); |
| 613 | #endif /* CONFIG_X86_X32 */ | 613 | #endif /* CONFIG_X86_X32_ABI */ |
| 614 | return snd_pcm_ioctl_sync_ptr_buggy(substream, argp); | 614 | return snd_pcm_ioctl_sync_ptr_buggy(substream, argp); |
| 615 | case SNDRV_PCM_IOCTL_HW_REFINE32: | 615 | case SNDRV_PCM_IOCTL_HW_REFINE32: |
| 616 | return snd_pcm_ioctl_hw_params_compat(substream, 1, argp); | 616 | return snd_pcm_ioctl_hw_params_compat(substream, 1, argp); |
| @@ -642,10 +642,10 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l · 25 unmodified lines | |||
| 642 | return snd_pcm_status_user_compat64(substream, argp, false); | 642 | return snd_pcm_status_user_compat64(substream, argp, false); |
| 643 | case SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT64: | 643 | case SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT64: |
| 644 | return snd_pcm_status_user_compat64(substream, argp, true); | 644 | return snd_pcm_status_user_compat64(substream, argp, true); |
| 645 | #ifdef CONFIG_X86_X32 | 645 | #ifdef CONFIG_X86_X32_ABI |
| 646 | case SNDRV_PCM_IOCTL_CHANNEL_INFO_X32: | 646 | case SNDRV_PCM_IOCTL_CHANNEL_INFO_X32: |
| 647 | return snd_pcm_ioctl_channel_info_x32(substream, argp); | 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 | return -ENOIOCTLCMD; | 651 | return -ENOIOCTLCMD; |
| @@ -77,6 +77,18 @@ struct unwind_hint { · 76 unmodified lines | |||
| 77 | #define STACK_FRAME_NON_STANDARD_FP(func) | 77 | #define STACK_FRAME_NON_STANDARD_FP(func) |
| 78 | #endif | 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 | #else /* __ASSEMBLY__ */ | 92 | #else /* __ASSEMBLY__ */ |
| 81 | 93 | ||
| 82 | /* | 94 | /* |
| @@ -129,6 +141,20 @@ struct unwind_hint { · 46 unmodified lines | |||
| 129 | .popsection | 141 | .popsection |
| 130 | .endm | 142 | .endm |
| 131 | 143 | ||
| 144 | .macro ANNOTATE_NOENDBR | ||
| 145 | .Lhere_\@: | ||
| 146 | .pushsection .discard.noendbr | ||
| 147 | .quad .Lhere_\@ | ||
| 148 | .popsection | ||
| 149 | .endm | ||
| 150 | |||
| 151 | .macro REACHABLE | ||
| 152 | .Lhere_\@: | ||
| 153 | .pushsection .discard.reachable | ||
| 154 | .long .Lhere_\@ - . | ||
| 155 | .popsection | ||
| 156 | .endm | ||
| 157 | |||
| 132 | #endif /* __ASSEMBLY__ */ | 158 | #endif /* __ASSEMBLY__ */ |
| 133 | 159 | ||
| 134 | #else /* !CONFIG_STACK_VALIDATION */ | 160 | #else /* !CONFIG_STACK_VALIDATION */ |
| @@ -139,12 +165,18 @@ struct unwind_hint { · 4 unmodified lines | |||
| 139 | "\n\t" | 165 | "\n\t" |
| 140 | #define STACK_FRAME_NON_STANDARD(func) | 166 | #define STACK_FRAME_NON_STANDARD(func) |
| 141 | #define STACK_FRAME_NON_STANDARD_FP(func) | 167 | #define STACK_FRAME_NON_STANDARD_FP(func) |
| 168 | #define ANNOTATE_NOENDBR | ||
| 169 | #define ASM_REACHABLE | ||
| 142 | #else | 170 | #else |
| 143 | #define ANNOTATE_INTRA_FUNCTION_CALL | 171 | #define ANNOTATE_INTRA_FUNCTION_CALL |
| 144 | .macro UNWIND_HINT sp_reg:req sp_offset=0 type:req end=0 | 172 | .macro UNWIND_HINT sp_reg:req sp_offset=0 type:req end=0 |
| 145 | .endm | 173 | .endm |
| 146 | .macro STACK_FRAME_NON_STANDARD func:req | 174 | .macro STACK_FRAME_NON_STANDARD func:req |
| 147 | .endm | 175 | .endm |
| 176 | .macro ANNOTATE_NOENDBR | ||
| 177 | .endm | ||
| 178 | .macro REACHABLE | ||
| 179 | .endm | ||
| 148 | #endif | 180 | #endif |
| 149 | 181 | ||
| 150 | #endif /* CONFIG_STACK_VALIDATION */ | 182 | #endif /* CONFIG_STACK_VALIDATION */ |
| @@ -103,6 +103,18 @@ unsigned long arch_jump_destination(struct instruction *insn) · 102 unmodified lines | |||
| 103 | #define rm_is_mem(reg) (mod_is_mem() && !is_RIP() && rm_is(reg)) | 103 | #define rm_is_mem(reg) (mod_is_mem() && !is_RIP() && rm_is(reg)) |
| 104 | #define rm_is_reg(reg) (mod_is_reg() && modrm_rm == (reg)) | 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 | int arch_decode_instruction(struct objtool_file *file, const struct section *sec, | 118 | int arch_decode_instruction(struct objtool_file *file, const struct section *sec, |
| 107 | unsigned long offset, unsigned int maxlen, | 119 | unsigned long offset, unsigned int maxlen, |
| 108 | unsigned int *len, enum insn_type *type, | 120 | unsigned int *len, enum insn_type *type, |
| @@ -112,7 +124,7 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec · 3 unmodified lines | |||
| 112 | const struct elf *elf = file->elf; | 124 | const struct elf *elf = file->elf; |
| 113 | struct insn insn; | 125 | struct insn insn; |
| 114 | int x86_64, ret; | 126 | int x86_64, ret; |
| 115 | unsigned char op1, op2, op3, | 127 | unsigned char op1, op2, op3, prefix, |
| 116 | rex = 0, rex_b = 0, rex_r = 0, rex_w = 0, rex_x = 0, | 128 | rex = 0, rex_b = 0, rex_r = 0, rex_w = 0, rex_x = 0, |
| 117 | modrm = 0, modrm_mod = 0, modrm_rm = 0, modrm_reg = 0, | 129 | modrm = 0, modrm_mod = 0, modrm_rm = 0, modrm_reg = 0, |
| 118 | sib = 0, /* sib_scale = 0, */ sib_index = 0, sib_base = 0; | 130 | sib = 0, /* sib_scale = 0, */ sib_index = 0, sib_base = 0; |
| @@ -137,6 +149,8 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec · 18 unmodified lines | |||
| 137 | if (insn.vex_prefix.nbytes) | 149 | if (insn.vex_prefix.nbytes) |
| 138 | return 0; | 150 | return 0; |
| 139 | 151 | ||
| 152 | prefix = insn.prefixes.bytes[0]; | ||
| 153 | |||
| 140 | op1 = insn.opcode.bytes[0]; | 154 | op1 = insn.opcode.bytes[0]; |
| 141 | op2 = insn.opcode.bytes[1]; | 155 | op2 = insn.opcode.bytes[1]; |
| 142 | op3 = insn.opcode.bytes[2]; | 156 | op3 = insn.opcode.bytes[2]; |
| @@ -492,6 +506,12 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec · 349 unmodified lines | |||
| 492 | /* nopl/nopw */ | 506 | /* nopl/nopw */ |
| 493 | *type = INSN_NOP; | 507 | *type = INSN_NOP; |
| 494 | 508 | ||
| 509 | } else if (op2 == 0x1e) { | ||
| 510 | |||
| 511 | if (prefix == 0xf3 && (modrm == 0xfa || modrm == 0xfb)) | ||
| 512 | *type = INSN_ENDBR; | ||
| 513 | |||
| 514 | |||
| 495 | } else if (op2 == 0x38 && op3 == 0xf8) { | 515 | } else if (op2 == 0x38 && op3 == 0xf8) { |
| 496 | if (insn.prefixes.nbytes == 1 && | 516 | if (insn.prefixes.nbytes == 1 && |
| 497 | insn.prefixes.bytes[0] == 0xf2) { | 517 | insn.prefixes.bytes[0] == 0xf2) { |
| @@ -636,20 +656,24 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec · 138 unmodified lines | |||
| 636 | break; | 656 | break; |
| 637 | 657 | ||
| 638 | case 0xff: | 658 | case 0xff: |
| 639 | if (modrm_reg == 2 || modrm_reg == 3) | 659 | if (modrm_reg == 2 || modrm_reg == 3) { |
| 640 | 660 | ||
| 641 | *type = INSN_CALL_DYNAMIC; | 661 | *type = INSN_CALL_DYNAMIC; |
| 662 | if (has_notrack_prefix(&insn)) | ||
| 663 | WARN("notrack prefix found at %s:0x%lx", sec->name, offset); | ||
| 642 | 664 | ||
| 643 | else if (modrm_reg == 4) | 665 | } else if (modrm_reg == 4) { |
| 644 | 666 | ||
| 645 | *type = INSN_JUMP_DYNAMIC; | 667 | *type = INSN_JUMP_DYNAMIC; |
| 668 | if (has_notrack_prefix(&insn)) | ||
| 669 | WARN("notrack prefix found at %s:0x%lx", sec->name, offset); | ||
| 646 | 670 | ||
| 647 | else if (modrm_reg == 5) | 671 | } else if (modrm_reg == 5) { |
| 648 | 672 | ||
| 649 | /* jmpf */ | 673 | /* jmpf */ |
| 650 | *type = INSN_CONTEXT_SWITCH; | 674 | *type = INSN_CONTEXT_SWITCH; |
| 651 | 675 | ||
| 652 | else if (modrm_reg == 6) { | 676 | } else if (modrm_reg == 6) { |
| 653 | 677 | ||
| 654 | /* push from mem */ | 678 | /* push from mem */ |
| 655 | ADD_OP(op) { | 679 | ADD_OP(op) { |
| @@ -20,7 +20,8 @@ · 19 unmodified lines | |||
| 20 | #include <objtool/objtool.h> | 20 | #include <objtool/objtool.h> |
| 21 | 21 | ||
| 22 | bool no_fp, no_unreachable, retpoline, module, backtrace, uaccess, stats, | 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 | static const char * const check_usage[] = { | 26 | static const char * const check_usage[] = { |
| 26 | "objtool check [<options>] file.o", | 27 | "objtool check [<options>] file.o", |
| @@ -40,12 +41,14 @@ const struct option check_options[] = { · 13 unmodified lines | |||
| 40 | OPT_BOOLEAN('b', "backtrace", &backtrace, "unwind on error"), | 41 | OPT_BOOLEAN('b', "backtrace", &backtrace, "unwind on error"), |
| 41 | OPT_BOOLEAN('a', "uaccess", &uaccess, "enable uaccess checking"), | 42 | OPT_BOOLEAN('a', "uaccess", &uaccess, "enable uaccess checking"), |
| 42 | OPT_BOOLEAN('s', "stats", &stats, "print statistics"), | 43 | OPT_BOOLEAN('s', "stats", &stats, "print statistics"), |
| 43 | OPT_BOOLEAN('d', "duplicate", &validate_dup, "duplicate validation for vmlinux.o"), | 44 | OPT_BOOLEAN(0, "lto", <o, "whole-archive like runs"), |
| 44 | OPT_BOOLEAN('n', "noinstr", &noinstr, "noinstr validation for vmlinux.o"), | 45 | OPT_BOOLEAN('n', "noinstr", &noinstr, "noinstr validation for vmlinux.o"), |
| 45 | OPT_BOOLEAN('l', "vmlinux", &vmlinux, "vmlinux.o validation"), | 46 | OPT_BOOLEAN('l', "vmlinux", &vmlinux, "vmlinux.o validation"), |
| 46 | OPT_BOOLEAN('M', "mcount", &mcount, "generate __mcount_loc"), | 47 | OPT_BOOLEAN('M', "mcount", &mcount, "generate __mcount_loc"), |
| 47 | OPT_BOOLEAN('B', "backup", &backup, "create .orig files before modification"), | 48 | OPT_BOOLEAN('B', "backup", &backup, "create .orig files before modification"), |
| 48 | OPT_BOOLEAN('S', "sls", &sls, "validate straight-line-speculation"), | 49 | OPT_BOOLEAN('S', "sls", &sls, "validate straight-line-speculation"), |
| 50 | OPT_BOOLEAN(0, "dry-run", &dryrun, "don't write the modifications"), | ||
| 51 | OPT_BOOLEAN(0, "ibt", &ibt, "validate ENDBR placement"), | ||
| 49 | OPT_END(), | 52 | OPT_END(), |
| 50 | }; | 53 | }; |
| 51 | 54 | ||
| @@ -181,6 +181,9 @@ static bool __dead_end_function(struct objtool_file *file, struct symbol *func, · 180 unmodified lines | |||
| 181 | "kunit_try_catch_throw", | 181 | "kunit_try_catch_throw", |
| 182 | "xen_start_kernel", | 182 | "xen_start_kernel", |
| 183 | "cpu_bringup_and_idle", | 183 | "cpu_bringup_and_idle", |
| 184 | "do_group_exit", | ||
| 185 | "stop_this_cpu", | ||
| 186 | "__invalid_creds", | ||
| 184 | }; | 187 | }; |
| 185 | 188 | ||
| 186 | if (!func) | 189 | if (!func) |
| @@ -380,6 +383,7 @@ static int decode_instructions(struct objtool_file *file) · 193 unmodified lines | |||
| 380 | memset(insn, 0, sizeof(*insn)); | 383 | memset(insn, 0, sizeof(*insn)); |
| 381 | INIT_LIST_HEAD(&insn->alts); | 384 | INIT_LIST_HEAD(&insn->alts); |
| 382 | INIT_LIST_HEAD(&insn->stack_ops); | 385 | INIT_LIST_HEAD(&insn->stack_ops); |
| 386 | INIT_LIST_HEAD(&insn->call_node); | ||
| 383 | 387 | ||
| 384 | insn->sec = sec; | 388 | insn->sec = sec; |
| 385 | insn->offset = offset; | 389 | insn->offset = offset; |
| @@ -392,6 +396,14 @@ static int decode_instructions(struct objtool_file *file) · 6 unmodified lines | |||
| 392 | if (ret) | 396 | if (ret) |
| 393 | goto err; | 397 | goto err; |
| 394 | 398 | ||
| 399 | /* | ||
| 400 | * By default, "ud2" is a dead end unless otherwise | ||
| 401 | * annotated, because GCC 7 inserts it for certain | ||
| 402 | * divide-by-zero cases. | ||
| 403 | */ | ||
| 404 | if (insn->type == INSN_BUG) | ||
| 405 | insn->dead_end = true; | ||
| 406 | |||
| 395 | hash_add(file->insn_hash, &insn->hash, sec_offset_hash(sec, insn->offset)); | 407 | hash_add(file->insn_hash, &insn->hash, sec_offset_hash(sec, insn->offset)); |
| 396 | list_add_tail(&insn->list, &file->insn_list); | 408 | list_add_tail(&insn->list, &file->insn_list); |
| 397 | nr_insns++; | 409 | nr_insns++; |
| @@ -407,8 +419,17 @@ static int decode_instructions(struct objtool_file *file) · 9 unmodified lines | |||
| 407 | return -1; | 419 | return -1; |
| 408 | } | 420 | } |
| 409 | 421 | ||
| 410 | sym_for_each_insn(file, func, insn) | 422 | sym_for_each_insn(file, func, insn) { |
| 411 | insn->func = func; | 423 | insn->func = func; |
| 424 | if (insn->type == INSN_ENDBR && list_empty(&insn->call_node)) { | ||
| 425 | if (insn->offset == insn->func->offset) { | ||
| 426 | list_add_tail(&insn->call_node, &file->endbr_list); | ||
| 427 | file->nr_endbr++; | ||
| 428 | } else { | ||
| 429 | file->nr_endbr_int++; | ||
| 430 | } | ||
| 431 | } | ||
| 432 | } | ||
| 412 | } | 433 | } |
| 413 | } | 434 | } |
| 414 | 435 | ||
| @@ -520,14 +541,6 @@ static int add_dead_ends(struct objtool_file *file) · 105 unmodified lines | |||
| 520 | struct reloc *reloc; | 541 | struct reloc *reloc; |
| 521 | struct instruction *insn; | 542 | struct instruction *insn; |
| 522 | 543 | ||
| 523 | /* | ||
| 524 | * By default, "ud2" is a dead end unless otherwise annotated, because | ||
| 525 | * GCC 7 inserts it for certain divide-by-zero cases. | ||
| 526 | */ | ||
| 527 | for_each_insn(file, insn) | ||
| 528 | if (insn->type == INSN_BUG) | ||
| 529 | insn->dead_end = true; | ||
| 530 | |||
| 531 | /* | 544 | /* |
| 532 | * Check for manually annotated dead ends. | 545 | * Check for manually annotated dead ends. |
| 533 | */ | 546 | */ |
| @@ -731,6 +744,58 @@ static int create_retpoline_sites_sections(struct objtool_file *file) · 197 unmodified lines | |||
| 731 | return 0; | 744 | return 0; |
| 732 | } | 745 | } |
| 733 | 746 | ||
| 747 | static int create_ibt_endbr_seal_sections(struct objtool_file *file) | ||
| 748 | { | ||
| 749 | struct instruction *insn; | ||
| 750 | struct section *sec; | ||
| 751 | int idx; | ||
| 752 | |||
| 753 | sec = find_section_by_name(file->elf, ".ibt_endbr_seal"); | ||
| 754 | if (sec) { | ||
| 755 | WARN("file already has .ibt_endbr_seal, skipping"); | ||
| 756 | return 0; | ||
| 757 | } | ||
| 758 | |||
| 759 | idx = 0; | ||
| 760 | list_for_each_entry(insn, &file->endbr_list, call_node) | ||
| 761 | idx++; | ||
| 762 | |||
| 763 | if (stats) { | ||
| 764 | printf("ibt: ENDBR at function start: %d\n", file->nr_endbr); | ||
| 765 | printf("ibt: ENDBR inside functions: %d\n", file->nr_endbr_int); | ||
| 766 | printf("ibt: superfluous ENDBR: %d\n", idx); | ||
| 767 | } | ||
| 768 | |||
| 769 | if (!idx) | ||
| 770 | return 0; | ||
| 771 | |||
| 772 | sec = elf_create_section(file->elf, ".ibt_endbr_seal", 0, | ||
| 773 | sizeof(int), idx); | ||
| 774 | if (!sec) { | ||
| 775 | WARN("elf_create_section: .ibt_endbr_seal"); | ||
| 776 | return -1; | ||
| 777 | } | ||
| 778 | |||
| 779 | idx = 0; | ||
| 780 | list_for_each_entry(insn, &file->endbr_list, call_node) { | ||
| 781 | |||
| 782 | int *site = (int *)sec->data->d_buf + idx; | ||
| 783 | *site = 0; | ||
| 784 | |||
| 785 | if (elf_add_reloc_to_insn(file->elf, sec, | ||
| 786 | idx * sizeof(int), | ||
| 787 | R_X86_64_PC32, | ||
| 788 | insn->sec, insn->offset)) { | ||
| 789 | WARN("elf_add_reloc_to_insn: .ibt_endbr_seal"); | ||
| 790 | return -1; | ||
| 791 | } | ||
| 792 | |||
| 793 | idx++; | ||
| 794 | } | ||
| 795 | |||
| 796 | return 0; | ||
| 797 | } | ||
| 798 | |||
| 734 | static int create_mcount_loc_sections(struct objtool_file *file) | 799 | static int create_mcount_loc_sections(struct objtool_file *file) |
| 735 | { | 800 | { |
| 736 | struct section *sec; | 801 | struct section *sec; |
| @@ -1111,6 +1176,9 @@ static void annotate_call_site(struct objtool_file *file, · 374 unmodified lines | |||
| 1111 | list_add_tail(&insn->call_node, &file->mcount_loc_list); | 1176 | list_add_tail(&insn->call_node, &file->mcount_loc_list); |
| 1112 | return; | 1177 | return; |
| 1113 | } | 1178 | } |
| 1179 | |||
| 1180 | if (!sibling && dead_end_function(file, sym)) | ||
| 1181 | insn->dead_end = true; | ||
| 1114 | } | 1182 | } |
| 1115 | 1183 | ||
| 1116 | static void add_call_dest(struct objtool_file *file, struct instruction *insn, | 1184 | static void add_call_dest(struct objtool_file *file, struct instruction *insn, |
| @@ -1165,6 +1233,19 @@ static void add_retpoline_call(struct objtool_file *file, struct instruction *in · 48 unmodified lines | |||
| 1165 | 1233 | ||
| 1166 | annotate_call_site(file, insn, false); | 1234 | annotate_call_site(file, insn, false); |
| 1167 | } | 1235 | } |
| 1236 | |||
| 1237 | static bool same_function(struct instruction *insn1, struct instruction *insn2) | ||
| 1238 | { | ||
| 1239 | return insn1->func->pfunc == insn2->func->pfunc; | ||
| 1240 | } | ||
| 1241 | |||
| 1242 | static bool is_first_func_insn(struct instruction *insn) | ||
| 1243 | { | ||
| 1244 | return insn->offset == insn->func->offset || | ||
| 1245 | (insn->type == INSN_ENDBR && | ||
| 1246 | insn->offset == insn->func->offset + insn->len); | ||
| 1247 | } | ||
| 1248 | |||
| 1168 | /* | 1249 | /* |
| 1169 | * Find the destination instructions for all jumps. | 1250 | * Find the destination instructions for all jumps. |
| 1170 | */ | 1251 | */ |
| @@ -1245,8 +1326,8 @@ static int add_jump_destinations(struct objtool_file *file) · 74 unmodified lines | |||
| 1245 | insn->func->cfunc = insn->jump_dest->func; | 1326 | insn->func->cfunc = insn->jump_dest->func; |
| 1246 | insn->jump_dest->func->pfunc = insn->func; | 1327 | insn->jump_dest->func->pfunc = insn->func; |
| 1247 | 1328 | ||
| 1248 | } else if (insn->jump_dest->func->pfunc != insn->func->pfunc && | 1329 | } else if (!same_function(insn, insn->jump_dest) && |
| 1249 | insn->jump_dest->offset == insn->jump_dest->func->offset) { | 1330 | is_first_func_insn(insn->jump_dest)) { |
| 1250 | /* internal sibling call (without reloc) */ | 1331 | /* internal sibling call (without reloc) */ |
| 1251 | add_call_dest(file, insn, insn->jump_dest->func, true); | 1332 | add_call_dest(file, insn, insn->jump_dest->func, true); |
| 1252 | } | 1333 | } |
| @@ -1836,6 +1917,16 @@ static int read_unwind_hints(struct objtool_file *file) · 583 unmodified lines | |||
| 1836 | 1917 | ||
| 1837 | insn->hint = true; | 1918 | insn->hint = true; |
| 1838 | 1919 | ||
| 1920 | if (ibt && hint->type == UNWIND_HINT_TYPE_REGS_PARTIAL) { | ||
| 1921 | struct symbol *sym = find_symbol_by_offset(insn->sec, insn->offset); | ||
| 1922 | |||
| 1923 | if (sym && sym->bind == STB_GLOBAL && | ||
| 1924 | insn->type != INSN_ENDBR && !insn->noendbr) { | ||
| 1925 | WARN_FUNC("UNWIND_HINT_IRET_REGS without ENDBR", | ||
| 1926 | insn->sec, insn->offset); | ||
| 1927 | } | ||
| 1928 | } | ||
| 1929 | |||
| 1839 | if (hint->type == UNWIND_HINT_TYPE_FUNC) { | 1930 | if (hint->type == UNWIND_HINT_TYPE_FUNC) { |
| 1840 | insn->cfi = &func_cfi; | 1931 | insn->cfi = &func_cfi; |
| 1841 | continue; | 1932 | continue; |
| @@ -1860,6 +1951,32 @@ static int read_unwind_hints(struct objtool_file *file) · 18 unmodified lines | |||
| 1860 | return 0; | 1951 | return 0; |
| 1861 | } | 1952 | } |
| 1862 | 1953 | ||
| 1954 | static int read_noendbr_hints(struct objtool_file *file) | ||
| 1955 | { | ||
| 1956 | struct section *sec; | ||
| 1957 | struct instruction *insn; | ||
| 1958 | struct reloc *reloc; | ||
| 1959 | |||
| 1960 | sec = find_section_by_name(file->elf, ".rela.discard.noendbr"); | ||
| 1961 | if (!sec) | ||
| 1962 | return 0; | ||
| 1963 | |||
| 1964 | list_for_each_entry(reloc, &sec->reloc_list, list) { | ||
| 1965 | insn = find_insn(file, reloc->sym->sec, reloc->sym->offset + reloc->addend); | ||
| 1966 | if (!insn) { | ||
| 1967 | WARN("bad .discard.noendbr entry"); | ||
| 1968 | return -1; | ||
| 1969 | } | ||
| 1970 | |||
| 1971 | if (insn->type == INSN_ENDBR) | ||
| 1972 | WARN_FUNC("ANNOTATE_NOENDBR on ENDBR", insn->sec, insn->offset); | ||
| 1973 | |||
| 1974 | insn->noendbr = 1; | ||
| 1975 | } | ||
| 1976 | |||
| 1977 | return 0; | ||
| 1978 | } | ||
| 1979 | |||
| 1863 | static int read_retpoline_hints(struct objtool_file *file) | 1980 | static int read_retpoline_hints(struct objtool_file *file) |
| 1864 | { | 1981 | { |
| 1865 | struct section *sec; | 1982 | struct section *sec; |
| @@ -2086,10 +2203,6 @@ static int decode_sections(struct objtool_file *file) · 220 unmodified lines | |||
| 2086 | if (ret) | 2203 | if (ret) |
| 2087 | return ret; | 2204 | return ret; |
| 2088 | 2205 | ||
| 2089 | ret = add_dead_ends(file); | ||
| 2090 | if (ret) | ||
| 2091 | return ret; | ||
| 2092 | |||
| 2093 | add_ignores(file); | 2206 | add_ignores(file); |
| 2094 | add_uaccess_safe(file); | 2207 | add_uaccess_safe(file); |
| 2095 | 2208 | ||
| @@ -2097,6 +2210,13 @@ static int decode_sections(struct objtool_file *file) · 1 unmodified line | |||
| 2097 | if (ret) | 2210 | if (ret) |
| 2098 | return ret; | 2211 | return ret; |
| 2099 | 2212 | ||
| 2213 | /* | ||
| 2214 | * Must be before read_unwind_hints() since that needs insn->noendbr. | ||
| 2215 | */ | ||
| 2216 | ret = read_noendbr_hints(file); | ||
| 2217 | if (ret) | ||
| 2218 | return ret; | ||
| 2219 | |||
| 2100 | /* | 2220 | /* |
| 2101 | * Must be before add_{jump_call}_destination. | 2221 | * Must be before add_{jump_call}_destination. |
| 2102 | */ | 2222 | */ |
| @@ -2128,6 +2248,14 @@ static int decode_sections(struct objtool_file *file) · 25 unmodified lines | |||
| 2128 | if (ret) | 2248 | if (ret) |
| 2129 | return ret; | 2249 | return ret; |
| 2130 | 2250 | ||
| 2251 | /* | ||
| 2252 | * Must be after add_call_destinations() such that it can override | ||
| 2253 | * dead_end_function() marks. | ||
| 2254 | */ | ||
| 2255 | ret = add_dead_ends(file); | ||
| 2256 | if (ret) | ||
| 2257 | return ret; | ||
| 2258 | |||
| 2131 | ret = add_jump_table_alts(file); | 2259 | ret = add_jump_table_alts(file); |
| 2132 | if (ret) | 2260 | if (ret) |
| 2133 | return ret; | 2261 | return ret; |
| @@ -3026,6 +3154,115 @@ static struct instruction *next_insn_to_validate(struct objtool_file *file, · 892 unmodified lines | |||
| 3026 | return next_insn_same_sec(file, insn); | 3154 | return next_insn_same_sec(file, insn); |
| 3027 | } | 3155 | } |
| 3028 | 3156 | ||
| 3157 | static struct instruction * | ||
| 3158 | validate_ibt_reloc(struct objtool_file *file, struct reloc *reloc) | ||
| 3159 | { | ||
| 3160 | struct instruction *dest; | ||
| 3161 | struct section *sec; | ||
| 3162 | unsigned long off; | ||
| 3163 | |||
| 3164 | sec = reloc->sym->sec; | ||
| 3165 | off = reloc->sym->offset; | ||
| 3166 | |||
| 3167 | if ((reloc->sec->base->sh.sh_flags & SHF_EXECINSTR) && | ||
| 3168 | (reloc->type == R_X86_64_PC32 || reloc->type == R_X86_64_PLT32)) | ||
| 3169 | off += arch_dest_reloc_offset(reloc->addend); | ||
| 3170 | else | ||
| 3171 | off += reloc->addend; | ||
| 3172 | |||
| 3173 | dest = find_insn(file, sec, off); | ||
| 3174 | if (!dest) | ||
| 3175 | return NULL; | ||
| 3176 | |||
| 3177 | if (dest->type == INSN_ENDBR) { | ||
| 3178 | if (!list_empty(&dest->call_node)) | ||
| 3179 | list_del_init(&dest->call_node); | ||
| 3180 | |||
| 3181 | return NULL; | ||
| 3182 | } | ||
| 3183 | |||
| 3184 | if (reloc->sym->static_call_tramp) | ||
| 3185 | return NULL; | ||
| 3186 | |||
| 3187 | return dest; | ||
| 3188 | } | ||
| 3189 | |||
| 3190 | static void warn_noendbr(const char *msg, struct section *sec, unsigned long offset, | ||
| 3191 | struct instruction *dest) | ||
| 3192 | { | ||
| 3193 | WARN_FUNC("%srelocation to !ENDBR: %s+0x%lx", sec, offset, msg, | ||
| 3194 | dest->func ? dest->func->name : dest->sec->name, | ||
| 3195 | dest->func ? dest->offset - dest->func->offset : dest->offset); | ||
| 3196 | } | ||
| 3197 | |||
| 3198 | static void validate_ibt_dest(struct objtool_file *file, struct instruction *insn, | ||
| 3199 | struct instruction *dest) | ||
| 3200 | { | ||
| 3201 | if (dest->func && dest->func == insn->func) { | ||
| 3202 | /* | ||
| 3203 | * Anything from->to self is either _THIS_IP_ or IRET-to-self. | ||
| 3204 | * | ||
| 3205 | * There is no sane way to annotate _THIS_IP_ since the compiler treats the | ||
| 3206 | * relocation as a constant and is happy to fold in offsets, skewing any | ||
| 3207 | * annotation we do, leading to vast amounts of false-positives. | ||
| 3208 | * | ||
| 3209 | * There's also compiler generated _THIS_IP_ through KCOV and | ||
| 3210 | * such which we have no hope of annotating. | ||
| 3211 | * | ||
| 3212 | * As such, blanket accept self-references without issue. | ||
| 3213 | */ | ||
| 3214 | return; | ||
| 3215 | } | ||
| 3216 | |||
| 3217 | if (dest->noendbr) | ||
| 3218 | return; | ||
| 3219 | |||
| 3220 | warn_noendbr("", insn->sec, insn->offset, dest); | ||
| 3221 | } | ||
| 3222 | |||
| 3223 | static void validate_ibt_insn(struct objtool_file *file, struct instruction *insn) | ||
| 3224 | { | ||
| 3225 | struct instruction *dest; | ||
| 3226 | struct reloc *reloc; | ||
| 3227 | |||
| 3228 | switch (insn->type) { | ||
| 3229 | case INSN_CALL: | ||
| 3230 | case INSN_CALL_DYNAMIC: | ||
| 3231 | case INSN_JUMP_CONDITIONAL: | ||
| 3232 | case INSN_JUMP_UNCONDITIONAL: | ||
| 3233 | case INSN_JUMP_DYNAMIC: | ||
| 3234 | case INSN_JUMP_DYNAMIC_CONDITIONAL: | ||
| 3235 | case INSN_RETURN: | ||
| 3236 | /* | ||
| 3237 | * We're looking for code references setting up indirect code | ||
| 3238 | * flow. As such, ignore direct code flow and the actual | ||
| 3239 | * dynamic branches. | ||
| 3240 | */ | ||
| 3241 | return; | ||
| 3242 | |||
| 3243 | case INSN_NOP: | ||
| 3244 | /* | ||
| 3245 | * handle_group_alt() will create INSN_NOP instruction that | ||
| 3246 | * don't belong to any section, ignore all NOP since they won't | ||
| 3247 | * carry a (useful) relocation anyway. | ||
| 3248 | */ | ||
| 3249 | return; | ||
| 3250 | |||
| 3251 | default: | ||
| 3252 | break; | ||
| 3253 | } | ||
| 3254 | |||
| 3255 | for (reloc = insn_reloc(file, insn); | ||
| 3256 | reloc; | ||
| 3257 | reloc = find_reloc_by_dest_range(file->elf, insn->sec, | ||
| 3258 | reloc->offset + 1, | ||
| 3259 | (insn->offset + insn->len) - (reloc->offset + 1))) { | ||
| 3260 | dest = validate_ibt_reloc(file, reloc); | ||
| 3261 | if (dest) | ||
| 3262 | validate_ibt_dest(file, insn, dest); | ||
| 3263 | } | ||
| 3264 | } | ||
| 3265 | |||
| 3029 | /* | 3266 | /* |
| 3030 | * Follow the branch starting at the given instruction, and recursively follow | 3267 | * Follow the branch starting at the given instruction, and recursively follow |
| 3031 | * any other branches (jumps). Meanwhile, track the frame pointer state at | 3268 | * any other branches (jumps). Meanwhile, track the frame pointer state at |
| @@ -3115,9 +3352,8 @@ static int validate_branch(struct objtool_file *file, struct symbol *func, · 83 unmodified lines | |||
| 3115 | switch (insn->type) { | 3352 | switch (insn->type) { |
| 3116 | 3353 | ||
| 3117 | case INSN_RETURN: | 3354 | case INSN_RETURN: |
| 3118 | if (next_insn && next_insn->type == INSN_TRAP) { | 3355 | if (sls && !insn->retpoline_safe && |
| 3119 | next_insn->ignore = true; | 3356 | next_insn && next_insn->type != INSN_TRAP) { |
| 3120 | } else if (sls && !insn->retpoline_safe) { | ||
| 3121 | WARN_FUNC("missing int3 after ret", | 3357 | WARN_FUNC("missing int3 after ret", |
| 3122 | insn->sec, insn->offset); | 3358 | insn->sec, insn->offset); |
| 3123 | } | 3359 | } |
| @@ -3136,7 +3372,7 @@ static int validate_branch(struct objtool_file *file, struct symbol *func, · 12 unmodified lines | |||
| 3136 | return 1; | 3372 | return 1; |
| 3137 | } | 3373 | } |
| 3138 | 3374 | ||
| 3139 | if (dead_end_function(file, insn->call_dest)) | 3375 | if (insn->dead_end) |
| 3140 | return 0; | 3376 | return 0; |
| 3141 | 3377 | ||
| 3142 | break; | 3378 | break; |
| @@ -3164,9 +3400,8 @@ static int validate_branch(struct objtool_file *file, struct symbol *func, · 21 unmodified lines | |||
| 3164 | break; | 3400 | break; |
| 3165 | 3401 | ||
| 3166 | case INSN_JUMP_DYNAMIC: | 3402 | case INSN_JUMP_DYNAMIC: |
| 3167 | if (next_insn && next_insn->type == INSN_TRAP) { | 3403 | if (sls && !insn->retpoline_safe && |
| 3168 | next_insn->ignore = true; | 3404 | next_insn && next_insn->type != INSN_TRAP) { |
| 3169 | } else if (sls && !insn->retpoline_safe) { | ||
| 3170 | WARN_FUNC("missing int3 after indirect jump", | 3405 | WARN_FUNC("missing int3 after indirect jump", |
| 3171 | insn->sec, insn->offset); | 3406 | insn->sec, insn->offset); |
| 3172 | } | 3407 | } |
| @@ -3237,6 +3472,9 @@ static int validate_branch(struct objtool_file *file, struct symbol *func, · 64 unmodified lines | |||
| 3237 | break; | 3472 | break; |
| 3238 | } | 3473 | } |
| 3239 | 3474 | ||
| 3475 | if (ibt) | ||
| 3476 | validate_ibt_insn(file, insn); | ||
| 3477 | |||
| 3240 | if (insn->dead_end) | 3478 | if (insn->dead_end) |
| 3241 | return 0; | 3479 | return 0; |
| 3242 | 3480 | ||
| @@ -3337,7 +3575,7 @@ static bool ignore_unreachable_insn(struct objtool_file *file, struct instructio · 94 unmodified lines | |||
| 3337 | int i; | 3575 | int i; |
| 3338 | struct instruction *prev_insn; | 3576 | struct instruction *prev_insn; |
| 3339 | 3577 | ||
| 3340 | if (insn->ignore || insn->type == INSN_NOP) | 3578 | if (insn->ignore || insn->type == INSN_NOP || insn->type == INSN_TRAP) |
| 3341 | return true; | 3579 | return true; |
| 3342 | 3580 | ||
| 3343 | /* | 3581 | /* |
| @@ -3348,6 +3586,49 @@ static bool ignore_unreachable_insn(struct objtool_file *file, struct instructio · 4 unmodified lines | |||
| 3348 | !strcmp(insn->sec->name, ".altinstr_aux")) | 3586 | !strcmp(insn->sec->name, ".altinstr_aux")) |
| 3349 | return true; | 3587 | return true; |
| 3350 | 3588 | ||
| 3589 | /* | ||
| 3590 | * Whole archive runs might encounder dead code from weak symbols. | ||
| 3591 | * This is where the linker will have dropped the weak symbol in | ||
| 3592 | * favour of a regular symbol, but leaves the code in place. | ||
| 3593 | * | ||
| 3594 | * In this case we'll find a piece of code (whole function) that is not | ||
| 3595 | * covered by a !section symbol. Ignore them. | ||
| 3596 | */ | ||
| 3597 | if (!insn->func && lto) { | ||
| 3598 | int size = find_symbol_hole_containing(insn->sec, insn->offset); | ||
| 3599 | unsigned long end = insn->offset + size; | ||
| 3600 | |||
| 3601 | if (!size) /* not a hole */ | ||
| 3602 | return false; | ||
| 3603 | |||
| 3604 | if (size < 0) /* hole until the end */ | ||
| 3605 | return true; | ||
| 3606 | |||
| 3607 | sec_for_each_insn_continue(file, insn) { | ||
| 3608 | /* | ||
| 3609 | * If we reach a visited instruction at or before the | ||
| 3610 | * end of the hole, ignore the unreachable. | ||
| 3611 | */ | ||
| 3612 | if (insn->visited) | ||
| 3613 | return true; | ||
| 3614 | |||
| 3615 | if (insn->offset >= end) | ||
| 3616 | break; | ||
| 3617 | |||
| 3618 | /* | ||
| 3619 | * If this hole jumps to a .cold function, mark it ignore too. | ||
| 3620 | */ | ||
| 3621 | if (insn->jump_dest && insn->jump_dest->func && | ||
| 3622 | strstr(insn->jump_dest->func->name, ".cold")) { | ||
| 3623 | struct instruction *dest = insn->jump_dest; | ||
| 3624 | func_for_each_insn(file, dest->func, dest) | ||
| 3625 | dest->ignore = true; | ||
| 3626 | } | ||
| 3627 | } | ||
| 3628 | |||
| 3629 | return false; | ||
| 3630 | } | ||
| 3631 | |||
| 3351 | if (!insn->func) | 3632 | if (!insn->func) |
| 3352 | return false; | 3633 | return false; |
| 3353 | 3634 | ||
| @@ -3479,6 +3760,53 @@ static int validate_functions(struct objtool_file *file) · 125 unmodified lines | |||
| 3479 | return warnings; | 3760 | return warnings; |
| 3480 | } | 3761 | } |
| 3481 | 3762 | ||
| 3763 | static int validate_ibt(struct objtool_file *file) | ||
| 3764 | { | ||
| 3765 | struct section *sec; | ||
| 3766 | struct reloc *reloc; | ||
| 3767 | |||
| 3768 | for_each_sec(file, sec) { | ||
| 3769 | bool is_data; | ||
| 3770 | |||
| 3771 | /* already done in validate_branch() */ | ||
| 3772 | if (sec->sh.sh_flags & SHF_EXECINSTR) | ||
| 3773 | continue; | ||
| 3774 | |||
| 3775 | if (!sec->reloc) | ||
| 3776 | continue; | ||
| 3777 | |||
| 3778 | if (!strncmp(sec->name, ".orc", 4)) | ||
| 3779 | continue; | ||
| 3780 | |||
| 3781 | if (!strncmp(sec->name, ".discard", 8)) | ||
| 3782 | continue; | ||
| 3783 | |||
| 3784 | if (!strncmp(sec->name, ".debug", 6)) | ||
| 3785 | continue; | ||
| 3786 | |||
| 3787 | if (!strcmp(sec->name, "_error_injection_whitelist")) | ||
| 3788 | continue; | ||
| 3789 | |||
| 3790 | if (!strcmp(sec->name, "_kprobe_blacklist")) | ||
| 3791 | continue; | ||
| 3792 | |||
| 3793 | is_data = strstr(sec->name, ".data") || strstr(sec->name, ".rodata"); | ||
| 3794 | |||
| 3795 | list_for_each_entry(reloc, &sec->reloc->reloc_list, list) { | ||
| 3796 | struct instruction *dest; | ||
| 3797 | |||
| 3798 | dest = validate_ibt_reloc(file, reloc); | ||
| 3799 | if (is_data && dest && !dest->noendbr) { | ||
| 3800 | warn_noendbr("data ", reloc->sym->sec, | ||
| 3801 | reloc->sym->offset + reloc->addend, | ||
| 3802 | dest); | ||
| 3803 | } | ||
| 3804 | } | ||
| 3805 | } | ||
| 3806 | |||
| 3807 | return 0; | ||
| 3808 | } | ||
| 3809 | |||
| 3482 | static int validate_reachable_instructions(struct objtool_file *file) | 3810 | static int validate_reachable_instructions(struct objtool_file *file) |
| 3483 | { | 3811 | { |
| 3484 | struct instruction *insn; | 3812 | struct instruction *insn; |
| @@ -3501,6 +3829,16 @@ int check(struct objtool_file *file) · 16 unmodified lines | |||
| 3501 | { | 3829 | { |
| 3502 | int ret, warnings = 0; | 3830 | int ret, warnings = 0; |
| 3503 | 3831 | ||
| 3832 | if (lto && !(vmlinux || module)) { | ||
| 3833 | fprintf(stderr, "--lto requires: --vmlinux or --module\n"); | ||
| 3834 | return 1; | ||
| 3835 | } | ||
| 3836 | |||
| 3837 | if (ibt && !lto) { | ||
| 3838 | fprintf(stderr, "--ibt requires: --lto\n"); | ||
| 3839 | return 1; | ||
| 3840 | } | ||
| 3841 | |||
| 3504 | arch_initial_func_cfi_state(&initial_func_cfi); | 3842 | arch_initial_func_cfi_state(&initial_func_cfi); |
| 3505 | init_cfi_state(&init_cfi); | 3843 | init_cfi_state(&init_cfi); |
| 3506 | init_cfi_state(&func_cfi); | 3844 | init_cfi_state(&func_cfi); |
| @@ -3521,7 +3859,7 @@ int check(struct objtool_file *file) · 14 unmodified lines | |||
| 3521 | if (list_empty(&file->insn_list)) | 3859 | if (list_empty(&file->insn_list)) |
| 3522 | goto out; | 3860 | goto out; |
| 3523 | 3861 | ||
| 3524 | if (vmlinux && !validate_dup) { | 3862 | if (vmlinux && !lto) { |
| 3525 | ret = validate_vmlinux_functions(file); | 3863 | ret = validate_vmlinux_functions(file); |
| 3526 | if (ret < 0) | 3864 | if (ret < 0) |
| 3527 | goto out; | 3865 | goto out; |
| @@ -3547,6 +3885,13 @@ int check(struct objtool_file *file) · 19 unmodified lines | |||
| 3547 | goto out; | 3885 | goto out; |
| 3548 | warnings += ret; | 3886 | warnings += ret; |
| 3549 | 3887 | ||
| 3888 | if (ibt) { | ||
| 3889 | ret = validate_ibt(file); | ||
| 3890 | if (ret < 0) | ||
| 3891 | goto out; | ||
| 3892 | warnings += ret; | ||
| 3893 | } | ||
| 3894 | |||
| 3550 | if (!warnings) { | 3895 | if (!warnings) { |
| 3551 | ret = validate_reachable_instructions(file); | 3896 | ret = validate_reachable_instructions(file); |
| 3552 | if (ret < 0) | 3897 | if (ret < 0) |
| @@ -3573,6 +3918,13 @@ int check(struct objtool_file *file) · 20 unmodified lines | |||
| 3573 | warnings += ret; | 3918 | warnings += ret; |
| 3574 | } | 3919 | } |
| 3575 | 3920 | ||
| 3921 | if (ibt) { | ||
| 3922 | ret = create_ibt_endbr_seal_sections(file); | ||
| 3923 | if (ret < 0) | ||
| 3924 | goto out; | ||
| 3925 | warnings += ret; | ||
| 3926 | } | ||
| 3927 | |||
| 3576 | if (stats) { | 3928 | if (stats) { |
| 3577 | printf("nr_insns_visited: %ld\n", nr_insns_visited); | 3929 | printf("nr_insns_visited: %ld\n", nr_insns_visited); |
| 3578 | printf("nr_cfi: %ld\n", nr_cfi); | 3930 | printf("nr_cfi: %ld\n", nr_cfi); |
| @@ -83,6 +83,31 @@ static int symbol_by_offset(const void *key, const struct rb_node *node) · 82 unmodified lines | |||
| 83 | return 0; | 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 | struct section *find_section_by_name(const struct elf *elf, const char *name) | 111 | struct section *find_section_by_name(const struct elf *elf, const char *name) |
| 87 | { | 112 | { |
| 88 | struct section *sec; | 113 | struct section *sec; |
| @@ -162,6 +187,41 @@ struct symbol *find_symbol_containing(const struct section *sec, unsigned long o · 73 unmodified lines | |||
| 162 | return NULL; | 187 | return NULL; |
| 163 | } | 188 | } |
| 164 | 189 | ||
| 190 | /* | ||
| 191 | * Returns size of hole starting at @offset. | ||
| 192 | */ | ||
| 193 | int find_symbol_hole_containing(const struct section *sec, unsigned long offset) | ||
| 194 | { | ||
| 195 | struct symbol_hole hole = { | ||
| 196 | .key = offset, | ||
| 197 | .sym = NULL, | ||
| 198 | }; | ||
| 199 | struct rb_node *n; | ||
| 200 | struct symbol *s; | ||
| 201 | |||
| 202 | /* | ||
| 203 | * Find the rightmost symbol for which @offset is after it. | ||
| 204 | */ | ||
| 205 | n = rb_find(&hole, &sec->symbol_tree, symbol_hole_by_offset); | ||
| 206 | |||
| 207 | /* found a symbol that contains @offset */ | ||
| 208 | if (n) | ||
| 209 | return 0; /* not a hole */ | ||
| 210 | |||
| 211 | /* didn't find a symbol for which @offset is after it */ | ||
| 212 | if (!hole.sym) | ||
| 213 | return 0; /* not a hole */ | ||
| 214 | |||
| 215 | /* @offset >= sym->offset + sym->len, find symbol after it */ | ||
| 216 | n = rb_next(&hole.sym->node); | ||
| 217 | if (!n) | ||
| 218 | return -1; /* until end of address space */ | ||
| 219 | |||
| 220 | /* hole until start of next symbol */ | ||
| 221 | s = rb_entry(n, struct symbol, node); | ||
| 222 | return s->offset - offset; | ||
| 223 | } | ||
| 224 | |||
| 165 | struct symbol *find_func_containing(struct section *sec, unsigned long offset) | 225 | struct symbol *find_func_containing(struct section *sec, unsigned long offset) |
| 166 | { | 226 | { |
| 167 | struct rb_node *node; | 227 | struct rb_node *node; |
| @@ -1019,6 +1079,9 @@ int elf_write(struct elf *elf) · 851 unmodified lines | |||
| 1019 | struct section *sec; | 1079 | struct section *sec; |
| 1020 | Elf_Scn *s; | 1080 | Elf_Scn *s; |
| 1021 | 1081 | ||
| 1082 | if (dryrun) | ||
| 1083 | return 0; | ||
| 1084 | |||
| 1022 | /* Update changed relocation sections and section headers: */ | 1085 | /* Update changed relocation sections and section headers: */ |
| 1023 | list_for_each_entry(sec, &elf->sections, list) { | 1086 | list_for_each_entry(sec, &elf->sections, list) { |
| 1024 | if (sec->changed) { | 1087 | if (sec->changed) { |
| @@ -27,6 +27,7 @@ enum insn_type { · 26 unmodified lines | |||
| 27 | INSN_STD, | 27 | INSN_STD, |
| 28 | INSN_CLD, | 28 | INSN_CLD, |
| 29 | INSN_TRAP, | 29 | INSN_TRAP, |
| 30 | INSN_ENDBR, | ||
| 30 | INSN_OTHER, | 31 | INSN_OTHER, |
| 31 | }; | 32 | }; |
| 32 | 33 | ||
| @@ -9,7 +9,8 @@ · 8 unmodified lines | |||
| 9 | 9 | ||
| 10 | extern const struct option check_options[]; | 10 | extern const struct option check_options[]; |
| 11 | extern bool no_fp, no_unreachable, retpoline, module, backtrace, uaccess, stats, | 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 | extern int cmd_parse_options(int argc, const char **argv, const char * const usage[]); | 15 | extern int cmd_parse_options(int argc, const char **argv, const char * const usage[]); |
| 15 | 16 | ||
| @@ -45,11 +45,18 @@ struct instruction { · 44 unmodified lines | |||
| 45 | unsigned int len; | 45 | unsigned int len; |
| 46 | enum insn_type type; | 46 | enum insn_type type; |
| 47 | unsigned long immediate; | 47 | unsigned long immediate; |
| 48 | bool dead_end, ignore, ignore_alts; | 48 | |
| 49 | bool hint; | 49 | u8 dead_end : 1, |
| 50 | bool retpoline_safe; | 50 | ignore : 1, |
| 51 | ignore_alts : 1, | ||
| 52 | hint : 1, | ||
| 53 | retpoline_safe : 1, | ||
| 54 | noendbr : 1; | ||
| 55 | /* 2 bit hole */ | ||
| 51 | s8 instr; | 56 | s8 instr; |
| 52 | u8 visited; | 57 | u8 visited; |
| 58 | /* u8 hole */ | ||
| 59 | |||
| 53 | struct alt_group *alt_group; | 60 | struct alt_group *alt_group; |
| 54 | struct symbol *call_dest; | 61 | struct symbol *call_dest; |
| 55 | struct instruction *jump_dest; | 62 | struct instruction *jump_dest; |
| @@ -152,6 +152,7 @@ struct symbol *find_func_by_offset(struct section *sec, unsigned long offset); · 151 unmodified lines | |||
| 152 | struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset); | 152 | struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset); |
| 153 | struct symbol *find_symbol_by_name(const struct elf *elf, const char *name); | 153 | struct symbol *find_symbol_by_name(const struct elf *elf, const char *name); |
| 154 | struct symbol *find_symbol_containing(const struct section *sec, unsigned long offset); | 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 | struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, unsigned long offset); | 156 | struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, unsigned long offset); |
| 156 | struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *sec, | 157 | struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *sec, |
| 157 | unsigned long offset, unsigned int len); | 158 | unsigned long offset, unsigned int len); |
| @@ -26,8 +26,12 @@ struct objtool_file { · 25 unmodified lines | |||
| 26 | struct list_head retpoline_call_list; | 26 | struct list_head retpoline_call_list; |
| 27 | struct list_head static_call_list; | 27 | struct list_head static_call_list; |
| 28 | struct list_head mcount_loc_list; | 28 | struct list_head mcount_loc_list; |
| 29 | struct list_head endbr_list; | ||
| 29 | bool ignore_unreachables, c_file, hints, rodata; | 30 | bool ignore_unreachables, c_file, hints, rodata; |
| 30 | 31 | ||
| 32 | unsigned int nr_endbr; | ||
| 33 | unsigned int nr_endbr_int; | ||
| 34 | |||
| 31 | unsigned long jl_short, jl_long; | 35 | unsigned long jl_short, jl_long; |
| 32 | unsigned long jl_nop_short, jl_nop_long; | 36 | unsigned long jl_nop_short, jl_nop_long; |
| 33 | 37 | ||
| @@ -22,6 +22,8 @@ static inline char *offstr(struct section *sec, unsigned long offset) · 21 unmodified lines | |||
| 22 | unsigned long name_off; | 22 | unsigned long name_off; |
| 23 | 23 | ||
| 24 | func = find_func_containing(sec, offset); | 24 | func = find_func_containing(sec, offset); |
| 25 | if (!func) | ||
| 26 | func = find_symbol_containing(sec, offset); | ||
| 25 | if (func) { | 27 | if (func) { |
| 26 | name = func->name; | 28 | name = func->name; |
| 27 | name_off = offset - func->offset; | 29 | name_off = offset - func->offset; |
| @@ -128,6 +128,7 @@ struct objtool_file *objtool_open_read(const char *_objname) · 127 unmodified lines | |||
| 128 | INIT_LIST_HEAD(&file.retpoline_call_list); | 128 | INIT_LIST_HEAD(&file.retpoline_call_list); |
| 129 | INIT_LIST_HEAD(&file.static_call_list); | 129 | INIT_LIST_HEAD(&file.static_call_list); |
| 130 | INIT_LIST_HEAD(&file.mcount_loc_list); | 130 | INIT_LIST_HEAD(&file.mcount_loc_list); |
| 131 | INIT_LIST_HEAD(&file.endbr_list); | ||
| 131 | file.c_file = !vmlinux && find_section_by_name(file.elf, ".comment"); | 132 | file.c_file = !vmlinux && find_section_by_name(file.elf, ".comment"); |
| 132 | file.ignore_unreachables = no_unreachable; | 133 | file.ignore_unreachables = no_unreachable; |
| 133 | file.hints = false; | 134 | file.hints = false; |