BACKPORT: kcov: test compiler capability in Kconfig and correct dependency

Work around missing cc-option support in Kconfig by checking required
compiler flags in Makefile.

(Upstream commit 5aadfdeb8de001ca04d500586e3b033404c28617.)

As Documentation/kbuild/kconfig-language.txt notes, 'select' should be
be used with care - it forces a lower limit of another symbol, ignoring
the dependency.  Currently, KCOV can select GCC_PLUGINS even if arch
does not select HAVE_GCC_PLUGINS.  This could cause the unmet direct
dependency.

Now that Kconfig can test compiler capability, let's handle this in a
more sophisticated way.

There are two ways to enable KCOV; use the compiler that natively
supports -fsanitize-coverage=trace-pc, or build the SANCOV plugin if
the compiler has ability to build GCC plugins.  Hence, the correct
dependency for KCOV is:

  depends on CC_HAS_SANCOV_TRACE_PC || GCC_PLUGINS

You do not need to build the SANCOV plugin if the compiler already
supports -fsanitize-coverage=trace-pc.  Hence, the select should be:

  select GCC_PLUGIN_SANCOV if !CC_HAS_SANCOV_TRACE_PC

With this, GCC_PLUGIN_SANCOV is selected only when necessary, so
scripts/Makefile.gcc-plugins can be cleaner.

I also cleaned up Kconfig and scripts/Makefile.kcov as well.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Change-Id: Iad9110eb7b6ecef6dfcec38cf483699c1b85af01
Signed-off-by: Andrey Konovalov <andreyknvl@google.com>
Bug: 147413187
This commit is contained in:
Masahiro Yamada 2018-05-28 18:22:04 +09:00 committed by Alistair Delva
parent 0f0fe8e7a5
commit c093b585da
4 changed files with 33 additions and 17 deletions

View File

@ -740,12 +740,17 @@ config ARCH_HAS_KCOV
only for x86_64. KCOV requires testing on other archs, and most likely only for x86_64. KCOV requires testing on other archs, and most likely
disabling of instrumentation for some early boot code. disabling of instrumentation for some early boot code.
# Upstream uses $(cc-option, -fsanitize-coverage=trace-pc), which requires
# cc-option support. Here we instead check CC in scripts/Makefile.kcov.
config CC_HAS_SANCOV_TRACE_PC
def_bool ARCH_HAS_KCOV
config KCOV config KCOV
bool "Code coverage for fuzzing" bool "Code coverage for fuzzing"
depends on ARCH_HAS_KCOV depends on ARCH_HAS_KCOV
depends on CC_HAS_SANCOV_TRACE_PC || GCC_PLUGINS
select DEBUG_FS select DEBUG_FS
select GCC_PLUGINS if !COMPILE_TEST select GCC_PLUGIN_SANCOV if !CC_HAS_SANCOV_TRACE_PC
select GCC_PLUGIN_SANCOV if !COMPILE_TEST
help help
KCOV exposes kernel code coverage information in a form suitable KCOV exposes kernel code coverage information in a form suitable
for coverage-guided fuzzing (randomized testing). for coverage-guided fuzzing (randomized testing).
@ -756,10 +761,11 @@ config KCOV
For more details, see Documentation/dev-tools/kcov.rst. For more details, see Documentation/dev-tools/kcov.rst.
# Upstream uses $(cc-option, -fsanitize-coverage=trace-cmp), which requires
# cc-option support. Here we instead check CC in scripts/Makefile.kcov.
config KCOV_ENABLE_COMPARISONS config KCOV_ENABLE_COMPARISONS
bool "Enable comparison operands collection by KCOV" bool "Enable comparison operands collection by KCOV"
depends on KCOV depends on KCOV
default n
help help
KCOV also exposes operands of every comparison in the instrumented KCOV also exposes operands of every comparison in the instrumented
code along with operand sizes and PCs of the comparison instructions. code along with operand sizes and PCs of the comparison instructions.
@ -769,7 +775,7 @@ config KCOV_ENABLE_COMPARISONS
config KCOV_INSTRUMENT_ALL config KCOV_INSTRUMENT_ALL
bool "Instrument all code by default" bool "Instrument all code by default"
depends on KCOV depends on KCOV
default y if KCOV default y
help help
If you are doing generic system call fuzzing (like e.g. syzkaller), If you are doing generic system call fuzzing (like e.g. syzkaller),
then you will want to instrument the whole kernel and you should then you will want to instrument the whole kernel and you should

View File

