diff options
Diffstat (limited to 'scripts/gcc-plugins')
| -rw-r--r-- | scripts/gcc-plugins/Kconfig | 38 | ||||
| -rw-r--r-- | scripts/gcc-plugins/Makefile | 24 | ||||
| -rwxr-xr-x | scripts/gcc-plugins/gen-random-seed.sh | 9 | ||||
| -rw-r--r-- | scripts/gcc-plugins/latent_entropy_plugin.c | 46 | ||||
| -rw-r--r-- | scripts/gcc-plugins/randomize_layout_plugin.c | 89 | ||||
| -rw-r--r-- | scripts/gcc-plugins/sancov_plugin.c | 2 | ||||
| -rw-r--r-- | scripts/gcc-plugins/stackleak_plugin.c | 2 | ||||
| -rw-r--r-- | scripts/gcc-plugins/structleak_plugin.c | 2 | 
8 files changed, 50 insertions, 162 deletions
diff --git a/scripts/gcc-plugins/Kconfig b/scripts/gcc-plugins/Kconfig index 51d81c3f03d6..e383cda05367 100644 --- a/scripts/gcc-plugins/Kconfig +++ b/scripts/gcc-plugins/Kconfig @@ -46,44 +46,6 @@ config GCC_PLUGIN_LATENT_ENTROPY  	   * https://grsecurity.net/  	   * https://pax.grsecurity.net/ -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-plugins/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. - -	  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 GCC_PLUGIN_ARM_SSP_PER_TASK  	bool  	depends on GCC_PLUGINS && ARM diff --git a/scripts/gcc-plugins/Makefile b/scripts/gcc-plugins/Makefile index 1952d3bb80c6..b34d11e22636 100644 --- a/scripts/gcc-plugins/Makefile +++ b/scripts/gcc-plugins/Makefile @@ -1,12 +1,17 @@  # SPDX-License-Identifier: GPL-2.0 -$(obj)/randomize_layout_plugin.so: $(objtree)/$(obj)/randomize_layout_seed.h -quiet_cmd_create_randomize_layout_seed = GENSEED $@ +$(obj)/randomize_layout_plugin.so: $(obj)/randomize_layout_seed.h +quiet_cmd_create_randomize_layout_seed = SEEDHDR $@  cmd_create_randomize_layout_seed = \ -  $(CONFIG_SHELL) $(srctree)/$(src)/gen-random-seed.sh $@ $(objtree)/include/generated/randomize_layout_hash.h -$(objtree)/$(obj)/randomize_layout_seed.h: FORCE +	SEED=$$(cat $(filter-out FORCE,$^) </dev/null); \ +	echo '/*' > $@; \ +	echo ' * This file is automatically generated. Keep it private.' >> $@; \ +	echo ' * Exposing this value will expose the layout of randomized structures.' >> $@; \ +	echo ' */' >> $@; \ +	echo "const char *randstruct_seed = \"$$SEED\";" >> $@ +$(obj)/randomize_layout_seed.h: $(objtree)/scripts/basic/randstruct.seed FORCE  	$(call if_changed,create_randomize_layout_seed) -targets += randomize_layout_seed.h randomize_layout_hash.h +targets += randomize_layout_seed.h  # Build rules for plugins  # @@ -23,10 +28,11 @@ GCC_PLUGINS_DIR = $(shell $(CC) -print-file-name=plugin)  plugin_cxxflags	= -Wp,-MMD,$(depfile) $(KBUILD_HOSTCXXFLAGS) -fPIC \  		  -include $(srctree)/include/linux/compiler-version.h \ -		   -I $(GCC_PLUGINS_DIR)/include -I $(obj) -std=gnu++11 \ -		   -fno-rtti -fno-exceptions -fasynchronous-unwind-tables \ -		   -ggdb -Wno-narrowing -Wno-unused-variable \ -		   -Wno-format-diag +		  -DPLUGIN_VERSION=$(call stringify,$(KERNELVERSION)) \ +		  -I $(GCC_PLUGINS_DIR)/include -I $(obj) -std=gnu++11 \ +		  -fno-rtti -fno-exceptions -fasynchronous-unwind-tables \ +		  -ggdb -Wno-narrowing -Wno-unused-variable \ +		  -Wno-format-diag  plugin_ldflags	= -shared diff --git a/scripts/gcc-plugins/gen-random-seed.sh b/scripts/gcc-plugins/gen-random-seed.sh deleted file mode 100755 index 68af5cc20a64..000000000000 --- a/scripts/gcc-plugins/gen-random-seed.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh -# SPDX-License-Identifier: GPL-2.0 - -if [ ! -f "$1" ]; then -	SEED=`od -A n -t x8 -N 32 /dev/urandom | tr -d ' \n'` -	echo "const char *randstruct_seed = \"$SEED\";" > "$1" -	HASH=`echo -n "$SEED" | sha256sum | cut -d" " -f1 | tr -d ' \n'` -	echo "#define RANDSTRUCT_HASHED_SEED \"$HASH\"" > "$2" -fi diff --git a/scripts/gcc-plugins/latent_entropy_plugin.c b/scripts/gcc-plugins/latent_entropy_plugin.c index 589454bce930..848918764174 100644 --- a/scripts/gcc-plugins/latent_entropy_plugin.c +++ b/scripts/gcc-plugins/latent_entropy_plugin.c @@ -82,29 +82,35 @@ __visible int plugin_is_GPL_compatible;  static GTY(()) tree latent_entropy_decl;  static struct plugin_info latent_entropy_plugin_info = { -	.version	= "201606141920vanilla", +	.version	= PLUGIN_VERSION,  	.help		= "disable\tturn off latent entropy instrumentation\n",  }; -static unsigned HOST_WIDE_INT seed; -/* - * get_random_seed() (this is a GCC function) generates the seed. - * This is a simple random generator without any cryptographic security because - * the entropy doesn't come from here. - */ +static unsigned HOST_WIDE_INT deterministic_seed; +static unsigned HOST_WIDE_INT rnd_buf[32]; +static size_t rnd_idx = ARRAY_SIZE(rnd_buf); +static int urandom_fd = -1; +  static unsigned HOST_WIDE_INT get_random_const(void)  { -	unsigned int i; -	unsigned HOST_WIDE_INT ret = 0; - -	for (i = 0; i < 8 * sizeof(ret); i++) { -		ret = (ret << 1) | (seed & 1); -		seed >>= 1; -		if (ret & 1) -			seed ^= 0xD800000000000000ULL; +	if (deterministic_seed) { +		unsigned HOST_WIDE_INT w = deterministic_seed; +		w ^= w << 13; +		w ^= w >> 7; +		w ^= w << 17; +		deterministic_seed = w; +		return deterministic_seed;  	} -	return ret; +	if (urandom_fd < 0) { +		urandom_fd = open("/dev/urandom", O_RDONLY); +		gcc_assert(urandom_fd >= 0); +	} +	if (rnd_idx >= ARRAY_SIZE(rnd_buf)) { +		gcc_assert(read(urandom_fd, rnd_buf, sizeof(rnd_buf)) == sizeof(rnd_buf)); +		rnd_idx = 0; +	} +	return rnd_buf[rnd_idx++];  }  static tree tree_get_random_const(tree type) @@ -537,8 +543,6 @@ static void latent_entropy_start_unit(void *gcc_data __unused,  	tree type, id;  	int quals; -	seed = get_random_seed(false); -  	if (in_lto_p)  		return; @@ -573,6 +577,12 @@ __visible int plugin_init(struct plugin_name_args *plugin_info,  	const struct plugin_argument * const argv = plugin_info->argv;  	int i; +	/* +	 * Call get_random_seed() with noinit=true, so that this returns +	 * 0 in the case where no seed has been passed via -frandom-seed. +	 */ +	deterministic_seed = get_random_seed(true); +  	static const struct ggc_root_tab gt_ggc_r_gt_latent_entropy[] = {  		{  			.base = &latent_entropy_decl, diff --git a/scripts/gcc-plugins/randomize_layout_plugin.c b/scripts/gcc-plugins/randomize_layout_plugin.c index 334741a31d0a..951b74ba1b24 100644 --- a/scripts/gcc-plugins/randomize_layout_plugin.c +++ b/scripts/gcc-plugins/randomize_layout_plugin.c @@ -34,29 +34,11 @@ __visible int plugin_is_GPL_compatible;  static int performance_mode;  static struct plugin_info randomize_layout_plugin_info = { -	.version	= "201402201816vanilla", +	.version	= PLUGIN_VERSION,  	.help		= "disable\t\t\tdo not activate plugin\n"  			  "performance-mode\tenable cacheline-aware layout randomization\n"  }; -struct whitelist_entry { -	const char *pathname; -	const char *lhs; -	const char *rhs; -}; - -static const struct whitelist_entry whitelist[] = { -	/* NIU overloads mapping with page struct */ -	{ "drivers/net/ethernet/sun/niu.c", "page", "address_space" }, -	/* unix_skb_parms via UNIXCB() buffer */ -	{ "net/unix/af_unix.c", "unix_skb_parms", "char" }, -	/* big_key payload.data struct splashing */ -	{ "security/keys/big_key.c", "path", "void *" }, -	/* walk struct security_hook_heads as an array of struct hlist_head */ -	{ "security/security.c", "hlist_head", "security_hook_heads" }, -	{ } -}; -  /* from old Linux dcache.h */  static inline unsigned long  partial_name_hash(unsigned long c, unsigned long prevhash) @@ -742,60 +724,6 @@ static void handle_local_var_initializers(void)  	}  } -static bool type_name_eq(gimple stmt, const_tree type_tree, const char *wanted_name) -{ -	const char *type_name; - -	if (type_tree == NULL_TREE) -		return false; - -	switch (TREE_CODE(type_tree)) { -	case RECORD_TYPE: -		type_name = TYPE_NAME_POINTER(type_tree); -		break; -	case INTEGER_TYPE: -		if (TYPE_PRECISION(type_tree) == CHAR_TYPE_SIZE) -			type_name = "char"; -		else { -			INFORM(gimple_location(stmt), "found non-char INTEGER_TYPE cast comparison: %qT\n", type_tree); -			debug_tree(type_tree); -			return false; -		} -		break; -	case POINTER_TYPE: -		if (TREE_CODE(TREE_TYPE(type_tree)) == VOID_TYPE) { -			type_name = "void *"; -			break; -		} else { -			INFORM(gimple_location(stmt), "found non-void POINTER_TYPE cast comparison %qT\n", type_tree); -			debug_tree(type_tree); -			return false; -		} -	default: -		INFORM(gimple_location(stmt), "unhandled cast comparison: %qT\n", type_tree); -		debug_tree(type_tree); -		return false; -	} - -	return strcmp(type_name, wanted_name) == 0; -} - -static bool whitelisted_cast(gimple stmt, const_tree lhs_tree, const_tree rhs_tree) -{ -	const struct whitelist_entry *entry; -	expanded_location xloc = expand_location(gimple_location(stmt)); - -	for (entry = whitelist; entry->pathname; entry++) { -		if (!strstr(xloc.file, entry->pathname)) -			continue; - -		if (type_name_eq(stmt, lhs_tree, entry->lhs) && type_name_eq(stmt, rhs_tree, entry->rhs)) -			return true; -	} - -	return false; -} -  /*   * iterate over all statements to find "bad" casts:   * those where the address of the start of a structure is cast @@ -872,10 +800,7 @@ static unsigned int find_bad_casts_execute(void)  #ifndef __DEBUG_PLUGIN  				if (lookup_attribute("randomize_performed", TYPE_ATTRIBUTES(ptr_lhs_type)))  #endif -				{ -					if (!whitelisted_cast(stmt, ptr_lhs_type, ptr_rhs_type)) -						MISMATCH(gimple_location(stmt), "rhs", ptr_lhs_type, ptr_rhs_type); -				} +				MISMATCH(gimple_location(stmt), "rhs", ptr_lhs_type, ptr_rhs_type);  				continue;  			} @@ -898,10 +823,7 @@ static unsigned int find_bad_casts_execute(void)  #ifndef __DEBUG_PLUGIN  				if (lookup_attribute("randomize_performed", TYPE_ATTRIBUTES(op0_type)))  #endif -				{ -					if (!whitelisted_cast(stmt, ptr_lhs_type, op0_type)) -						MISMATCH(gimple_location(stmt), "op0", ptr_lhs_type, op0_type); -				} +				MISMATCH(gimple_location(stmt), "op0", ptr_lhs_type, op0_type);  			} else {  				const_tree ssa_name_var = SSA_NAME_VAR(rhs1);  				/* skip bogus type casts introduced by container_of */ @@ -911,10 +833,7 @@ static unsigned int find_bad_casts_execute(void)  #ifndef __DEBUG_PLUGIN  				if (lookup_attribute("randomize_performed", TYPE_ATTRIBUTES(ptr_rhs_type)))  #endif -				{ -					if (!whitelisted_cast(stmt, ptr_lhs_type, ptr_rhs_type)) -						MISMATCH(gimple_location(stmt), "ssa", ptr_lhs_type, ptr_rhs_type); -				} +				MISMATCH(gimple_location(stmt), "ssa", ptr_lhs_type, ptr_rhs_type);  			}  		} diff --git a/scripts/gcc-plugins/sancov_plugin.c b/scripts/gcc-plugins/sancov_plugin.c index 23bd023a283b..b76cb9c42cec 100644 --- a/scripts/gcc-plugins/sancov_plugin.c +++ b/scripts/gcc-plugins/sancov_plugin.c @@ -26,7 +26,7 @@ __visible int plugin_is_GPL_compatible;  tree sancov_fndecl;  static struct plugin_info sancov_plugin_info = { -	.version	= "20160402", +	.version	= PLUGIN_VERSION,  	.help		= "sancov plugin\n",  }; diff --git a/scripts/gcc-plugins/stackleak_plugin.c b/scripts/gcc-plugins/stackleak_plugin.c index 42f0252ee2a4..ff91885f9470 100644 --- a/scripts/gcc-plugins/stackleak_plugin.c +++ b/scripts/gcc-plugins/stackleak_plugin.c @@ -44,7 +44,7 @@ static bool verbose = false;  static GTY(()) tree track_function_decl;  static struct plugin_info stackleak_plugin_info = { -	.version = "201707101337", +	.version = PLUGIN_VERSION,  	.help = "track-min-size=nn\ttrack stack for functions with a stack frame size >= nn bytes\n"  		"arch=target_arch\tspecify target build arch\n"  		"disable\t\tdo not activate the plugin\n" diff --git a/scripts/gcc-plugins/structleak_plugin.c b/scripts/gcc-plugins/structleak_plugin.c index 74e319288389..8bc04068ed39 100644 --- a/scripts/gcc-plugins/structleak_plugin.c +++ b/scripts/gcc-plugins/structleak_plugin.c @@ -37,7 +37,7 @@  __visible int plugin_is_GPL_compatible;  static struct plugin_info structleak_plugin_info = { -	.version	= "20190125vanilla", +	.version	= PLUGIN_VERSION,  	.help		= "disable\tdo not activate plugin\n"  			  "byref\tinit structs passed by reference\n"  			  "byref-all\tinit anything passed by reference\n"  |