Commit f594e28d authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull compiler hardening updates from Kees Cook:
 "These are various compiler-related hardening feature updates. Notable
  is the addition of an explicit limited rationale for, and deprecation
  schedule of, gcc-plugins.

  gcc-plugins:
   - remove support for GCC 4.9 and older (Ard Biesheuvel)
   - remove duplicate include in gcc-common.h (Ye Guojin)
   - Explicitly document purpose and deprecation schedule (Kees Cook)
   - Remove cyc_complexity (Kees Cook)

  instrumentation:
   - Avoid harmless Clang option under CONFIG_INIT_STACK_ALL_ZERO (Kees Cook)

  Clang LTO:
   - kallsyms: strip LTO suffixes from static functions (Nick Desaulniers)"

* tag 'hardening-v5.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
  gcc-plugins: remove duplicate include in gcc-common.h
  gcc-plugins: Remove cyc_complexity
  gcc-plugins: Explicitly document purpose and deprecation schedule
  kallsyms: strip LTO suffixes from static functions
  gcc-plugins: remove support for GCC 4.9 and older
  hardening: Avoid harmless Clang option under CONFIG_INIT_STACK_ALL_ZERO
parents 01463374 6425392a
Loading
Loading
Loading
Loading
+26 −2
Original line number Diff line number Diff line
@@ -32,6 +32,32 @@ This infrastructure was ported from grsecurity [6]_ and PaX [7]_.
.. [7] https://pax.grsecurity.net/


Purpose
=======

GCC plugins are designed to provide a place to experiment with potential
compiler features that are neither in GCC nor Clang upstream. Once
their utility is proven, the goal is to upstream the feature into GCC
(and Clang), and then to finally remove them from the kernel once the
feature is available in all supported versions of GCC.

Specifically, new plugins should implement only features that have no
upstream compiler support (in either GCC or Clang).

When a feature exists in Clang but not GCC, effort should be made to
bring the feature to upstream GCC (rather than just as a kernel-specific
GCC plugin), so the entire ecosystem can benefit from it.

Similarly, even if a feature provided by a GCC plugin does *not* exist
in Clang, but the feature is proven to be useful, effort should be spent
to upstream the feature to GCC (and Clang).

After a feature is available in upstream GCC, the plugin will be made
unbuildable for the corresponding GCC version (and later). Once all
kernel-supported versions of GCC provide the feature, the plugin will
be removed from the kernel.


Files
=====

@@ -70,7 +96,6 @@ Enable the GCC plugin infrastructure and some plugin(s) you want to use
in the kernel config::

	CONFIG_GCC_PLUGINS=y
	CONFIG_GCC_PLUGIN_CYC_COMPLEXITY=y
	CONFIG_GCC_PLUGIN_LATENT_ENTROPY=y
	...

@@ -89,4 +114,3 @@ The GCC plugins are in scripts/gcc-plugins/. You need to put plugin source files
right under scripts/gcc-plugins/. Creating subdirectories is not supported.
It must be added to scripts/gcc-plugins/Makefile, scripts/Makefile.gcc-plugins
and a relevant Kconfig file.
See the cyc_complexity_plugin.c (CONFIG_GCC_PLUGIN_CYC_COMPLEXITY) GCC plugin.
+3 −3
Original line number Diff line number Diff line
@@ -831,12 +831,12 @@ endif

# Initialize all stack variables with a zero value.
ifdef CONFIG_INIT_STACK_ALL_ZERO
# Future support for zero initialization is still being debated, see
# https://bugs.llvm.org/show_bug.cgi?id=45497. These flags are subject to being
# renamed or dropped.
KBUILD_CFLAGS	+= -ftrivial-auto-var-init=zero
ifdef CONFIG_CC_IS_CLANG
# https://bugs.llvm.org/show_bug.cgi?id=45497
KBUILD_CFLAGS	+= -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang
endif
endif

# While VLAs have been removed, GCC produces unreachable stack probes
# for the randomize_kstack_offset feature. Disable it for all compilers.
+33 −13
Original line number Diff line number Diff line
@@ -164,26 +164,46 @@ static unsigned long kallsyms_sym_address(int idx)
	return kallsyms_relative_base - 1 - kallsyms_offsets[idx];
}

#if defined(CONFIG_CFI_CLANG) && defined(CONFIG_LTO_CLANG_THIN)
/*
 * LLVM appends a hash to static function names when ThinLTO and CFI are
 * both enabled, i.e. foo() becomes foo$707af9a22804d33c81801f27dcfe489b.
 * This causes confusion and potentially breaks user space tools, so we
 * strip the suffix from expanded symbol names.
 */
static inline bool cleanup_symbol_name(char *s)
static bool cleanup_symbol_name(char *s)
{
	char *res;

	if (!IS_ENABLED(CONFIG_LTO_CLANG))
		return false;

	/*
	 * LLVM appends various suffixes for local functions and variables that
	 * must be promoted to global scope as part of LTO.  This can break
	 * hooking of static functions with kprobes. '.' is not a valid
	 * character in an identifier in C. Suffixes observed:
	 * - foo.llvm.[0-9a-f]+
	 * - foo.[0-9a-f]+
	 * - foo.[0-9a-f]+.cfi_jt
	 */
	res = strchr(s, '.');
	if (res) {
		*res = '\0';
		return true;
	}

	if (!IS_ENABLED(CONFIG_CFI_CLANG) ||
	    !IS_ENABLED(CONFIG_LTO_CLANG_THIN) ||
	    CONFIG_CLANG_VERSION >= 130000)
		return false;

	/*
	 * Prior to LLVM 13, the following suffixes were observed when thinLTO
	 * and CFI are both enabled:
	 * - foo$[0-9]+
	 */
	res = strrchr(s, '$');
	if (res)
	if (res) {
		*res = '\0';
		return true;
	}

	return res != NULL;
	return false;
}
#else
static inline bool cleanup_symbol_name(char *s) { return false; }
#endif

/* Lookup the address for this symbol. Returns 0 if not found. */
unsigned long kallsyms_lookup_name(const char *name)
+0 −2
Original line number Diff line number Diff line
# 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
+2 −18
Original line number Diff line number Diff line
@@ -19,24 +19,10 @@ menuconfig GCC_PLUGINS

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
	# Plugin can be removed once the kernel only supports GCC 6+
	depends on !CC_HAS_SANCOV_TRACE_PC
	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
@@ -83,8 +69,6 @@ config GCC_PLUGIN_RANDSTRUCT
	  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/
Loading