@ -14,16 +14,12 @@ ifdef CONFIG_GCC_PLUGINS
endif endif
ifdef CONFIG_GCC_PLUGIN_SANCOV ifdef CONFIG_GCC_PLUGIN_SANCOV
ifeq ($(strip $(CFLAGS_KCOV)),)
# It is needed because of the gcc-plugin.sh and gcc version checks. # It is needed because of the gcc-plugin.sh and gcc version checks.
gcc-plugin-$(CONFIG_GCC_PLUGIN_SANCOV) += sancov_plugin.so gcc-plugin-$(CONFIG_GCC_PLUGIN_SANCOV) += sancov_plugin.so
ifneq ($(PLUGINCC),) ifeq ($(PLUGINCC),)
CFLAGS_KCOV := $(SANCOV_PLUGIN)
else
$(warning warning: cannot use CONFIG_KCOV: -fsanitize-coverage=trace-pc is not supported by compiler) $(warning warning: cannot use CONFIG_KCOV: -fsanitize-coverage=trace-pc is not supported by compiler)
endif endif
endif
endif endif
gcc-plugin-$(CONFIG_GCC_PLUGIN_STRUCTLEAK) += structleak_plugin.so gcc-plugin-$(CONFIG_GCC_PLUGIN_STRUCTLEAK) += structleak_plugin.so
@ -38,7 +34,7 @@ ifdef CONFIG_GCC_PLUGINS
GCC_PLUGINS_CFLAGS := $(strip $(addprefix -fplugin=$(objtree)/scripts/gcc-plugins/, $(gcc-plugin-y)) $(gcc-plugin-cflags-y)) GCC_PLUGINS_CFLAGS := $(strip $(addprefix -fplugin=$(objtree)/scripts/gcc-plugins/, $(gcc-plugin-y)) $(gcc-plugin-cflags-y))
export PLUGINCC GCC_PLUGINS_CFLAGS GCC_PLUGIN GCC_PLUGIN_SUBDIR export PLUGINCC GCC_PLUGINS_CFLAGS GCC_PLUGIN GCC_PLUGIN_SUBDIR
export SANCOV_PLUGIN DISABLE_LATENT_ENTROPY_PLUGIN export DISABLE_LATENT_ENTROPY_PLUGIN
ifneq ($(PLUGINCC),) ifneq ($(PLUGINCC),)
# SANCOV_PLUGIN can be only in CFLAGS_KCOV because avoid duplication. # SANCOV_PLUGIN can be only in CFLAGS_KCOV because avoid duplication.

View File

@ -1,7 +1,25 @@
ifdef CONFIG_KCOV ifdef CONFIG_KCOV
CFLAGS_KCOV := $(call cc-option,-fsanitize-coverage=trace-pc,)
ifeq ($(CONFIG_KCOV_ENABLE_COMPARISONS),y) ifeq ($(call cc-option, -fsanitize-coverage=trace-pc -Werror),)
CFLAGS_KCOV += $(call cc-option,-fsanitize-coverage=trace-cmp,) ifneq ($(CONFIG_COMPILE_TEST),y)
$(error Cannot use CONFIG_KCOV: \
-fsanitize-coverage=trace-pc is not supported by compiler)
endif
endif endif
ifdef CONFIG_KCOV_ENABLE_COMPARISONS
ifeq ($(call cc-option, -fsanitize-coverage=trace-cmp -Werror),)
ifneq ($(CONFIG_COMPILE_TEST),y)
$(error Cannot use CONFIG_KCOV_ENABLE_COMPARISONS: \
-fsanitize-coverage=trace-cmp is not supported by compiler)
endif
endif
endif
kcov-flags-$(CONFIG_CC_HAS_SANCOV_TRACE_PC) += -fsanitize-coverage=trace-pc
kcov-flags-$(CONFIG_KCOV_ENABLE_COMPARISONS) += -fsanitize-coverage=trace-cmp
kcov-flags-$(CONFIG_GCC_PLUGIN_SANCOV) += -fplugin=$(objtree)/scripts/gcc-plugins/sancov_plugin.so
export CFLAGS_KCOV := $(kcov-flags-y)
endif endif

View File

@ -13,10 +13,6 @@ else
export HOST_EXTRACXXFLAGS export HOST_EXTRACXXFLAGS
endif endif
ifneq ($(CFLAGS_KCOV), $(SANCOV_PLUGIN))
GCC_PLUGIN := $(filter-out $(SANCOV_PLUGIN), $(GCC_PLUGIN))
endif
export HOSTLIBS export HOSTLIBS
$(obj)/randomize_layout_plugin.o: $(objtree)/$(obj)/randomize_layout_seed.h $(obj)/randomize_layout_plugin.o: $(objtree)/$(obj)/randomize_layout_seed.h