From 0e731dbc18241d68318e0a7d2c2c0087c9073fb9 Mon Sep 17 00:00:00 2001 From: Sami Tolvanen Date: Fri, 17 Jul 2020 12:04:27 -0700 Subject: objtool: Don't autodetect vmlinux.o With LTO, we run objtool on vmlinux.o, but don't want noinstr validation. This change requires --vmlinux to be passed to objtool explicitly. Suggested-by: Peter Zijlstra Signed-off-by: Sami Tolvanen Reviewed-by: Kees Cook --- scripts/link-vmlinux.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts/link-vmlinux.sh') diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index c5919d5a0b4f..423a4106f0dd 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -106,7 +106,7 @@ objtool_link() local objtoolopt; if [ -n "${CONFIG_VMLINUX_VALIDATION}" ]; then - objtoolopt="check" + objtoolopt="check --vmlinux" if [ -z "${CONFIG_FRAME_POINTER}" ]; then objtoolopt="${objtoolopt} --no-fp" fi -- cgit v1.2.3 From 41425ebe20245c99b44d6ba0f017be9bfc28414f Mon Sep 17 00:00:00 2001 From: Sami Tolvanen Date: Wed, 30 Sep 2020 14:36:59 -0700 Subject: objtool: Split noinstr validation from --vmlinux This change adds a --noinstr flag to objtool to allow us to specify that we're processing vmlinux.o without also enabling noinstr validation. This is needed to avoid false positives with LTO when we run objtool on vmlinux.o without CONFIG_DEBUG_ENTRY. Signed-off-by: Sami Tolvanen --- scripts/link-vmlinux.sh | 2 +- tools/objtool/builtin-check.c | 3 ++- tools/objtool/builtin.h | 2 +- tools/objtool/check.c | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) (limited to 'scripts/link-vmlinux.sh') diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index 423a4106f0dd..18aed761f9c0 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -106,7 +106,7 @@ objtool_link() local objtoolopt; if [ -n "${CONFIG_VMLINUX_VALIDATION}" ]; then - objtoolopt="check --vmlinux" + objtoolopt="check --vmlinux --noinstr" if [ -z "${CONFIG_FRAME_POINTER}" ]; then objtoolopt="${objtoolopt} --no-fp" fi diff --git a/tools/objtool/builtin-check.c b/tools/objtool/builtin-check.c index facfc10bc5dc..b84cdc72b51f 100644 --- a/tools/objtool/builtin-check.c +++ b/tools/objtool/builtin-check.c @@ -18,7 +18,7 @@ #include "builtin.h" #include "objtool.h" -bool no_fp, no_unreachable, retpoline, module, backtrace, uaccess, stats, validate_dup, vmlinux, mcount; +bool no_fp, no_unreachable, retpoline, module, backtrace, uaccess, stats, validate_dup, vmlinux, mcount, noinstr; static const char * const check_usage[] = { "objtool check [] file.o", @@ -34,6 +34,7 @@ const struct option check_options[] = { OPT_BOOLEAN('a', "uaccess", &uaccess, "enable uaccess checking"), OPT_BOOLEAN('s', "stats", &stats, "print statistics"), OPT_BOOLEAN('d', "duplicate", &validate_dup, "duplicate validation for vmlinux.o"), + OPT_BOOLEAN('n', "noinstr", &noinstr, "noinstr validation for vmlinux.o"), OPT_BOOLEAN('l', "vmlinux", &vmlinux, "vmlinux.o validation"), OPT_BOOLEAN('M', "mcount", &mcount, "generate __mcount_loc"), OPT_END(), diff --git a/tools/objtool/builtin.h b/tools/objtool/builtin.h index 94565a72b701..2502bb27de17 100644 --- a/tools/objtool/builtin.h +++ b/tools/objtool/builtin.h @@ -8,7 +8,7 @@ #include extern const struct option check_options[]; -extern bool no_fp, no_unreachable, retpoline, module, backtrace, uaccess, stats, validate_dup, vmlinux, mcount; +extern bool no_fp, no_unreachable, retpoline, module, backtrace, uaccess, stats, validate_dup, vmlinux, mcount, noinstr; extern int cmd_check(int argc, const char **argv); extern int cmd_orc(int argc, const char **argv); diff --git a/tools/objtool/check.c b/tools/objtool/check.c index ab87fb92793c..85993e606782 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -244,7 +244,7 @@ static void init_insn_state(struct insn_state *state, struct section *sec) * not correctly determine insn->call_dest->sec (external symbols do * not have a section). */ - if (vmlinux && sec) + if (vmlinux && noinstr && sec) state->noinstr = sec->noinstr; } -- cgit v1.2.3 From b1a1a1a09b4606d41723a426110382d2077c26fb Mon Sep 17 00:00:00 2001 From: Sami Tolvanen Date: Mon, 13 Apr 2020 16:10:13 -0700 Subject: kbuild: lto: postpone objtool With LTO, LLVM bitcode won't be compiled into native code until modpost_link, or modfinal for modules. This change postpones calls to objtool until after these steps, and moves objtool_args to Makefile.lib, so the arguments can be reused in Makefile.modfinal. As we didn't have objects to process earlier, we use --duplicate when processing vmlinux.o. This change also disables unreachable instruction warnings with LTO to avoid warnings about the int3 padding between functions. Signed-off-by: Sami Tolvanen Reviewed-by: Kees Cook --- scripts/Makefile.build | 22 ++-------------------- scripts/Makefile.lib | 12 ++++++++++++ scripts/Makefile.modfinal | 19 ++++++++++++++++--- scripts/link-vmlinux.sh | 28 +++++++++++++++++++++++++--- 4 files changed, 55 insertions(+), 26 deletions(-) (limited to 'scripts/link-vmlinux.sh') diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 59fabd9685ee..3f6bf0ea7c0e 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -218,30 +218,11 @@ cmd_record_mcount = $(if $(findstring $(strip $(CC_FLAGS_FTRACE)),$(_c_flags)), endif # CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT ifdef CONFIG_STACK_VALIDATION +ifndef CONFIG_LTO_CLANG ifneq ($(SKIP_STACK_VALIDATION),1) __objtool_obj := $(objtree)/tools/objtool/objtool -objtool_args = $(if $(CONFIG_UNWINDER_ORC),orc generate,check) - -objtool_args += $(if $(part-of-module), --module,) - -ifndef CONFIG_FRAME_POINTER -objtool_args += --no-fp -endif -ifdef CONFIG_GCOV_KERNEL -objtool_args += --no-unreachable -endif -ifdef CONFIG_RETPOLINE - objtool_args += --retpoline -endif -ifdef CONFIG_X86_SMAP - objtool_args += --uaccess -endif -ifdef CONFIG_FTRACE_MCOUNT_USE_OBJTOOL - objtool_args += --mcount -endif - # 'OBJECT_FILES_NON_STANDARD := y': skip objtool checking for a directory # 'OBJECT_FILES_NON_STANDARD_foo.o := 'y': skip objtool checking for a file # 'OBJECT_FILES_NON_STANDARD_foo.o := 'n': override directory skip for a file @@ -253,6 +234,7 @@ objtool_obj = $(if $(patsubst y%,, \ $(__objtool_obj)) endif # SKIP_STACK_VALIDATION +endif # CONFIG_LTO_CLANG endif # CONFIG_STACK_VALIDATION # Rebuild all objects when objtool changes, or is enabled/disabled. diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 3ff3dbb3a830..6d004143c4d7 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -220,6 +220,18 @@ dtc_cpp_flags = -Wp,-MMD,$(depfile).pre.tmp -nostdinc \ $(addprefix -I,$(DTC_INCLUDE)) \ -undef -D__DTS__ +# Objtool arguments are also needed for modfinal with LTO, so we define +# then here to avoid duplication. +objtool_args = \ + $(if $(CONFIG_UNWINDER_ORC),orc generate,check) \ + $(if $(part-of-module), --module,) \ + $(if $(CONFIG_FRAME_POINTER),, --no-fp) \ + $(if $(or $(CONFIG_GCOV_KERNEL),$(CONFIG_LTO_CLANG)), \ + --no-unreachable,) \ + $(if $(CONFIG_RETPOLINE), --retpoline,) \ + $(if $(CONFIG_X86_SMAP), --uaccess,) \ + $(if $(CONFIG_FTRACE_MCOUNT_USE_OBJTOOL), --mcount,) + # Useful for describing the dependency of composite objects # Usage: # $(call multi_depend, multi_used_targets, suffix_to_remove, suffix_to_add) diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal index 6de2c35b64e8..735e11e9041b 100644 --- a/scripts/Makefile.modfinal +++ b/scripts/Makefile.modfinal @@ -9,7 +9,7 @@ __modfinal: include include/config/auto.conf include $(srctree)/scripts/Kbuild.include -# for c_flags +# for c_flags and objtool_args include $(srctree)/scripts/Makefile.lib # find all modules listed in modules.order @@ -34,10 +34,23 @@ ifdef CONFIG_LTO_CLANG # With CONFIG_LTO_CLANG, reuse the object file we compiled for modpost to # avoid a second slow LTO link prelink-ext := .lto -endif + +# ELF processing was skipped earlier because we didn't have native code, +# so let's now process the prelinked binary before we link the module. + +ifdef CONFIG_STACK_VALIDATION +ifneq ($(SKIP_STACK_VALIDATION),1) +cmd_ld_ko_o += \ + $(objtree)/tools/objtool/objtool $(objtool_args) \ + $(@:.ko=$(prelink-ext).o); + +endif # SKIP_STACK_VALIDATION +endif # CONFIG_STACK_VALIDATION + +endif # CONFIG_LTO_CLANG quiet_cmd_ld_ko_o = LD [M] $@ - cmd_ld_ko_o = \ + cmd_ld_ko_o += \ $(LD) -r $(KBUILD_LDFLAGS) \ $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \ -T scripts/module.lds -o $@ $(filter %.o, $^); \ diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index 18aed761f9c0..3b261b0f74f0 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -103,14 +103,36 @@ modpost_link() objtool_link() { + local objtoolcmd; local objtoolopt; + if [ "${CONFIG_LTO_CLANG} ${CONFIG_STACK_VALIDATION}" = "y y" ]; then + # Don't perform vmlinux validation unless explicitly requested, + # but run objtool on vmlinux.o now that we have an object file. + if [ -n "${CONFIG_UNWINDER_ORC}" ]; then + objtoolcmd="orc generate" + fi + + objtoolopt="${objtoolopt} --duplicate" + + if [ -n "${CONFIG_FTRACE_MCOUNT_USE_OBJTOOL}" ]; then + objtoolopt="${objtoolopt} --mcount" + fi + fi + if [ -n "${CONFIG_VMLINUX_VALIDATION}" ]; then - objtoolopt="check --vmlinux --noinstr" + objtoolopt="${objtoolopt} --noinstr" + fi + + if [ -n "${objtoolopt}" ]; then + if [ -z "${objtoolcmd}" ]; then + objtoolcmd="check" + fi + objtoolopt="${objtoolopt} --vmlinux" if [ -z "${CONFIG_FRAME_POINTER}" ]; then objtoolopt="${objtoolopt} --no-fp" fi - if [ -n "${CONFIG_GCOV_KERNEL}" ]; then + if [ -n "${CONFIG_GCOV_KERNEL}" ] || [ -n "${CONFIG_LTO_CLANG}" ]; then objtoolopt="${objtoolopt} --no-unreachable" fi if [ -n "${CONFIG_RETPOLINE}" ]; then @@ -120,7 +142,7 @@ objtool_link() objtoolopt="${objtoolopt} --uaccess" fi info OBJTOOL ${1} - tools/objtool/objtool ${objtoolopt} ${1} + tools/objtool/objtool ${objtoolcmd} ${objtoolopt} ${1} fi } -- cgit v1.2.3