kcov: test compiler capability in Kconfig and correct dependency

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>
This commit is contained in:
Masahiro Yamada 2018-05-28 18:22:04 +09:00
parent 6a61b70b43
commit 5aadfdeb8d
5 changed files with 16 additions and 19 deletions

View File

@ -601,7 +601,7 @@ all: vmlinux
CFLAGS_GCOV := -fprofile-arcs -ftest-coverage \ CFLAGS_GCOV := -fprofile-arcs -ftest-coverage \
$(call cc-option,-fno-tree-loop-im) \ $(call cc-option,-fno-tree-loop-im) \
$(call cc-disable-warning,maybe-uninitialized,) $(call cc-disable-warning,maybe-uninitialized,)
export CFLAGS_GCOV CFLAGS_KCOV export CFLAGS_GCOV
# The arch Makefile can set ARCH_{CPP,A,C}FLAGS to override the default # The arch Makefile can set ARCH_{CPP,A,C}FLAGS to override the default
# values of the respective KBUILD_* variables # values of the respective KBUILD_* variables

View File

@ -736,12 +736,15 @@ 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.
config CC_HAS_SANCOV_TRACE_PC
def_bool $(cc-option,-fsanitize-coverage=trace-pc)
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).
@ -755,7 +758,7 @@ config 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 depends on $(cc-option,-fsanitize-coverage=trace-cmp)
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.
@ -765,7 +768,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,9 @@
ifdef CONFIG_KCOV ifdef CONFIG_KCOV
CFLAGS_KCOV := $(call cc-option,-fsanitize-coverage=trace-pc,)
ifeq ($(CONFIG_KCOV_ENABLE_COMPARISONS),y) kcov-flags-$(CONFIG_CC_HAS_SANCOV_TRACE_PC) += -fsanitize-coverage=trace-pc
CFLAGS_KCOV += $(call cc-option,-fsanitize-coverage=trace-cmp,) kcov-flags-$(CONFIG_KCOV_ENABLE_COMPARISONS) += -fsanitize-coverage=trace-cmp
endif 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