diff --git a/arch/Kconfig b/arch/Kconfig index d1f2ed462ac84db369d463b8bc65cee59e334d98..8543bc3c21fe9ee3b3a1af0572fbea38fa20e20e 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -408,150 +408,6 @@ config SECCOMP_FILTER See Documentation/userspace-api/seccomp_filter.rst 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 - An arch should select this symbol if it supports building with - GCC plugins. - -menuconfig GCC_PLUGINS - bool "GCC plugins" - depends on HAVE_GCC_PLUGINS - depends on PLUGIN_HOSTCC != "" - help - GCC plugins are loadable modules that provide extra features to the - compiler. They are useful for runtime instrumentation and static analysis. - - See Documentation/gcc-plugins.txt for details. - -config GCC_PLUGIN_CYC_COMPLEXITY - bool "Compute the cyclomatic complexity of a function" if EXPERT - depends on GCC_PLUGINS - depends on !COMPILE_TEST # too noisy - help - The complexity M of a function's control flow graph is defined as: - M = E - N + 2P - where - - E = the number of edges - N = the number of nodes - P = the number of connected components (exit nodes). - - Enabling this plugin reports the complexity to stderr during the - build. It mainly serves as a simple example of how to create a - gcc plugin for the kernel. - -config GCC_PLUGIN_SANCOV - bool - depends on GCC_PLUGINS - help - This plugin inserts a __sanitizer_cov_trace_pc() call at the start of - basic blocks. It supports all gcc versions with plugin support (from - gcc-4.5 on). It is based on the commit "Add fuzzing coverage support" - by Dmitry Vyukov . - -config GCC_PLUGIN_LATENT_ENTROPY - bool "Generate some entropy during boot and runtime" - depends on GCC_PLUGINS - help - By saying Y here the kernel will instrument some kernel code to - extract some entropy from both original and artificially created - program state. This will help especially embedded systems where - there is little 'natural' source of entropy normally. The cost - is some slowdown of the boot process (about 0.5%) and fork and - irq processing. - - Note that entropy extracted this way is not cryptographically - secure! - - This plugin was ported from grsecurity/PaX. More information at: - * https://grsecurity.net/ - * https://pax.grsecurity.net/ - -config GCC_PLUGIN_STRUCTLEAK - bool "Force initialization of variables containing userspace addresses" - depends on GCC_PLUGINS - # Currently STRUCTLEAK inserts initialization out of live scope of - # variables from KASAN point of view. This leads to KASAN false - # positive reports. Prohibit this combination for now. - depends on !KASAN_EXTRA - help - This plugin zero-initializes any structures containing a - __user attribute. This can prevent some classes of information - exposures. - - This plugin was ported from grsecurity/PaX. More information at: - * https://grsecurity.net/ - * https://pax.grsecurity.net/ - -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. - -config GCC_PLUGIN_STRUCTLEAK_VERBOSE - bool "Report forcefully initialized variables" - depends on GCC_PLUGIN_STRUCTLEAK - 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 - initialized. Since not all existing initializers are detected - by the plugin, this can produce false positive warnings. - -config GCC_PLUGIN_RANDSTRUCT - bool "Randomize layout of sensitive kernel structures" - depends on GCC_PLUGINS - select MODVERSIONS if MODULES - help - If you say Y here, the layouts of structures that are entirely - function pointers (and have not been manually annotated with - __no_randomize_layout), or structures that have been explicitly - marked with __randomize_layout, will be randomized at compile-time. - This can introduce the requirement of an additional information - exposure vulnerability for exploits targeting these structure - types. - - Enabling this feature will introduce some performance impact, - slightly increase memory usage, and prevent the use of forensic - tools like Volatility against the system (unless the kernel - source tree isn't cleaned after kernel installation). - - The seed used for compilation is located at - scripts/gcc-plgins/randomize_layout_seed.h. It remains after - a make clean to allow for external modules to be compiled with - the existing seed and will be removed by a make mrproper or - make distclean. - - Note that the implementation requires gcc 4.7 or newer. - - This plugin was ported from grsecurity/PaX. More information at: - * https://grsecurity.net/ - * https://pax.grsecurity.net/ - -config GCC_PLUGIN_RANDSTRUCT_PERFORMANCE - bool "Use cacheline-aware structure randomization" - depends on GCC_PLUGIN_RANDSTRUCT - 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 - groups of elements. It will further not randomize bitfields - in structures. This reduces the performance hit of RANDSTRUCT - at the cost of weakened randomization. - config HAVE_STACKPROTECTOR bool help @@ -975,3 +831,5 @@ config REFCOUNT_FULL security flaw exploits. source "kernel/gcov/Kconfig" + +source "scripts/gcc-plugins/Kconfig" diff --git a/scripts/Makefile.gcc-plugins b/scripts/Makefile.gcc-plugins index c961b9a65d11ac7954b2a5a3b0826f6a5697063a..0a482f341576766793cb7ac85601e92e5c0e8c8d 100644 --- a/scripts/Makefile.gcc-plugins +++ b/scripts/Makefile.gcc-plugins @@ -1,33 +1,44 @@ # SPDX-License-Identifier: GPL-2.0 + 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 +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 + DISABLE_LATENT_ENTROPY_PLUGIN += -fplugin-arg-latent_entropy_plugin-disable endif +export DISABLE_LATENT_ENTROPY_PLUGIN 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-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-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-cflags-$(CONFIG_GCC_PLUGIN_RANDSTRUCT) \ + += -DRANDSTRUCT_PLUGIN +gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_RANDSTRUCT_PERFORMANCE) \ + += -fplugin-arg-randomize_layout_plugin-performance-mode +# All the plugin CFLAGS are collected here in case a build target needs to +# filter them out of the KBUILD_CFLAGS. GCC_PLUGINS_CFLAGS := $(strip $(addprefix -fplugin=$(objtree)/scripts/gcc-plugins/, $(gcc-plugin-y)) $(gcc-plugin-cflags-y)) - -export GCC_PLUGINS_CFLAGS GCC_PLUGIN GCC_PLUGIN_SUBDIR -export DISABLE_LATENT_ENTROPY_PLUGIN - -# sancov_plugin.so can be only in CFLAGS_KCOV because avoid duplication. +# The sancov_plugin.so is included via CFLAGS_KCOV, so it is removed here. GCC_PLUGINS_CFLAGS := $(filter-out %/sancov_plugin.so, $(GCC_PLUGINS_CFLAGS)) +export GCC_PLUGINS_CFLAGS +# Add the flags to the build! KBUILD_CFLAGS += $(GCC_PLUGINS_CFLAGS) + +# All enabled GCC plugins are collected here for building below. GCC_PLUGIN := $(gcc-plugin-y) -GCC_PLUGIN_SUBDIR := $(gcc-plugin-subdir-y) +export GCC_PLUGIN # Actually do the build, if requested. PHONY += gcc-plugins diff --git a/scripts/gcc-plugins/Kconfig b/scripts/gcc-plugins/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..7430a7c77a4a1ddb586519d5d38f215cd300c675 --- /dev/null +++ b/scripts/gcc-plugins/Kconfig @@ -0,0 +1,142 @@ +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 + An arch should select this symbol if it supports building with + GCC plugins. + +menuconfig GCC_PLUGINS + bool "GCC plugins" + depends on HAVE_GCC_PLUGINS + depends on PLUGIN_HOSTCC != "" + help + GCC plugins are loadable modules that provide extra features to the + compiler. They are useful for runtime instrumentation and static analysis. + + See Documentation/gcc-plugins.txt for details. + +if GCC_PLUGINS + +config GCC_PLUGIN_CYC_COMPLEXITY + bool "Compute the cyclomatic complexity of a function" if EXPERT + depends on !COMPILE_TEST # too noisy + help + The complexity M of a function's control flow graph is defined as: + M = E - N + 2P + where + + E = the number of edges + N = the number of nodes + P = the number of connected components (exit nodes). + + Enabling this plugin reports the complexity to stderr during the + build. It mainly serves as a simple example of how to create a + gcc plugin for the kernel. + +config GCC_PLUGIN_SANCOV + bool + help + This plugin inserts a __sanitizer_cov_trace_pc() call at the start of + basic blocks. It supports all gcc versions with plugin support (from + gcc-4.5 on). It is based on the commit "Add fuzzing coverage support" + by Dmitry Vyukov . + +config GCC_PLUGIN_LATENT_ENTROPY + bool "Generate some entropy during boot and runtime" + help + By saying Y here the kernel will instrument some kernel code to + extract some entropy from both original and artificially created + program state. This will help especially embedded systems where + there is little 'natural' source of entropy normally. The cost + is some slowdown of the boot process (about 0.5%) and fork and + irq processing. + + Note that entropy extracted this way is not cryptographically + secure! + + This plugin was ported from grsecurity/PaX. More information at: + * https://grsecurity.net/ + * https://pax.grsecurity.net/ + +config GCC_PLUGIN_STRUCTLEAK + bool "Force initialization of variables containing userspace addresses" + # Currently STRUCTLEAK inserts initialization out of live scope of + # variables from KASAN point of view. This leads to KASAN false + # positive reports. Prohibit this combination for now. + depends on !KASAN_EXTRA + help + This plugin zero-initializes any structures containing a + __user attribute. This can prevent some classes of information + exposures. + + This plugin was ported from grsecurity/PaX. More information at: + * https://grsecurity.net/ + * https://pax.grsecurity.net/ + +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. + +config GCC_PLUGIN_STRUCTLEAK_VERBOSE + bool "Report forcefully initialized variables" + depends on GCC_PLUGIN_STRUCTLEAK + 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 + initialized. Since not all existing initializers are detected + by the plugin, this can produce false positive warnings. + +config GCC_PLUGIN_RANDSTRUCT + bool "Randomize layout of sensitive kernel structures" + select MODVERSIONS if MODULES + help + If you say Y here, the layouts of structures that are entirely + function pointers (and have not been manually annotated with + __no_randomize_layout), or structures that have been explicitly + marked with __randomize_layout, will be randomized at compile-time. + This can introduce the requirement of an additional information + exposure vulnerability for exploits targeting these structure + types. + + Enabling this feature will introduce some performance impact, + slightly increase memory usage, and prevent the use of forensic + tools like Volatility against the system (unless the kernel + source tree isn't cleaned after kernel installation). + + The seed used for compilation is located at + scripts/gcc-plgins/randomize_layout_seed.h. It remains after + a make clean to allow for external modules to be compiled with + the existing seed and will be removed by a make mrproper or + make distclean. + + Note that the implementation requires gcc 4.7 or newer. + + This plugin was ported from grsecurity/PaX. More information at: + * https://grsecurity.net/ + * https://pax.grsecurity.net/ + +config GCC_PLUGIN_RANDSTRUCT_PERFORMANCE + bool "Use cacheline-aware structure randomization" + depends on GCC_PLUGIN_RANDSTRUCT + 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 + groups of elements. It will further not randomize bitfields + in structures. This reduces the performance hit of RANDSTRUCT + at the cost of weakened randomization. + +endif diff --git a/scripts/gcc-plugins/Makefile b/scripts/gcc-plugins/Makefile index 326254653bd0464f28e8c966289d5ad030377f3b..aa0d0ec6936d7cb10da0ddd6064bdd57dace2345 100644 --- a/scripts/gcc-plugins/Makefile +++ b/scripts/gcc-plugins/Makefile @@ -14,8 +14,6 @@ else export HOST_EXTRACXXFLAGS endif -export HOSTLIBS - $(obj)/randomize_layout_plugin.o: $(objtree)/$(obj)/randomize_layout_seed.h quiet_cmd_create_randomize_layout_seed = GENSEED $@ cmd_create_randomize_layout_seed = \ @@ -29,7 +27,4 @@ always := $($(HOSTLIBS)-y) $(foreach p,$($(HOSTLIBS)-y:%.so=%),$(eval $(p)-objs := $(p).o)) -subdir-y := $(GCC_PLUGIN_SUBDIR) -subdir- += $(GCC_PLUGIN_SUBDIR) - clean-files += *.so diff --git a/scripts/gcc-plugins/gcc-common.h b/scripts/gcc-plugins/gcc-common.h index f467500533776c7394e83f4ae4fa47fb76521394..552d5efd7cb7524b221272cb1c14f6da222b324c 100644 --- a/scripts/gcc-plugins/gcc-common.h +++ b/scripts/gcc-plugins/gcc-common.h @@ -392,13 +392,6 @@ static inline struct cgraph_node *cgraph_alias_target(struct cgraph_node *n) } #endif -#if BUILDING_GCC_VERSION >= 4007 && BUILDING_GCC_VERSION <= 4009 -#define cgraph_create_edge(caller, callee, call_stmt, count, freq, nest) \ - cgraph_create_edge((caller), (callee), (call_stmt), (count), (freq)) -#define cgraph_create_edge_including_clones(caller, callee, old_call_stmt, call_stmt, count, freq, nest, reason) \ - cgraph_create_edge_including_clones((caller), (callee), (old_call_stmt), (call_stmt), (count), (freq), (reason)) -#endif - #if BUILDING_GCC_VERSION <= 4008 #define ENTRY_BLOCK_PTR_FOR_FN(FN) ENTRY_BLOCK_PTR_FOR_FUNCTION(FN) #define EXIT_BLOCK_PTR_FOR_FN(FN) EXIT_BLOCK_PTR_FOR_FUNCTION(FN) @@ -723,10 +716,23 @@ static inline const char *get_decl_section_name(const_tree decl) #define varpool_get_node(decl) varpool_node::get(decl) #define dump_varpool_node(file, node) (node)->dump(file) -#define cgraph_create_edge(caller, callee, call_stmt, count, freq, nest) \ +#if BUILDING_GCC_VERSION >= 8000 +#define cgraph_create_edge(caller, callee, call_stmt, count, freq) \ + (caller)->create_edge((callee), (call_stmt), (count)) + +#define cgraph_create_edge_including_clones(caller, callee, \ + old_call_stmt, call_stmt, count, freq, reason) \ + (caller)->create_edge_including_clones((callee), \ + (old_call_stmt), (call_stmt), (count), (reason)) +#else +#define cgraph_create_edge(caller, callee, call_stmt, count, freq) \ (caller)->create_edge((callee), (call_stmt), (count), (freq)) -#define cgraph_create_edge_including_clones(caller, callee, old_call_stmt, call_stmt, count, freq, nest, reason) \ - (caller)->create_edge_including_clones((callee), (old_call_stmt), (call_stmt), (count), (freq), (reason)) + +#define cgraph_create_edge_including_clones(caller, callee, \ + old_call_stmt, call_stmt, count, freq, reason) \ + (caller)->create_edge_including_clones((callee), \ + (old_call_stmt), (call_stmt), (count), (freq), (reason)) +#endif typedef struct cgraph_node *cgraph_node_ptr; typedef struct cgraph_edge *cgraph_edge_p;