Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Thu,  5 May 2016 10:21:08 -0700
From: Michael Leibowitz <michael.leibowitz@...el.com>
To: spender@...ecurity.net,
	kernel-hardening@...ts.openwall.com,
	keescook@...omium.org,
	re.emese@...il.com,
	pageexec@...email.hu
Cc: michael.leibowitz@...el.com
Subject: [RFC 2/3] Enable the RANDSTRUCT plugin

These are config changes necessary to configure/enable the
structure layout randomizing gcc plugin

This feature is ported over from grsecurity.  This is largely
unchanged from the Original code written by the PaX Team and Spender.

Signed-off-by: Michael Leibowitz <michael.leibowitz@...el.com>
---
 arch/Kconfig                 | 43 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/compiler-gcc.h |  5 +++++
 include/linux/compiler.h     |  9 +++++++++
 include/linux/vermagic.h     |  9 ++++++++-
 kernel/module.c              | 27 +++++++++++++++++++++++++++
 5 files changed, 92 insertions(+), 1 deletion(-)

diff --git a/arch/Kconfig b/arch/Kconfig
index 8af17ae..c3955a2 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -389,6 +389,49 @@ config GCC_PLUGIN_SANCOV
 	  gcc-4.5 on). It is based on the commit "Add fuzzing coverage support"
 	  by Dmitry Vyukov <dvyukov@...gle.com>.
 
+config GCC_PLUGIN_RANDSTRUCT
+	bool "Randomize layout of sensitive kernel structures"
+	default n
+	depends on GCC_PLUGINS
+	select MODVERSIONS if MODULES
+	help
+
+	  If you say Y here, the layouts of a number of sensitive kernel
+	  structures and all structures composed entirely of function pointers
+	  (aka "ops" structs) will be randomized at compile-time.  This can make
+	  exploitation that targets these structures more difficult by either
+	  requiring an additional information leak vulnerability, or knowing the
+	  pricise build that the target is running.
+
+	  Enabling this feature will have a 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).
+
+	  Additionally, enabling this feature causes modules compiled with one
+	  random seed to have gibberish names when loaded by a kernel with a
+	  different random seed.
+
+	  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.
+
+	  Note that the implementation requires gcc 4.6.4. or newer.  You may need
+	  to install the supporting headers explicitly in addition to the normal
+	  gcc package.
+
+config GCC_PLUGIN_RANDSTRUCT_PERFORMANCE
+	bool "Use cacheline-aware structure randomization"
+	default n
+	depends on GCC_PLUGIN_RANDSTRUCT
+	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_CC_STACKPROTECTOR
 	bool
 	help
diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h
index 22ab246..7bfa763 100644
--- a/include/linux/compiler-gcc.h
+++ b/include/linux/compiler-gcc.h
@@ -201,6 +201,11 @@
 /* Mark a function definition as prohibited from being cloned. */
 #define __noclone	__attribute__((__noclone__))
 
+#ifdef RANDSTRUCT_PLUGIN
+#define __randomize_layout __attribute__((randomize_layout))
+#define __no_randomize_layout __attribute__((no_randomize_layout))
+#endif
+
 #endif /* GCC_VERSION >= 40500 */
 
 #if GCC_VERSION >= 40600
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 48f5aab..8d0776e 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -416,6 +416,15 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
 # define __attribute_const__	/* unimplemented */
 #endif
 
+#ifndef __randomize_layout
+# define __randomize_layout
+#endif
+
+#ifndef __no_randomize_layout
+# define __no_randomize_layout
+#endif
+
+
 /*
  * Tell gcc if a function is cold. The compiler will assume any path
  * directly leading to the call is unlikely.
diff --git a/include/linux/vermagic.h b/include/linux/vermagic.h
index 6f8fbcf..af6c03f 100644
--- a/include/linux/vermagic.h
+++ b/include/linux/vermagic.h
@@ -24,10 +24,17 @@
 #ifndef MODULE_ARCH_VERMAGIC
 #define MODULE_ARCH_VERMAGIC ""
 #endif
+#ifdef RANDSTRUCT_PLUGIN
+#include <generated/randomize_layout_hash.h>
+#define MODULE_RANDSTRUCT_PLUGIN "RANDSTRUCT_PLUGIN_" RANDSTRUCT_HASHED_SEED
+#else
+#define MODULE_RANDSTRUCT_PLUGIN
+#endif
 
 #define VERMAGIC_STRING 						\
 	UTS_RELEASE " "							\
 	MODULE_VERMAGIC_SMP MODULE_VERMAGIC_PREEMPT 			\
 	MODULE_VERMAGIC_MODULE_UNLOAD MODULE_VERMAGIC_MODVERSIONS	\
-	MODULE_ARCH_VERMAGIC
+	MODULE_ARCH_VERMAGIC						\
+	MODULE_RANDSTRUCT_PLUGIN
 
diff --git a/kernel/module.c b/kernel/module.c
index 794ebe8..74cf098 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -1296,12 +1296,31 @@ static int check_version(Elf_Shdr *sechdrs,
 		goto bad_version;
 	}
 
+#ifdef CONFIG_GCC_PLUGIN_RANDSTRUCT
+	/*
+	 * avoid potentially printing jibberish on attempted load
+	 * of a module randomized with a different seed
+	 */
+	pr_warn("no symbol version for %s\n", symname);
+#else
+	pr_warn("%s: no symbol version for %s\n", mod->name, symname);
+#endif
+
 	pr_warn("%s: no symbol version for %s\n", mod->name, symname);
 	return 0;
 
 bad_version:
+#ifdef CONFIG_GCC_PLUGIN_RANDSTRUCT
+	/*
+	 * avoid potentially printing jibberish on attempted load
+	 * of a module randomized with a different seed
+	 */
+	pr_warn("attempted module disagrees about version of symbol %s\n",
+		symname);
+#else
 	pr_warn("%s: disagrees about version of symbol %s\n",
 	       mod->name, symname);
+#endif
 	return 0;
 }
 
@@ -2835,7 +2854,15 @@ static struct module *setup_load_info(struct load_info *info, int flags)
 	mod = (void *)info->sechdrs[info->index.mod].sh_addr;
 
 	if (info->index.sym == 0) {
+#ifdef CONFIG_GCC_PLUGIN_RANDSTRUCT
+		/*
+		 * avoid potentially printing jibberish on attempted load
+		 * of a module randomized with a different seed
+		 */
+		pr_warn("module has no symbols (stripped?)\n");
+#else
 		pr_warn("%s: module has no symbols (stripped?)\n", mod->name);
+#endif
 		return ERR_PTR(-ENOEXEC);
 	}
 
-- 
1.9.1

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.