diff options
author | Peter Zijlstra | 2022-03-08 16:30:56 +0100 |
---|---|---|
committer | Peter Zijlstra | 2022-03-15 10:32:47 +0100 |
commit | ed53a0d971926e484d86cce617ec02a7ee85c3fe (patch) | |
tree | 1423484f3912113c56c0b77fa5b0397113040828 /scripts | |
parent | 89bc853eae4ad125030ef99f207ba76c2f00a26e (diff) |
x86/alternative: Use .ibt_endbr_seal to seal indirect calls
Objtool's --ibt option generates .ibt_endbr_seal which lists
superfluous ENDBR instructions. That is those instructions for which
the function is never indirectly called.
Overwrite these ENDBR instructions with a NOP4 such that these
function can never be indirect called, reducing the number of viable
ENDBR targets in the kernel.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
Link: https://lore.kernel.org/r/20220308154319.822545231@infradead.org
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/Makefile.build | 47 | ||||
-rwxr-xr-x | scripts/link-vmlinux.sh | 10 |
2 files changed, 46 insertions, 11 deletions
diff --git a/scripts/Makefile.build b/scripts/Makefile.build index a4b89b757287..926d2549a59c 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -86,12 +86,18 @@ ifdef need-builtin targets-for-builtin += $(obj)/built-in.a endif -targets-for-modules := $(patsubst %.o, %.mod, $(filter %.o, $(obj-m))) +targets-for-modules := ifdef CONFIG_LTO_CLANG targets-for-modules += $(patsubst %.o, %.lto.o, $(filter %.o, $(obj-m))) endif +ifdef CONFIG_X86_KERNEL_IBT +targets-for-modules += $(patsubst %.o, %.objtool, $(filter %.o, $(obj-m))) +endif + +targets-for-modules += $(patsubst %.o, %.mod, $(filter %.o, $(obj-m))) + ifdef need-modorder targets-for-modules += $(obj)/modules.order endif @@ -230,6 +236,7 @@ objtool := $(objtree)/tools/objtool/objtool objtool_args = \ $(if $(CONFIG_UNWINDER_ORC),orc generate,check) \ $(if $(part-of-module), --module) \ + $(if $(CONFIG_X86_KERNEL_IBT), --lto --ibt) \ $(if $(CONFIG_FRAME_POINTER),, --no-fp) \ $(if $(CONFIG_GCOV_KERNEL)$(CONFIG_LTO_CLANG), --no-unreachable)\ $(if $(CONFIG_RETPOLINE), --retpoline) \ @@ -237,8 +244,8 @@ objtool_args = \ $(if $(CONFIG_FTRACE_MCOUNT_USE_OBJTOOL), --mcount) \ $(if $(CONFIG_SLS), --sls) -cmd_objtool = $(if $(objtool-enabled), ; $(objtool) $(objtool_args) $@) -cmd_gen_objtooldep = $(if $(objtool-enabled), { echo ; echo '$@: $$(wildcard $(objtool))' ; } >> $(dot-target).cmd) +cmd_objtool = $(if $(objtool-enabled), ; $(objtool) $(objtool_args) $(@:.objtool=.o)) +cmd_gen_objtooldep = $(if $(objtool-enabled), { echo ; echo '$(@:.objtool=.o): $$(wildcard $(objtool))' ; } >> $(dot-target).cmd) endif # CONFIG_STACK_VALIDATION @@ -247,6 +254,21 @@ ifdef CONFIG_LTO_CLANG # Skip objtool for LLVM bitcode $(obj)/%.o: objtool-enabled := +# objtool was skipped for LLVM bitcode, run it now that we have compiled +# modules into native code +$(obj)/%.lto.o: objtool-enabled = y +$(obj)/%.lto.o: part-of-module := y + +else ifdef CONFIG_X86_KERNEL_IBT + +# Skip objtool on individual files +$(obj)/%.o: objtool-enabled := + +# instead run objtool on the module as a whole, right before +# the final link pass with the linker script. +$(obj)/%.objtool: objtool-enabled = y +$(obj)/%.objtool: part-of-module := y + else # 'OBJECT_FILES_NON_STANDARD := y': skip objtool checking for a directory @@ -292,18 +314,13 @@ ifdef CONFIG_LTO_CLANG # Module .o files may contain LLVM bitcode, compile them into native code # before ELF processing quiet_cmd_cc_lto_link_modules = LTO [M] $@ -cmd_cc_lto_link_modules = \ + cmd_cc_lto_link_modules = \ $(LD) $(ld_flags) -r -o $@ \ $(shell [ -s $(@:.lto.o=.o.symversions) ] && \ echo -T $(@:.lto.o=.o.symversions)) \ --whole-archive $(filter-out FORCE,$^) \ $(cmd_objtool) -# objtool was skipped for LLVM bitcode, run it now that we have compiled -# modules into native code -$(obj)/%.lto.o: objtool-enabled = y -$(obj)/%.lto.o: part-of-module := y - $(obj)/%.lto.o: $(obj)/%.o FORCE $(call if_changed,cc_lto_link_modules) endif @@ -316,6 +333,18 @@ cmd_mod = { \ $(obj)/%.mod: $(obj)/%$(mod-prelink-ext).o FORCE $(call if_changed,mod) +# +# Since objtool will re-write the file it will change the timestamps, therefore +# it is critical that the %.objtool file gets a timestamp *after* objtool runs. +# +# Additionally, care must be had with ordering this rule against the other rules +# that take %.o as a dependency. +# +cmd_objtool_mod = true $(cmd_objtool) ; touch $@ + +$(obj)/%.objtool: $(obj)/%$(mod-prelink-ext).o FORCE + $(call if_changed,objtool_mod) + quiet_cmd_cc_lst_c = MKLST $@ cmd_cc_lst_c = $(CC) $(c_flags) -g -c -o $*.o $< && \ $(CONFIG_SHELL) $(srctree)/scripts/makelst $*.o \ diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index 9b08dca26f99..f704034ebbe6 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -108,7 +108,9 @@ objtool_link() local objtoolcmd; local objtoolopt; - if is_enabled CONFIG_LTO_CLANG && is_enabled CONFIG_STACK_VALIDATION; then + if is_enabled CONFIG_STACK_VALIDATION && \ + ( is_enabled CONFIG_LTO_CLANG || is_enabled CONFIG_X86_KERNEL_IBT ); then + # Don't perform vmlinux validation unless explicitly requested, # but run objtool on vmlinux.o now that we have an object file. if is_enabled CONFIG_UNWINDER_ORC; then @@ -117,6 +119,10 @@ objtool_link() objtoolopt="${objtoolopt} --lto" + if is_enabled CONFIG_X86_KERNEL_IBT; then + objtoolopt="${objtoolopt} --ibt" + fi + if is_enabled CONFIG_FTRACE_MCOUNT_USE_OBJTOOL; then objtoolopt="${objtoolopt} --mcount" fi @@ -168,7 +174,7 @@ vmlinux_link() # skip output file argument shift - if is_enabled CONFIG_LTO_CLANG; then + if is_enabled CONFIG_LTO_CLANG || is_enabled CONFIG_X86_KERNEL_IBT; then # Use vmlinux.o instead of performing the slow LTO link again. objs=vmlinux.o libs= |