From 2a61f4747eeaa85ce26ca9fbd81421b15facd018 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 28 May 2018 18:22:00 +0900 Subject: stack-protector: test compiler capability in Kconfig and drop AUTO mode Move the test for -fstack-protector(-strong) option to Kconfig. If the compiler does not support the option, the corresponding menu is automatically hidden. If STRONG is not supported, it will fall back to REGULAR. If REGULAR is not supported, it will be disabled. This means, AUTO is implicitly handled by the dependency solver of Kconfig, hence removed. I also turned the 'choice' into only two boolean symbols. The use of 'choice' is not a good idea here, because all of all{yes,mod,no}config would choose the first visible value, while we want allnoconfig to disable as many features as possible. X86 has additional shell scripts in case the compiler supports those options, but generates broken code. I added CC_HAS_SANE_STACKPROTECTOR to test this. I had to add -m32 to gcc-x86_32-has-stack-protector.sh to make it work correctly. Signed-off-by: Masahiro Yamada Acked-by: Kees Cook --- arch/Kconfig | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) (limited to 'arch/Kconfig') diff --git a/arch/Kconfig b/arch/Kconfig index 8a7f7e1f2ca7..2c7c3cf8adfc 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -536,13 +536,16 @@ config HAVE_CC_STACKPROTECTOR bool help An arch should select this symbol if: - - its compiler supports the -fstack-protector option - it has implemented a stack canary (e.g. __stack_chk_guard) -choice - prompt "Stack Protector buffer overflow detection" +config CC_HAS_STACKPROTECTOR_NONE + def_bool $(cc-option,-fno-stack-protector) + +config CC_STACKPROTECTOR + bool "Stack Protector buffer overflow detection" depends on HAVE_CC_STACKPROTECTOR - default CC_STACKPROTECTOR_AUTO + depends on $(cc-option,-fstack-protector) + default y help This option turns on the "stack-protector" GCC feature. This feature puts, at the beginning of functions, a canary value on @@ -552,14 +555,6 @@ choice overwrite the canary, which gets detected and the attack is then neutralized via a kernel panic. -config CC_STACKPROTECTOR_NONE - bool "None" - help - Disable "stack-protector" GCC feature. - -config CC_STACKPROTECTOR_REGULAR - bool "Regular" - help Functions will have the stack-protector canary logic added if they have an 8-byte or larger character array on the stack. @@ -571,7 +566,10 @@ config CC_STACKPROTECTOR_REGULAR by about 0.3%. config CC_STACKPROTECTOR_STRONG - bool "Strong" + bool "Strong Stack Protector" + depends on CC_STACKPROTECTOR + depends on $(cc-option,-fstack-protector-strong) + default y help Functions will have the stack-protector canary logic added in any of the following conditions: @@ -589,14 +587,6 @@ config CC_STACKPROTECTOR_STRONG about 20% of all kernel functions, which increases the kernel code size by about 2%. -config CC_STACKPROTECTOR_AUTO - bool "Automatic" - help - If the compiler supports it, the best available stack-protector - option will be chosen. - -endchoice - config HAVE_ARCH_WITHIN_STACK_FRAMES bool help -- cgit v1.2.3-59-g8ed1b From 59f53855babf757ac7be19995670ab884aaf9b71 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 28 May 2018 18:22:06 +0900 Subject: gcc-plugins: test plugin support in Kconfig and clean up Makefile Run scripts/gcc-plugin.sh from Kconfig so that users can enable GCC_PLUGINS only when the compiler supports building plugins. Kconfig defines a new symbol, PLUGIN_HOSTCC. This will contain the compiler (g++ or gcc) used for building plugins, or empty if the plugin can not be supported at all. This allows us to remove all ugly testing in Makefile.gcc-plugins. Signed-off-by: Masahiro Yamada Acked-by: Kees Cook --- arch/Kconfig | 10 ++++++ scripts/Kconfig.include | 3 ++ scripts/Makefile.gcc-plugins | 79 ++++++++++++-------------------------------- scripts/gcc-plugins/Makefile | 1 + 4 files changed, 36 insertions(+), 57 deletions(-) (limited to 'arch/Kconfig') diff --git a/arch/Kconfig b/arch/Kconfig index 2c7c3cf8adfc..e4a47d640a87 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -398,6 +398,15 @@ config SECCOMP_FILTER See Documentation/prctl/seccomp_filter.txt for details. +preferred-plugin-hostcc := $(if-success,[ $(gcc-version) -ge 40800 ],$(HOSTCXX),$(HOSTCC)) + +config PLUGIN_HOSTCC + string + default "$(shell,$(srctree)/scripts/gcc-plugin.sh "$(preferred-plugin-hostcc)" "$(HOSTCXX)" "$(CC)")" + help + Host compiler used to build GCC plugins. This can be $(HOSTCXX), + $(HOSTCC), or a null string if GCC plugin is unsupported. + config HAVE_GCC_PLUGINS bool help @@ -407,6 +416,7 @@ config HAVE_GCC_PLUGINS menuconfig GCC_PLUGINS bool "GCC plugins" depends on HAVE_GCC_PLUGINS + depends on PLUGIN_HOSTCC != "" depends on !COMPILE_TEST help GCC plugins are loadable modules that provide extra features to the diff --git a/scripts/Kconfig.include b/scripts/Kconfig.include index bf7c0c9fa3a4..dad5583451af 100644 --- a/scripts/Kconfig.include +++ b/scripts/Kconfig.include @@ -25,3 +25,6 @@ cc-option = $(success,$(CC) -Werror $(1) -E -x c /dev/null -o /dev/null) # $(ld-option,) # Return y if the linker supports , n otherwise ld-option = $(success,$(LD) -v $(1)) + +# gcc version including patch level +gcc-version := $(shell,$(srctree)/scripts/gcc-version.sh -p $(CC) | sed 's/^0*//') diff --git a/scripts/Makefile.gcc-plugins b/scripts/Makefile.gcc-plugins index 32bdf184eced..c961b9a65d11 100644 --- a/scripts/Makefile.gcc-plugins +++ b/scripts/Makefile.gcc-plugins @@ -1,72 +1,37 @@ # SPDX-License-Identifier: GPL-2.0 -ifdef CONFIG_GCC_PLUGINS - __PLUGINCC := $(call cc-ifversion, -ge, 0408, $(HOSTCXX), $(HOSTCC)) - PLUGINCC := $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-plugin.sh "$(__PLUGINCC)" "$(HOSTCXX)" "$(CC)") - - SANCOV_PLUGIN := -fplugin=$(objtree)/scripts/gcc-plugins/sancov_plugin.so - - gcc-plugin-$(CONFIG_GCC_PLUGIN_CYC_COMPLEXITY) += cyc_complexity_plugin.so +gcc-plugin-$(CONFIG_GCC_PLUGIN_CYC_COMPLEXITY) += cyc_complexity_plugin.so - gcc-plugin-$(CONFIG_GCC_PLUGIN_LATENT_ENTROPY) += latent_entropy_plugin.so - gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_LATENT_ENTROPY) += -DLATENT_ENTROPY_PLUGIN - ifdef CONFIG_GCC_PLUGIN_LATENT_ENTROPY +gcc-plugin-$(CONFIG_GCC_PLUGIN_LATENT_ENTROPY) += latent_entropy_plugin.so +gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_LATENT_ENTROPY) += -DLATENT_ENTROPY_PLUGIN +ifdef CONFIG_GCC_PLUGIN_LATENT_ENTROPY DISABLE_LATENT_ENTROPY_PLUGIN += -fplugin-arg-latent_entropy_plugin-disable - endif - - ifdef CONFIG_GCC_PLUGIN_SANCOV - # It is needed because of the gcc-plugin.sh and gcc version checks. - gcc-plugin-$(CONFIG_GCC_PLUGIN_SANCOV) += sancov_plugin.so - - ifeq ($(PLUGINCC),) - $(warning warning: cannot use CONFIG_KCOV: -fsanitize-coverage=trace-pc is not supported by compiler) - endif - endif - - gcc-plugin-$(CONFIG_GCC_PLUGIN_STRUCTLEAK) += structleak_plugin.so - gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK_VERBOSE) += -fplugin-arg-structleak_plugin-verbose - gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL) += -fplugin-arg-structleak_plugin-byref-all - gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK) += -DSTRUCTLEAK_PLUGIN +endif - gcc-plugin-$(CONFIG_GCC_PLUGIN_RANDSTRUCT) += randomize_layout_plugin.so - gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_RANDSTRUCT) += -DRANDSTRUCT_PLUGIN - gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_RANDSTRUCT_PERFORMANCE) += -fplugin-arg-randomize_layout_plugin-performance-mode +gcc-plugin-$(CONFIG_GCC_PLUGIN_SANCOV) += sancov_plugin.so +gcc-plugin-$(CONFIG_GCC_PLUGIN_STRUCTLEAK) += structleak_plugin.so +gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK_VERBOSE) += -fplugin-arg-structleak_plugin-verbose +gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL) += -fplugin-arg-structleak_plugin-byref-all +gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK) += -DSTRUCTLEAK_PLUGIN - GCC_PLUGINS_CFLAGS := $(strip $(addprefix -fplugin=$(objtree)/scripts/gcc-plugins/, $(gcc-plugin-y)) $(gcc-plugin-cflags-y)) +gcc-plugin-$(CONFIG_GCC_PLUGIN_RANDSTRUCT) += randomize_layout_plugin.so +gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_RANDSTRUCT) += -DRANDSTRUCT_PLUGIN +gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_RANDSTRUCT_PERFORMANCE) += -fplugin-arg-randomize_layout_plugin-performance-mode - export PLUGINCC GCC_PLUGINS_CFLAGS GCC_PLUGIN GCC_PLUGIN_SUBDIR - export DISABLE_LATENT_ENTROPY_PLUGIN +GCC_PLUGINS_CFLAGS := $(strip $(addprefix -fplugin=$(objtree)/scripts/gcc-plugins/, $(gcc-plugin-y)) $(gcc-plugin-cflags-y)) - ifneq ($(PLUGINCC),) - # SANCOV_PLUGIN can be only in CFLAGS_KCOV because avoid duplication. - GCC_PLUGINS_CFLAGS := $(filter-out $(SANCOV_PLUGIN), $(GCC_PLUGINS_CFLAGS)) - endif +export GCC_PLUGINS_CFLAGS GCC_PLUGIN GCC_PLUGIN_SUBDIR +export DISABLE_LATENT_ENTROPY_PLUGIN - KBUILD_CFLAGS += $(GCC_PLUGINS_CFLAGS) - GCC_PLUGIN := $(gcc-plugin-y) - GCC_PLUGIN_SUBDIR := $(gcc-plugin-subdir-y) -endif +# sancov_plugin.so can be only in CFLAGS_KCOV because avoid duplication. +GCC_PLUGINS_CFLAGS := $(filter-out %/sancov_plugin.so, $(GCC_PLUGINS_CFLAGS)) -# If plugins aren't supported, abort the build before hard-to-read compiler -# errors start getting spewed by the main build. -PHONY += gcc-plugins-check -gcc-plugins-check: FORCE -ifdef CONFIG_GCC_PLUGINS - ifeq ($(PLUGINCC),) - ifneq ($(GCC_PLUGINS_CFLAGS),) - ifeq ($(call cc-ifversion, -ge, 0405, y), y) - $(Q)$(srctree)/scripts/gcc-plugin.sh --show-error "$(__PLUGINCC)" "$(HOSTCXX)" "$(CC)" || true - @echo "Cannot use CONFIG_GCC_PLUGINS: your gcc installation does not support plugins, perhaps the necessary headers are missing?" >&2 && exit 1 - else - @echo "Cannot use CONFIG_GCC_PLUGINS: your gcc version does not support plugins, you should upgrade it to at least gcc 4.5" >&2 && exit 1 - endif - endif - endif -endif - @: +KBUILD_CFLAGS += $(GCC_PLUGINS_CFLAGS) +GCC_PLUGIN := $(gcc-plugin-y) +GCC_PLUGIN_SUBDIR := $(gcc-plugin-subdir-y) # Actually do the build, if requested. PHONY += gcc-plugins -gcc-plugins: scripts_basic gcc-plugins-check +gcc-plugins: scripts_basic ifdef CONFIG_GCC_PLUGINS $(Q)$(MAKE) $(build)=scripts/gcc-plugins endif diff --git a/scripts/gcc-plugins/Makefile b/scripts/gcc-plugins/Makefile index ea465799ced5..326254653bd0 100644 --- a/scripts/gcc-plugins/Makefile +++ b/scripts/gcc-plugins/Makefile @@ -1,4 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 +PLUGINCC := $(CONFIG_PLUGIN_HOSTCC:"%"=%) GCC_PLUGINS_DIR := $(shell $(CC) -print-file-name=plugin) ifeq ($(PLUGINCC),$(HOSTCC)) -- cgit v1.2.3-59-g8ed1b From 1658dcee3d43edde9c971b6e88fee64ab9fc67e0 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 28 May 2018 18:22:07 +0900 Subject: gcc-plugins: allow to enable GCC_PLUGINS for COMPILE_TEST Now that the compiler's plugin support is checked in Kconfig, all{yes,mod}config will not be bothered. Remove 'depends on !COMPILE_TEST' for GCC_PLUGINS. 'depends on !COMPILE_TEST' for the following three are still kept: GCC_PLUGIN_CYC_COMPLEXITY GCC_PLUGIN_STRUCTLEAK_VERBOSE GCC_PLUGIN_RANDSTRUCT_PERFORMANCE Kees suggested to do so because the first two are too noisy, and the last one would reduce the compile test coverage. I commented the reasons in arch/Kconfig. Signed-off-by: Masahiro Yamada Acked-by: Kees Cook --- arch/Kconfig | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'arch/Kconfig') diff --git a/arch/Kconfig b/arch/Kconfig index e4a47d640a87..c2695293ca5b 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -417,7 +417,6 @@ menuconfig GCC_PLUGINS bool "GCC plugins" depends on HAVE_GCC_PLUGINS depends on PLUGIN_HOSTCC != "" - depends on !COMPILE_TEST help GCC plugins are loadable modules that provide extra features to the compiler. They are useful for runtime instrumentation and static analysis. @@ -427,7 +426,7 @@ menuconfig GCC_PLUGINS config GCC_PLUGIN_CYC_COMPLEXITY bool "Compute the cyclomatic complexity of a function" if EXPERT depends on GCC_PLUGINS - depends on !COMPILE_TEST + depends on !COMPILE_TEST # too noisy help The complexity M of a function's control flow graph is defined as: M = E - N + 2P @@ -494,7 +493,7 @@ config GCC_PLUGIN_STRUCTLEAK_BYREF_ALL config GCC_PLUGIN_STRUCTLEAK_VERBOSE bool "Report forcefully initialized variables" depends on GCC_PLUGIN_STRUCTLEAK - depends on !COMPILE_TEST + depends on !COMPILE_TEST # too noisy help This option will cause a warning to be printed each time the structleak plugin finds a variable it thinks needs to be @@ -534,7 +533,7 @@ config GCC_PLUGIN_RANDSTRUCT config GCC_PLUGIN_RANDSTRUCT_PERFORMANCE bool "Use cacheline-aware structure randomization" depends on GCC_PLUGIN_RANDSTRUCT - depends on !COMPILE_TEST + depends on !COMPILE_TEST # do not reduce test coverage help If you say Y here, the RANDSTRUCT randomization will make a best effort at restricting randomization to cacheline-sized -- cgit v1.2.3-59-g8ed1b From caa91ba53eb1c92d00abdf5b6c67a310d2b4c2d9 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 1 Jun 2018 13:32:00 +0900 Subject: gcc-plugins: disable GCC_PLUGIN_STRUCTLEAK_BYREF_ALL for COMPILE_TEST MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have enabled GCC_PLUGINS for COMPILE_TEST, but allmodconfig now produces new warnings. CC [M] drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.o drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c: In function ‘wlc_phy_workarounds_nphy_rev7’: drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c:16563:1: warning: the frame size of 3128 bytes is larger than 2048 bytes [-Wframe-larger-than=] } ^ drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c: In function ‘wlc_phy_workarounds_nphy_rev3’: drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c:16905:1: warning: the frame size of 2800 bytes is larger than 2048 bytes [-Wframe-larger-than=] } ^ drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c: In function ‘wlc_phy_cal_txiqlo_nphy’: drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c:26033:1: warning: the frame size of 2488 bytes is larger than 2048 bytes [-Wframe-larger-than=] } ^ It looks like GCC_PLUGIN_STRUCTLEAK_BYREF_ALL is causing this. Add "depends on !COMPILE_TEST" to not dirturb the compile test. Reported-by: Stephen Rothwell Suggested-by: Kees Cook Signed-off-by: Masahiro Yamada --- arch/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/Kconfig') diff --git a/arch/Kconfig b/arch/Kconfig index c2695293ca5b..f62542e6dc55 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -486,6 +486,7 @@ config GCC_PLUGIN_STRUCTLEAK config GCC_PLUGIN_STRUCTLEAK_BYREF_ALL bool "Force initialize all struct type variables passed by reference" depends on GCC_PLUGIN_STRUCTLEAK + depends on !COMPILE_TEST help Zero initialize any struct type local variable that may be passed by reference without having been initialized. -- cgit v1.2.3-59-g8ed1b