linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 00/20] Introduce struct layout randomization plugin
@ 2017-05-26 20:17 Kees Cook
  2017-05-26 20:17 ` [PATCH v2 01/20] NFS: Avoid cross-structure casting Kees Cook
                   ` (19 more replies)
  0 siblings, 20 replies; 55+ messages in thread
From: Kees Cook @ 2017-05-26 20:17 UTC (permalink / raw)
  To: kernel-hardening; +Cc: Kees Cook, Laura Abbott, x86, linux-kernel

This series brings grsecurity's structure layout randomization plugin
to upstream. The plugin randomizes the layout of selected structures at
compile time, as a probabilistic defense against attacks that need to
know the layout of structures within the kernel. This is most useful for
"in-house" kernel builds where the neither the randomization seed nor
other build artifacts are made available to an attacker. While less useful
for distribution kernels (where the randomization seed must be exposed for
third party kernel module builds), it still has some value there since now
all kernel builds would need to be tracked by an attacker.

One requirement of the plugin is that randomized structures must use
designated initializers. Many of these have been landing already as
I've been sending them over the past couple months, but there are
still some stragglers, which are included here.

Another area to address are places where randomized structures are cast
to other structures, since there may be implicit positional details
that need to be addressed. Luckily, there are only a few of these false
positives, and they have been worked around either by adjusting the source
(e.g. correctly using ERR_CAST() or container_of()) or whitelisting them
in the plugin. Some of these fixes have landed already, again with
stragglers included here.

The plugin selects structures in two ways: manually marked with the
new __randomize_layout annotation, or automatically when a structure
is found to consist entirely of function pointers (which can be opted
out of with the new __no_randomize_layout annotation).

A structure that is especially sensitive and regularly abused in
exploits is task_struct, but randomizing it requires some special
handling due to some fields needing to be at the start and end. To
deal with this, an internal anonymous struct is used to mark the
portion that will be randomized. I'd love feedback on whether I
should bite the bullet and perform indenting or violate indenting
rules to avoid a massive white-space change. Also is the problem
that older GCC seems to balk at its use, which I have not figured
out yet.

As already mentioned, the bulk of this feature and annotations are ported
over from grsecurity. The implementation is almost entirely identical
to the original code written by the PaX Team and Brad Spengler. The
changes are an addition of improved designated initializer markings,
a whitelisting mechanism, many false positive fixes, and a different
approach to handling the task_struct randomization.

I've been doing boot tests with instrumentation showing successfully
changing offsets within the task_struct, which ran overnight without
problems. So far, the 0day builder hasn't alerted on anything either.

This series is based on next-20170525.

I intend to push patches 1 through 18 into linux-next if there are no
objections. The task_struct change needs some more attention, and I
continue to wait on ACPICA to take the changes in the final patch.

Patches are:

[PATCH 01/20] NFS: Avoid cross-structure casting
	Fix to use ERR_CAST()

[PATCH 02/20] gcc-plugins: Detail c-common.h location for GCC 4.6
	Update documentation about GCC 4.6 version file locations.

[PATCH 03/20] compiler: Add __designated_init annotation
	Introduce annotation for designated initializers.

[PATCH 04/20] gcc-plugins: Add the randstruct plugin
	The plugin itself, with struct auto-detection disabled.

[PATCH 05/20] randstruct: Whitelist struct security_hook_heads cast
[PATCH 06/20] randstruct: Whitelist UNIXCB cast
[PATCH 07/20] randstruct: Whitelist big_key path struct overloading
[PATCH 08/20] randstruct: Whitelist NIU struct page overloading
	Whitelist a number of false positives that do not have
	trivial source corrections to be made.

[PATCH 09/20] randstruct: Mark various structs for randomization
	Adds the manual annotation for structures to randomize.

[PATCH 10/20] randstruct: opt-out externally exposed function pointer
	Opt out of some externally-exposed structs that would be
	otherwise automatically randomized.

[PATCH 11/20] randstruct: Disable randomization of ACPICA structs
	Opt out of ACPICA randomization.

[PATCH 12/20] sgi-xp: Use designated initializers
[PATCH 13/20] drm/amdgpu: Use designated initializers
[PATCH 14/20] drm/amd/powerplay: Use designated initializers
[PATCH 15/20] mtk-vcodec: Use designated initializers
	The remaining designated initializer fixes for automatic
	struct randomization.

[PATCH 16/20] ntfs: Use ERR_CAST() to avoid cross-structure cast
[PATCH 17/20] ocfs2: Use ERR_CAST() to avoid cross-structure cast
	The remaining cast fixes for automatic struct randomization.

[PATCH 18/20] randstruct: Enable function pointer struct detection
	Enables automatic struct randomization.

[PATCH 19/20] [RFC] task_struct: Allow randomized layout
	Tricky anonymous struct within task_struct...

[PATCH 20/20] ACPICA: Use designated initializers
	Proposed upstream ACPICA solution for designated initializers...

Testing/feedback appreciated!

-Kees

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [PATCH v2 01/20] NFS: Avoid cross-structure casting
  2017-05-26 20:17 [PATCH v2 00/20] Introduce struct layout randomization plugin Kees Cook
@ 2017-05-26 20:17 ` Kees Cook
  2017-05-28  7:53   ` Christoph Hellwig
  2017-05-26 20:17 ` [PATCH v2 02/20] gcc-plugins: Detail c-common.h location for GCC 4.6 Kees Cook
                   ` (18 subsequent siblings)
  19 siblings, 1 reply; 55+ messages in thread
From: Kees Cook @ 2017-05-26 20:17 UTC (permalink / raw)
  To: kernel-hardening; +Cc: Kees Cook, Laura Abbott, x86, linux-kernel

When the call to nfs_devname() fails, the error path attempts to retain
the error via the mnt variable, but this requires a cast across very
different types (char * to struct vfsmount *), which the upcoming
structure layout randomization plugin flags as being potentially
dangerous in the face of randomization. This is a false positive, but
what this code actually wants to do is retain the error value, so this
patch explicitly sets it, instead of using what seems to be an
unexpected cast.

Signed-off-by: Kees Cook <keescook@chromium.org>
Acked-by: Trond Myklebust <trond.myklebust@primarydata.com>
---
 fs/nfs/namespace.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index 1a224a33a6c2..e5686be67be8 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -246,7 +246,7 @@ struct vfsmount *nfs_do_submount(struct dentry *dentry, struct nfs_fh *fh,
 
 	devname = nfs_devname(dentry, page, PAGE_SIZE);
 	if (IS_ERR(devname))
-		mnt = (struct vfsmount *)devname;
+		mnt = ERR_CAST(devname);
 	else
 		mnt = nfs_do_clone_mount(NFS_SB(dentry->d_sb), devname, &mountdata);
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v2 02/20] gcc-plugins: Detail c-common.h location for GCC 4.6
  2017-05-26 20:17 [PATCH v2 00/20] Introduce struct layout randomization plugin Kees Cook
  2017-05-26 20:17 ` [PATCH v2 01/20] NFS: Avoid cross-structure casting Kees Cook
@ 2017-05-26 20:17 ` Kees Cook
  2017-05-26 20:17 ` [PATCH v2 03/20] compiler: Add __designated_init annotation Kees Cook
                   ` (17 subsequent siblings)
  19 siblings, 0 replies; 55+ messages in thread
From: Kees Cook @ 2017-05-26 20:17 UTC (permalink / raw)
  To: kernel-hardening; +Cc: Kees Cook, Laura Abbott, x86, linux-kernel

The c-common.h file moved in stock gcc 4.7, not gcc 4.6. However, most
people building plugins with gcc 4.6 are using the Debian or Ubuntu
version, which includes a patch to move the headers to the 4.7 location.
In case anyone trips over this with a stock gcc 4.6, add a pointer to the
patch used by Debian/Ubuntu.

Signed-off-by: Kees Cook <keescook@chromium.org>
---
 scripts/gcc-plugins/gcc-common.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/scripts/gcc-plugins/gcc-common.h b/scripts/gcc-plugins/gcc-common.h
index b232ab15624c..918953ca4527 100644
--- a/scripts/gcc-plugins/gcc-common.h
+++ b/scripts/gcc-plugins/gcc-common.h
@@ -63,6 +63,13 @@
 #endif
 
 #if BUILDING_GCC_VERSION >= 4006
+/*
+ * The c-family headers were moved into a subdirectory in GCC version
+ * 4.7, but most plugin-building users of GCC 4.6 are using the Debian
+ * or Ubuntu package, which has an out-of-tree patch to move this to the
+ * same location as found in 4.7 and later:
+ * https://sources.debian.net/src/gcc-4.6/4.6.3-14/debian/patches/pr45078.diff/
+ */
 #include "c-family/c-common.h"
 #else
 #include "c-common.h"
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v2 03/20] compiler: Add __designated_init annotation
  2017-05-26 20:17 [PATCH v2 00/20] Introduce struct layout randomization plugin Kees Cook
  2017-05-26 20:17 ` [PATCH v2 01/20] NFS: Avoid cross-structure casting Kees Cook
  2017-05-26 20:17 ` [PATCH v2 02/20] gcc-plugins: Detail c-common.h location for GCC 4.6 Kees Cook
@ 2017-05-26 20:17 ` Kees Cook
  2017-05-26 20:17 ` [PATCH v2 04/20] gcc-plugins: Add the randstruct plugin Kees Cook
                   ` (16 subsequent siblings)
  19 siblings, 0 replies; 55+ messages in thread
From: Kees Cook @ 2017-05-26 20:17 UTC (permalink / raw)
  To: kernel-hardening; +Cc: Kees Cook, Laura Abbott, x86, linux-kernel

This allows structure annotations for requiring designated initialization
in GCC 5.1.0 and later:
https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html

The structure randomization layout plugin will be using this to help
identify structures that need this form of initialization.

Signed-off-by: Kees Cook <keescook@chromium.org>
---
 include/linux/compiler-gcc.h | 8 ++++++++
 include/linux/compiler.h     | 4 ++++
 2 files changed, 12 insertions(+)

diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h
index 0efef9cf014f..386caf6771ed 100644
--- a/include/linux/compiler-gcc.h
+++ b/include/linux/compiler-gcc.h
@@ -294,6 +294,14 @@
 #define __no_sanitize_address __attribute__((no_sanitize_address))
 #endif
 
+#if GCC_VERSION >= 50100
+/*
+ * Mark structures as requiring designated initializers.
+ * https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html
+ */
+#define __designated_init __attribute__((designated_init))
+#endif
+
 #endif	/* gcc version >= 40000 specific checks */
 
 #if !defined(__noclone)
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 707242fdbb89..bbe881054bf0 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -436,6 +436,10 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
 # define __attribute_const__	/* unimplemented */
 #endif
 
+#ifndef __designated_init
+# define __designated_init
+#endif
+
 #ifndef __latent_entropy
 # define __latent_entropy
 #endif
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v2 04/20] gcc-plugins: Add the randstruct plugin
  2017-05-26 20:17 [PATCH v2 00/20] Introduce struct layout randomization plugin Kees Cook
                   ` (2 preceding siblings ...)
  2017-05-26 20:17 ` [PATCH v2 03/20] compiler: Add __designated_init annotation Kees Cook
@ 2017-05-26 20:17 ` Kees Cook
  2017-06-29 22:08   ` Arnd Bergmann
  2017-05-26 20:17 ` [PATCH v2 05/20] randstruct: Whitelist struct security_hook_heads cast Kees Cook
                   ` (15 subsequent siblings)
  19 siblings, 1 reply; 55+ messages in thread
From: Kees Cook @ 2017-05-26 20:17 UTC (permalink / raw)
  To: kernel-hardening; +Cc: Kees Cook, Laura Abbott, x86, linux-kernel

This feature is ported from grsecurity. The implementation is almost
entirely identical to the original code written by the PaX Team and
Brad Spengler.

The new plugin randomizes the layout of selected structures at compile
time. This is a probabilistic defense against attacks that need to
know the layout of structures within the kernel. While less useful for
distribution kernels (where the randomization seed must be exposed for
third party kernel module builds), it still has some value there since
now all kernel builds would need to be tracked by an attacker. This is
most useful in situations where kernel build artifacts have not been
published (i.e. in-house kernel builds).

This defines two annotations __randomize_layout and __no_randomize_layout,
which respectively tell the plugin to either randomize or not to randomize
the struct in question. Follow-on patches enable the auto-detection
logic for selecting structures that contain only function pointers. It
is disabled here to assist with bisection.

Since any randomized structs must be initialized using designated
initializers, __randomize_layout includes the __designated_init
annotation even when the plugin is disabled so that all builds will
require the needed initialization. (The plugin adds the annotation
for automatically chosen structures.)

The main differences between this implemenation and grsecurity are:
- disable automatic struct selection (enabled in follow-up patch)
- add designated_init attribute at runtime and for manual marking
- clarify debugging output to differentiate bad cast warnings
- add whitelisting infrastructure
- support gcc 7's DECL_ALIGN and DECL_MODE changes (Laura Abbott)
- raise minimum required GCC version to 4.7

Earlier versions of this patch were ported by Michael Leibowitz.

Signed-off-by: Kees Cook <keescook@chromium.org>
---
 Documentation/dontdiff                        |    2 +
 arch/Kconfig                                  |   39 +
 include/linux/compiler-gcc.h                  |    5 +
 include/linux/compiler.h                      |    8 +
 include/linux/vermagic.h                      |    9 +-
 scripts/Makefile.gcc-plugins                  |    4 +
 scripts/gcc-plugins/.gitignore                |    1 +
 scripts/gcc-plugins/Makefile                  |    8 +
 scripts/gcc-plugins/gcc-common.h              |    5 +
 scripts/gcc-plugins/gen-random-seed.sh        |    8 +
 scripts/gcc-plugins/randomize_layout_plugin.c | 1017 +++++++++++++++++++++++++
 11 files changed, 1105 insertions(+), 1 deletion(-)
 create mode 100644 scripts/gcc-plugins/.gitignore
 create mode 100644 scripts/gcc-plugins/gen-random-seed.sh
 create mode 100644 scripts/gcc-plugins/randomize_layout_plugin.c

diff --git a/Documentation/dontdiff b/Documentation/dontdiff
index 77b92221f951..e10a484629e4 100644
--- a/Documentation/dontdiff
+++ b/Documentation/dontdiff
@@ -207,6 +207,8 @@ r200_reg_safe.h
 r300_reg_safe.h
 r420_reg_safe.h
 r600_reg_safe.h
+randomize_layout_hash.h
+randomize_layout_seed.h
 recordmcount
 relocs
 rlim_names.h
diff --git a/arch/Kconfig b/arch/Kconfig
index e0dced4da4bf..3eac97a4c7b3 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -443,6 +443,45 @@ config GCC_PLUGIN_STRUCTLEAK_VERBOSE
 	  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 explicitly
+	  marked by __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
+	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 386caf6771ed..7deaae3dc87d 100644
--- a/include/linux/compiler-gcc.h
+++ b/include/linux/compiler-gcc.h
@@ -223,6 +223,11 @@
 /* Mark a function definition as prohibited from being cloned. */
 #define __noclone	__attribute__((__noclone__, __optimize__("no-tracer")))
 
+#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 bbe881054bf0..219f82f3ec1a 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -444,6 +444,14 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
 # define __latent_entropy
 #endif
 
+#ifndef __randomize_layout
+# define __randomize_layout __designated_init
+#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 6f8fbcf10dfb..af6c03f7f986 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/scripts/Makefile.gcc-plugins b/scripts/Makefile.gcc-plugins
index 82335533620e..2e0e2eaa397f 100644
--- a/scripts/Makefile.gcc-plugins
+++ b/scripts/Makefile.gcc-plugins
@@ -29,6 +29,10 @@ ifdef CONFIG_GCC_PLUGINS
   gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK_VERBOSE)	+= -fplugin-arg-structleak_plugin-verbose
   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_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
diff --git a/scripts/gcc-plugins/.gitignore b/scripts/gcc-plugins/.gitignore
new file mode 100644
index 000000000000..de92ed9e3d83
--- /dev/null
+++ b/scripts/gcc-plugins/.gitignore
@@ -0,0 +1 @@
+randomize_layout_seed.h
diff --git a/scripts/gcc-plugins/Makefile b/scripts/gcc-plugins/Makefile
index 8b29dc17c73c..214eb2335c31 100644
--- a/scripts/gcc-plugins/Makefile
+++ b/scripts/gcc-plugins/Makefile
@@ -18,6 +18,14 @@ 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 = \
+  $(CONFIG_SHELL) $(srctree)/$(src)/gen-random-seed.sh $@ $(objtree)/include/generated/randomize_layout_hash.h
+$(objtree)/$(obj)/randomize_layout_seed.h: FORCE
+	$(call if_changed,create_randomize_layout_seed)
+targets = randomize_layout_seed.h randomize_layout_hash.h
+
 $(HOSTLIBS)-y := $(foreach p,$(GCC_PLUGIN),$(if $(findstring /,$(p)),,$(p)))
 always := $($(HOSTLIBS)-y)
 
diff --git a/scripts/gcc-plugins/gcc-common.h b/scripts/gcc-plugins/gcc-common.h
index 918953ca4527..6948898b3cdf 100644
--- a/scripts/gcc-plugins/gcc-common.h
+++ b/scripts/gcc-plugins/gcc-common.h
@@ -953,4 +953,9 @@ static inline void debug_gimple_stmt(const_gimple s)
 	get_inner_reference(exp, pbitsize, pbitpos, poffset, pmode, punsignedp, preversep, pvolatilep)
 #endif
 
+#if BUILDING_GCC_VERSION < 7000
+#define SET_DECL_ALIGN(decl, align)	DECL_ALIGN(decl) = (align)
+#define SET_DECL_MODE(decl, mode)	DECL_MODE(decl) = (mode)
+#endif
+
 #endif
diff --git a/scripts/gcc-plugins/gen-random-seed.sh b/scripts/gcc-plugins/gen-random-seed.sh
new file mode 100644
index 000000000000..7514850f4815
--- /dev/null
+++ b/scripts/gcc-plugins/gen-random-seed.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+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/randomize_layout_plugin.c b/scripts/gcc-plugins/randomize_layout_plugin.c
new file mode 100644
index 000000000000..bccbec2af0e4
--- /dev/null
+++ b/scripts/gcc-plugins/randomize_layout_plugin.c
@@ -0,0 +1,1017 @@
+/*
+ * Copyright 2014-2016 by Open Source Security, Inc., Brad Spengler <spender@grsecurity.net>
+ *                   and PaX Team <pageexec@freemail.hu>
+ * Licensed under the GPL v2
+ *
+ * Note: the choice of the license means that the compilation process is
+ *       NOT 'eligible' as defined by gcc's library exception to the GPL v3,
+ *       but for the kernel it doesn't matter since it doesn't link against
+ *       any of the gcc libraries
+ *
+ * Usage:
+ * $ # for 4.5/4.6/C based 4.7
+ * $ gcc -I`gcc -print-file-name=plugin`/include -I`gcc -print-file-name=plugin`/include/c-family -fPIC -shared -O2 -o randomize_layout_plugin.so randomize_layout_plugin.c
+ * $ # for C++ based 4.7/4.8+
+ * $ g++ -I`g++ -print-file-name=plugin`/include -I`g++ -print-file-name=plugin`/include/c-family -fPIC -shared -O2 -o randomize_layout_plugin.so randomize_layout_plugin.c
+ * $ gcc -fplugin=./randomize_layout_plugin.so test.c -O2
+ */
+
+#include "gcc-common.h"
+#include "randomize_layout_seed.h"
+
+#if BUILDING_GCC_MAJOR < 4 || (BUILDING_GCC_MAJOR == 4 && BUILDING_GCC_MINOR < 7)
+#error "The RANDSTRUCT plugin requires GCC 4.7 or newer."
+#endif
+
+#define ORIG_TYPE_NAME(node) \
+	(TYPE_NAME(TYPE_MAIN_VARIANT(node)) != NULL_TREE ? ((const unsigned char *)IDENTIFIER_POINTER(TYPE_NAME(TYPE_MAIN_VARIANT(node)))) : (const unsigned char *)"anonymous")
+
+__visible int plugin_is_GPL_compatible;
+
+static int performance_mode;
+
+static struct plugin_info randomize_layout_plugin_info = {
+	.version	= "201402201816vanilla",
+	.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[] = {
+	{ }
+};
+
+/* from old Linux dcache.h */
+static inline unsigned long
+partial_name_hash(unsigned long c, unsigned long prevhash)
+{
+	return (prevhash + (c << 4) + (c >> 4)) * 11;
+}
+static inline unsigned int
+name_hash(const unsigned char *name)
+{
+	unsigned long hash = 0;
+	unsigned int len = strlen((const char *)name);
+	while (len--)
+		hash = partial_name_hash(*name++, hash);
+	return (unsigned int)hash;
+}
+
+static tree handle_randomize_layout_attr(tree *node, tree name, tree args, int flags, bool *no_add_attrs)
+{
+	tree type;
+
+	*no_add_attrs = true;
+	if (TREE_CODE(*node) == FUNCTION_DECL) {
+		error("%qE attribute does not apply to functions (%qF)", name, *node);
+		return NULL_TREE;
+	}
+
+	if (TREE_CODE(*node) == PARM_DECL) {
+		error("%qE attribute does not apply to function parameters (%qD)", name, *node);
+		return NULL_TREE;
+	}
+
+	if (TREE_CODE(*node) == VAR_DECL) {
+		error("%qE attribute does not apply to variables (%qD)", name, *node);
+		return NULL_TREE;
+	}
+
+	if (TYPE_P(*node)) {
+		type = *node;
+	} else {
+		gcc_assert(TREE_CODE(*node) == TYPE_DECL);
+		type = TREE_TYPE(*node);
+	}
+
+	if (TREE_CODE(type) != RECORD_TYPE) {
+		error("%qE attribute used on %qT applies to struct types only", name, type);
+		return NULL_TREE;
+	}
+
+	if (lookup_attribute(IDENTIFIER_POINTER(name), TYPE_ATTRIBUTES(type))) {
+		error("%qE attribute is already applied to the type %qT", name, type);
+		return NULL_TREE;
+	}
+
+	*no_add_attrs = false;
+
+	return NULL_TREE;
+}
+
+/* set on complete types that we don't need to inspect further at all */
+static tree handle_randomize_considered_attr(tree *node, tree name, tree args, int flags, bool *no_add_attrs)
+{
+	*no_add_attrs = false;
+	return NULL_TREE;
+}
+
+/*
+ * set on types that we've performed a shuffle on, to prevent re-shuffling
+ * this does not preclude us from inspecting its fields for potential shuffles
+ */
+static tree handle_randomize_performed_attr(tree *node, tree name, tree args, int flags, bool *no_add_attrs)
+{
+	*no_add_attrs = false;
+	return NULL_TREE;
+}
+
+/*
+ * 64bit variant of Bob Jenkins' public domain PRNG
+ * 256 bits of internal state
+ */
+
+typedef unsigned long long u64;
+
+typedef struct ranctx { u64 a; u64 b; u64 c; u64 d; } ranctx;
+
+#define rot(x,k) (((x)<<(k))|((x)>>(64-(k))))
+static u64 ranval(ranctx *x) {
+	u64 e = x->a - rot(x->b, 7);
+	x->a = x->b ^ rot(x->c, 13);
+	x->b = x->c + rot(x->d, 37);
+	x->c = x->d + e;
+	x->d = e + x->a;
+	return x->d;
+}
+
+static void raninit(ranctx *x, u64 *seed) {
+	int i;
+
+	x->a = seed[0];
+	x->b = seed[1];
+	x->c = seed[2];
+	x->d = seed[3];
+
+	for (i=0; i < 30; ++i)
+		(void)ranval(x);
+}
+
+static u64 shuffle_seed[4];
+
+struct partition_group {
+	tree tree_start;
+	unsigned long start;
+	unsigned long length;
+};
+
+static void partition_struct(tree *fields, unsigned long length, struct partition_group *size_groups, unsigned long *num_groups)
+{
+	unsigned long i;
+	unsigned long accum_size = 0;
+	unsigned long accum_length = 0;
+	unsigned long group_idx = 0;
+
+	gcc_assert(length < INT_MAX);
+
+	memset(size_groups, 0, sizeof(struct partition_group) * length);
+
+	for (i = 0; i < length; i++) {
+		if (size_groups[group_idx].tree_start == NULL_TREE) {
+			size_groups[group_idx].tree_start = fields[i];
+			size_groups[group_idx].start = i;
+			accum_length = 0;
+			accum_size = 0;
+		}
+		accum_size += (unsigned long)int_size_in_bytes(TREE_TYPE(fields[i]));
+		accum_length++;
+		if (accum_size >= 64) {
+			size_groups[group_idx].length = accum_length;
+			accum_length = 0;
+			group_idx++;
+		}
+	}
+
+	if (size_groups[group_idx].tree_start != NULL_TREE &&
+	    !size_groups[group_idx].length) {
+		size_groups[group_idx].length = accum_length;
+		group_idx++;
+	}
+
+	*num_groups = group_idx;
+}
+
+static void performance_shuffle(tree *newtree, unsigned long length, ranctx *prng_state)
+{
+	unsigned long i, x;
+	struct partition_group size_group[length];
+	unsigned long num_groups = 0;
+	unsigned long randnum;
+
+	partition_struct(newtree, length, (struct partition_group *)&size_group, &num_groups);
+	for (i = num_groups - 1; i > 0; i--) {
+		struct partition_group tmp;
+		randnum = ranval(prng_state) % (i + 1);
+		tmp = size_group[i];
+		size_group[i] = size_group[randnum];
+		size_group[randnum] = tmp;
+	}
+
+	for (x = 0; x < num_groups; x++) {
+		for (i = size_group[x].start + size_group[x].length - 1; i > size_group[x].start; i--) {
+			tree tmp;
+			if (DECL_BIT_FIELD_TYPE(newtree[i]))
+				continue;
+			randnum = ranval(prng_state) % (i + 1);
+			// we could handle this case differently if desired
+			if (DECL_BIT_FIELD_TYPE(newtree[randnum]))
+				continue;
+			tmp = newtree[i];
+			newtree[i] = newtree[randnum];
+			newtree[randnum] = tmp;
+		}
+	}
+}
+
+static void full_shuffle(tree *newtree, unsigned long length, ranctx *prng_state)
+{
+	unsigned long i, randnum;
+
+	for (i = length - 1; i > 0; i--) {
+		tree tmp;
+		randnum = ranval(prng_state) % (i + 1);
+		tmp = newtree[i];
+		newtree[i] = newtree[randnum];
+		newtree[randnum] = tmp;
+	}
+}
+
+/* modern in-place Fisher-Yates shuffle */
+static void shuffle(const_tree type, tree *newtree, unsigned long length)
+{
+	unsigned long i;
+	u64 seed[4];
+	ranctx prng_state;
+	const unsigned char *structname;
+
+	if (length == 0)
+		return;
+
+	gcc_assert(TREE_CODE(type) == RECORD_TYPE);
+
+	structname = ORIG_TYPE_NAME(type);
+
+#ifdef __DEBUG_PLUGIN
+	fprintf(stderr, "Shuffling struct %s %p\n", (const char *)structname, type);
+#ifdef __DEBUG_VERBOSE
+	debug_tree((tree)type);
+#endif
+#endif
+
+	for (i = 0; i < 4; i++) {
+		seed[i] = shuffle_seed[i];
+		seed[i] ^= name_hash(structname);
+	}
+
+	raninit(&prng_state, (u64 *)&seed);
+
+	if (performance_mode)
+		performance_shuffle(newtree, length, &prng_state);
+	else
+		full_shuffle(newtree, length, &prng_state);
+}
+
+static bool is_flexible_array(const_tree field)
+{
+	const_tree fieldtype;
+	const_tree typesize;
+	const_tree elemtype;
+	const_tree elemsize;
+
+	fieldtype = TREE_TYPE(field);
+	typesize = TYPE_SIZE(fieldtype);
+
+	if (TREE_CODE(fieldtype) != ARRAY_TYPE)
+		return false;
+
+	elemtype = TREE_TYPE(fieldtype);
+	elemsize = TYPE_SIZE(elemtype);
+
+	/* size of type is represented in bits */
+
+	if (typesize == NULL_TREE && TYPE_DOMAIN(fieldtype) != NULL_TREE &&
+	    TYPE_MAX_VALUE(TYPE_DOMAIN(fieldtype)) == NULL_TREE)
+		return true;
+
+	if (typesize != NULL_TREE &&
+	    (TREE_CONSTANT(typesize) && (!tree_to_uhwi(typesize) ||
+	     tree_to_uhwi(typesize) == tree_to_uhwi(elemsize))))
+		return true;
+
+	return false;
+}
+
+static int relayout_struct(tree type)
+{
+	unsigned long num_fields = (unsigned long)list_length(TYPE_FIELDS(type));
+	unsigned long shuffle_length = num_fields;
+	tree field;
+	tree newtree[num_fields];
+	unsigned long i;
+	tree list;
+	tree variant;
+	tree main_variant;
+	expanded_location xloc;
+	bool has_flexarray = false;
+
+	if (TYPE_FIELDS(type) == NULL_TREE)
+		return 0;
+
+	if (num_fields < 2)
+		return 0;
+
+	gcc_assert(TREE_CODE(type) == RECORD_TYPE);
+
+	gcc_assert(num_fields < INT_MAX);
+
+	if (lookup_attribute("randomize_performed", TYPE_ATTRIBUTES(type)) ||
+	    lookup_attribute("no_randomize_layout", TYPE_ATTRIBUTES(TYPE_MAIN_VARIANT(type))))
+		return 0;
+
+	/* Workaround for 3rd-party VirtualBox source that we can't modify ourselves */
+	if (!strcmp((const char *)ORIG_TYPE_NAME(type), "INTNETTRUNKFACTORY") ||
+	    !strcmp((const char *)ORIG_TYPE_NAME(type), "RAWPCIFACTORY"))
+		return 0;
+
+	/* throw out any structs in uapi */
+	xloc = expand_location(DECL_SOURCE_LOCATION(TYPE_FIELDS(type)));
+
+	if (strstr(xloc.file, "/uapi/"))
+		error(G_("attempted to randomize userland API struct %s"), ORIG_TYPE_NAME(type));
+
+	for (field = TYPE_FIELDS(type), i = 0; field; field = TREE_CHAIN(field), i++) {
+		gcc_assert(TREE_CODE(field) == FIELD_DECL);
+		newtree[i] = field;
+	}
+
+	/*
+	 * enforce that we don't randomize the layout of the last
+	 * element of a struct if it's a 0 or 1-length array
+	 * or a proper flexible array
+	 */
+	if (is_flexible_array(newtree[num_fields - 1])) {
+		has_flexarray = true;
+		shuffle_length--;
+	}
+
+	shuffle(type, (tree *)newtree, shuffle_length);
+
+	/*
+	 * set up a bogus anonymous struct field designed to error out on unnamed struct initializers
+	 * as gcc provides no other way to detect such code
+	 */
+	list = make_node(FIELD_DECL);
+	TREE_CHAIN(list) = newtree[0];
+	TREE_TYPE(list) = void_type_node;
+	DECL_SIZE(list) = bitsize_zero_node;
+	DECL_NONADDRESSABLE_P(list) = 1;
+	DECL_FIELD_BIT_OFFSET(list) = bitsize_zero_node;
+	DECL_SIZE_UNIT(list) = size_zero_node;
+	DECL_FIELD_OFFSET(list) = size_zero_node;
+	DECL_CONTEXT(list) = type;
+	// to satisfy the constify plugin
+	TREE_READONLY(list) = 1;
+
+	for (i = 0; i < num_fields - 1; i++)
+		TREE_CHAIN(newtree[i]) = newtree[i+1];
+	TREE_CHAIN(newtree[num_fields - 1]) = NULL_TREE;
+
+	main_variant = TYPE_MAIN_VARIANT(type);
+	for (variant = main_variant; variant; variant = TYPE_NEXT_VARIANT(variant)) {
+		TYPE_FIELDS(variant) = list;
+		TYPE_ATTRIBUTES(variant) = copy_list(TYPE_ATTRIBUTES(variant));
+		TYPE_ATTRIBUTES(variant) = tree_cons(get_identifier("randomize_performed"), NULL_TREE, TYPE_ATTRIBUTES(variant));
+		TYPE_ATTRIBUTES(variant) = tree_cons(get_identifier("designated_init"), NULL_TREE, TYPE_ATTRIBUTES(variant));
+		if (has_flexarray)
+			TYPE_ATTRIBUTES(type) = tree_cons(get_identifier("has_flexarray"), NULL_TREE, TYPE_ATTRIBUTES(type));
+	}
+
+	/*
+	 * force a re-layout of the main variant
+	 * the TYPE_SIZE for all variants will be recomputed
+	 * by finalize_type_size()
+	 */
+	TYPE_SIZE(main_variant) = NULL_TREE;
+	layout_type(main_variant);
+	gcc_assert(TYPE_SIZE(main_variant) != NULL_TREE);
+
+	return 1;
+}
+
+/* from constify plugin */
+static const_tree get_field_type(const_tree field)
+{
+	return strip_array_types(TREE_TYPE(field));
+}
+
+/* from constify plugin */
+static bool is_fptr(const_tree fieldtype)
+{
+	if (TREE_CODE(fieldtype) != POINTER_TYPE)
+		return false;
+
+	return TREE_CODE(TREE_TYPE(fieldtype)) == FUNCTION_TYPE;
+}
+
+/* derived from constify plugin */
+static int is_pure_ops_struct(const_tree node)
+{
+	const_tree field;
+
+	gcc_assert(TREE_CODE(node) == RECORD_TYPE || TREE_CODE(node) == UNION_TYPE);
+
+	/* XXX: Do not apply randomization to all-ftpr structs yet. */
+	return 0;
+
+	for (field = TYPE_FIELDS(node); field; field = TREE_CHAIN(field)) {
+		const_tree fieldtype = get_field_type(field);
+		enum tree_code code = TREE_CODE(fieldtype);
+
+		if (node == fieldtype)
+			continue;
+
+		if (!is_fptr(fieldtype))
+			return 0;
+
+		if (code != RECORD_TYPE && code != UNION_TYPE)
+			continue;
+
+		if (!is_pure_ops_struct(fieldtype))
+			return 0;
+	}
+
+	return 1;
+}
+
+static void randomize_type(tree type)
+{
+	tree variant;
+
+	gcc_assert(TREE_CODE(type) == RECORD_TYPE);
+
+	if (lookup_attribute("randomize_considered", TYPE_ATTRIBUTES(type)))
+		return;
+
+	if (lookup_attribute("randomize_layout", TYPE_ATTRIBUTES(TYPE_MAIN_VARIANT(type))) || is_pure_ops_struct(type))
+		relayout_struct(type);
+
+	for (variant = TYPE_MAIN_VARIANT(type); variant; variant = TYPE_NEXT_VARIANT(variant)) {
+		TYPE_ATTRIBUTES(type) = copy_list(TYPE_ATTRIBUTES(type));
+		TYPE_ATTRIBUTES(type) = tree_cons(get_identifier("randomize_considered"), NULL_TREE, TYPE_ATTRIBUTES(type));
+	}
+#ifdef __DEBUG_PLUGIN
+	fprintf(stderr, "Marking randomize_considered on struct %s\n", ORIG_TYPE_NAME(type));
+#ifdef __DEBUG_VERBOSE
+	debug_tree(type);
+#endif
+#endif
+}
+
+static void update_decl_size(tree decl)
+{
+	tree lastval, lastidx, field, init, type, flexsize;
+	unsigned HOST_WIDE_INT len;
+
+	type = TREE_TYPE(decl);
+
+	if (!lookup_attribute("has_flexarray", TYPE_ATTRIBUTES(type)))
+		return;
+
+	init = DECL_INITIAL(decl);
+	if (init == NULL_TREE || init == error_mark_node)
+		return;
+
+	if (TREE_CODE(init) != CONSTRUCTOR)
+		return;
+
+	len = CONSTRUCTOR_NELTS(init);
+        if (!len)
+		return;
+
+	lastval = CONSTRUCTOR_ELT(init, CONSTRUCTOR_NELTS(init) - 1)->value;
+	lastidx = CONSTRUCTOR_ELT(init, CONSTRUCTOR_NELTS(init) - 1)->index;
+
+	for (field = TYPE_FIELDS(TREE_TYPE(decl)); TREE_CHAIN(field); field = TREE_CHAIN(field))
+		;
+
+	if (lastidx != field)
+		return;
+
+	if (TREE_CODE(lastval) != STRING_CST) {
+		error("Only string constants are supported as initializers "
+		      "for randomized structures with flexible arrays");
+		return;
+	}
+
+	flexsize = bitsize_int(TREE_STRING_LENGTH(lastval) *
+		tree_to_uhwi(TYPE_SIZE(TREE_TYPE(TREE_TYPE(lastval)))));
+
+	DECL_SIZE(decl) = size_binop(PLUS_EXPR, TYPE_SIZE(type), flexsize);
+
+	return;
+}
+
+
+static void randomize_layout_finish_decl(void *event_data, void *data)
+{
+	tree decl = (tree)event_data;
+	tree type;
+
+	if (decl == NULL_TREE || decl == error_mark_node)
+		return;
+
+	type = TREE_TYPE(decl);
+
+	if (TREE_CODE(decl) != VAR_DECL)
+		return;
+
+	if (TREE_CODE(type) != RECORD_TYPE && TREE_CODE(type) != UNION_TYPE)
+		return;
+
+	if (!lookup_attribute("randomize_performed", TYPE_ATTRIBUTES(type)))
+		return;
+
+	DECL_SIZE(decl) = 0;
+	DECL_SIZE_UNIT(decl) = 0;
+	SET_DECL_ALIGN(decl, 0);
+	SET_DECL_MODE (decl, VOIDmode);
+	SET_DECL_RTL(decl, 0);
+	update_decl_size(decl);
+	layout_decl(decl, 0);
+}
+
+static void finish_type(void *event_data, void *data)
+{
+	tree type = (tree)event_data;
+
+	if (type == NULL_TREE || type == error_mark_node)
+		return;
+
+	if (TREE_CODE(type) != RECORD_TYPE)
+		return;
+
+	if (TYPE_FIELDS(type) == NULL_TREE)
+		return;
+
+	if (lookup_attribute("randomize_considered", TYPE_ATTRIBUTES(type)))
+		return;
+
+#ifdef __DEBUG_PLUGIN
+	fprintf(stderr, "Calling randomize_type on %s\n", ORIG_TYPE_NAME(type));
+#endif
+#ifdef __DEBUG_VERBOSE
+	debug_tree(type);
+#endif
+	randomize_type(type);
+
+	return;
+}
+
+static struct attribute_spec randomize_layout_attr = {
+	.name		= "randomize_layout",
+	// related to args
+	.min_length	= 0,
+	.max_length	= 0,
+	.decl_required	= false,
+	// need type declaration
+	.type_required	= true,
+	.function_type_required = false,
+	.handler		= handle_randomize_layout_attr,
+#if BUILDING_GCC_VERSION >= 4007
+	.affects_type_identity  = true
+#endif
+};
+
+static struct attribute_spec no_randomize_layout_attr = {
+	.name		= "no_randomize_layout",
+	// related to args
+	.min_length	= 0,
+	.max_length	= 0,
+	.decl_required	= false,
+	// need type declaration
+	.type_required	= true,
+	.function_type_required = false,
+	.handler		= handle_randomize_layout_attr,
+#if BUILDING_GCC_VERSION >= 4007
+	.affects_type_identity  = true
+#endif
+};
+
+static struct attribute_spec randomize_considered_attr = {
+	.name		= "randomize_considered",
+	// related to args
+	.min_length	= 0,
+	.max_length	= 0,
+	.decl_required	= false,
+	// need type declaration
+	.type_required	= true,
+	.function_type_required = false,
+	.handler		= handle_randomize_considered_attr,
+#if BUILDING_GCC_VERSION >= 4007
+	.affects_type_identity  = false
+#endif
+};
+
+static struct attribute_spec randomize_performed_attr = {
+	.name		= "randomize_performed",
+	// related to args
+	.min_length	= 0,
+	.max_length	= 0,
+	.decl_required	= false,
+	// need type declaration
+	.type_required	= true,
+	.function_type_required = false,
+	.handler		= handle_randomize_performed_attr,
+#if BUILDING_GCC_VERSION >= 4007
+	.affects_type_identity  = false
+#endif
+};
+
+static void register_attributes(void *event_data, void *data)
+{
+	register_attribute(&randomize_layout_attr);
+	register_attribute(&no_randomize_layout_attr);
+	register_attribute(&randomize_considered_attr);
+	register_attribute(&randomize_performed_attr);
+}
+
+static void check_bad_casts_in_constructor(tree var, tree init)
+{
+	unsigned HOST_WIDE_INT idx;
+	tree field, val;
+	tree field_type, val_type;
+
+	FOR_EACH_CONSTRUCTOR_ELT(CONSTRUCTOR_ELTS(init), idx, field, val) {
+		if (TREE_CODE(val) == CONSTRUCTOR) {
+			check_bad_casts_in_constructor(var, val);
+			continue;
+		}
+
+		/* pipacs' plugin creates franken-arrays that differ from those produced by
+		   normal code which all have valid 'field' trees. work around this */
+		if (field == NULL_TREE)
+			continue;
+		field_type = TREE_TYPE(field);
+		val_type = TREE_TYPE(val);
+
+		if (TREE_CODE(field_type) != POINTER_TYPE || TREE_CODE(val_type) != POINTER_TYPE)
+			continue;
+
+		if (field_type == val_type)
+			continue;
+
+		field_type = TYPE_MAIN_VARIANT(strip_array_types(TYPE_MAIN_VARIANT(TREE_TYPE(field_type))));
+		val_type = TYPE_MAIN_VARIANT(strip_array_types(TYPE_MAIN_VARIANT(TREE_TYPE(val_type))));
+
+		if (field_type == void_type_node)
+			continue;
+		if (field_type == val_type)
+			continue;
+		if (TREE_CODE(val_type) != RECORD_TYPE)
+			continue;
+
+		if (!lookup_attribute("randomize_performed", TYPE_ATTRIBUTES(val_type)))
+			continue;
+		inform(DECL_SOURCE_LOCATION(var), "found mismatched constructor struct pointer types: %qT and %qT\n", TYPE_MAIN_VARIANT(field_type), TYPE_MAIN_VARIANT(val_type));
+	}
+}
+
+/* derived from the constify plugin */
+static void check_global_variables(void *event_data, void *data)
+{
+	struct varpool_node *node;
+	tree init;
+
+	FOR_EACH_VARIABLE(node) {
+		tree var = NODE_DECL(node);
+		init = DECL_INITIAL(var);
+		if (init == NULL_TREE)
+			continue;
+
+		if (TREE_CODE(init) != CONSTRUCTOR)
+			continue;
+
+		check_bad_casts_in_constructor(var, init);
+	}
+}
+
+static bool dominated_by_is_err(const_tree rhs, basic_block bb)
+{
+	basic_block dom;
+	gimple dom_stmt;
+	gimple call_stmt;
+	const_tree dom_lhs;
+	const_tree poss_is_err_cond;
+	const_tree poss_is_err_func;
+	const_tree is_err_arg;
+
+	dom = get_immediate_dominator(CDI_DOMINATORS, bb);
+	if (!dom)
+		return false;
+
+	dom_stmt = last_stmt(dom);
+	if (!dom_stmt)
+		return false;
+
+	if (gimple_code(dom_stmt) != GIMPLE_COND)
+		return false;
+
+	if (gimple_cond_code(dom_stmt) != NE_EXPR)
+		return false;
+
+	if (!integer_zerop(gimple_cond_rhs(dom_stmt)))
+		return false;
+
+	poss_is_err_cond = gimple_cond_lhs(dom_stmt);
+
+	if (TREE_CODE(poss_is_err_cond) != SSA_NAME)
+		return false;
+
+	call_stmt = SSA_NAME_DEF_STMT(poss_is_err_cond);
+
+	if (gimple_code(call_stmt) != GIMPLE_CALL)
+		return false;
+
+	dom_lhs = gimple_get_lhs(call_stmt);
+	poss_is_err_func = gimple_call_fndecl(call_stmt);
+	if (!poss_is_err_func)
+		return false;
+	if (dom_lhs != poss_is_err_cond)
+		return false;
+	if (strcmp(DECL_NAME_POINTER(poss_is_err_func), "IS_ERR"))
+		return false;
+
+	is_err_arg = gimple_call_arg(call_stmt, 0);
+	if (!is_err_arg)
+		return false;
+
+	if (is_err_arg != rhs)
+		return false;
+
+	return true;
+}
+
+static void handle_local_var_initializers(void)
+{
+	tree var;
+	unsigned int i;
+
+	FOR_EACH_LOCAL_DECL(cfun, i, var) {
+		tree init = DECL_INITIAL(var);
+		if (!init)
+			continue;
+		if (TREE_CODE(init) != CONSTRUCTOR)
+			continue;
+		check_bad_casts_in_constructor(var, init);
+	}
+}
+
+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
+ * to a pointer of a structure of a different type, or a
+ * structure pointer type is cast to a different structure pointer type
+ */
+static unsigned int find_bad_casts_execute(void)
+{
+	basic_block bb;
+
+	handle_local_var_initializers();
+
+	FOR_EACH_BB_FN(bb, cfun) {
+		gimple_stmt_iterator gsi;
+
+		for (gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) {
+			gimple stmt;
+			const_tree lhs;
+			const_tree lhs_type;
+			const_tree rhs1;
+			const_tree rhs_type;
+			const_tree ptr_lhs_type;
+			const_tree ptr_rhs_type;
+			const_tree op0;
+			const_tree op0_type;
+			enum tree_code rhs_code;
+
+			stmt = gsi_stmt(gsi);
+
+#ifdef __DEBUG_PLUGIN
+#ifdef __DEBUG_VERBOSE
+			debug_gimple_stmt(stmt);
+			debug_tree(gimple_get_lhs(stmt));
+#endif
+#endif
+
+			if (gimple_code(stmt) != GIMPLE_ASSIGN)
+				continue;
+
+#ifdef __DEBUG_PLUGIN
+#ifdef __DEBUG_VERBOSE
+			debug_tree(gimple_assign_rhs1(stmt));
+#endif
+#endif
+
+
+			rhs_code = gimple_assign_rhs_code(stmt);
+
+			if (rhs_code != ADDR_EXPR && rhs_code != SSA_NAME)
+				continue;
+
+			lhs = gimple_get_lhs(stmt);
+			lhs_type = TREE_TYPE(lhs);
+			rhs1 = gimple_assign_rhs1(stmt);
+			rhs_type = TREE_TYPE(rhs1);
+
+			if (TREE_CODE(rhs_type) != POINTER_TYPE ||
+			    TREE_CODE(lhs_type) != POINTER_TYPE)
+				continue;
+
+			ptr_lhs_type = TYPE_MAIN_VARIANT(strip_array_types(TYPE_MAIN_VARIANT(TREE_TYPE(lhs_type))));
+			ptr_rhs_type = TYPE_MAIN_VARIANT(strip_array_types(TYPE_MAIN_VARIANT(TREE_TYPE(rhs_type))));
+
+			if (ptr_rhs_type == void_type_node)
+				continue;
+
+			if (ptr_lhs_type == void_type_node)
+				continue;
+
+			if (dominated_by_is_err(rhs1, bb))
+				continue;
+
+			if (TREE_CODE(ptr_rhs_type) != RECORD_TYPE) {
+#ifndef __DEBUG_PLUGIN
+				if (lookup_attribute("randomize_performed", TYPE_ATTRIBUTES(ptr_lhs_type)))
+#endif
+				{
+					if (!whitelisted_cast(stmt, ptr_lhs_type, ptr_rhs_type))
+						inform(gimple_location(stmt), "found mismatched rhs struct pointer types: %qT and %qT\n", ptr_lhs_type, ptr_rhs_type);
+				}
+				continue;
+			}
+
+			if (rhs_code == SSA_NAME && ptr_lhs_type == ptr_rhs_type)
+				continue;
+
+			if (rhs_code == ADDR_EXPR) {
+				op0 = TREE_OPERAND(rhs1, 0);
+
+				if (op0 == NULL_TREE)
+					continue;
+
+				if (TREE_CODE(op0) != VAR_DECL)
+					continue;
+
+				op0_type = TYPE_MAIN_VARIANT(strip_array_types(TYPE_MAIN_VARIANT(TREE_TYPE(op0))));
+				if (op0_type == ptr_lhs_type)
+					continue;
+
+#ifndef __DEBUG_PLUGIN
+				if (lookup_attribute("randomize_performed", TYPE_ATTRIBUTES(op0_type)))
+#endif
+				{
+					if (!whitelisted_cast(stmt, ptr_lhs_type, op0_type))
+						inform(gimple_location(stmt), "found mismatched op0 struct pointer types: %qT and %qT\n", ptr_lhs_type, op0_type);
+				}
+			} else {
+				const_tree ssa_name_var = SSA_NAME_VAR(rhs1);
+				/* skip bogus type casts introduced by container_of */
+				if (ssa_name_var != NULL_TREE && DECL_NAME(ssa_name_var) && 
+				    !strcmp((const char *)DECL_NAME_POINTER(ssa_name_var), "__mptr"))
+					continue;
+#ifndef __DEBUG_PLUGIN
+				if (lookup_attribute("randomize_performed", TYPE_ATTRIBUTES(ptr_rhs_type)))
+#endif
+				{
+					if (!whitelisted_cast(stmt, ptr_lhs_type, ptr_rhs_type))
+						inform(gimple_location(stmt), "found mismatched ssa struct pointer types: %qT and %qT\n", ptr_lhs_type, ptr_rhs_type);
+				}
+			}
+
+		}
+	}
+	return 0;
+}
+
+#define PASS_NAME find_bad_casts
+#define NO_GATE
+#define TODO_FLAGS_FINISH TODO_dump_func
+#include "gcc-generate-gimple-pass.h"
+
+__visible int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version)
+{
+	int i;
+	const char * const plugin_name = plugin_info->base_name;
+	const int argc = plugin_info->argc;
+	const struct plugin_argument * const argv = plugin_info->argv;
+	bool enable = true;
+	int obtained_seed = 0;
+	struct register_pass_info find_bad_casts_pass_info;
+
+	find_bad_casts_pass_info.pass			= make_find_bad_casts_pass();
+	find_bad_casts_pass_info.reference_pass_name	= "ssa";
+	find_bad_casts_pass_info.ref_pass_instance_number	= 1;
+	find_bad_casts_pass_info.pos_op			= PASS_POS_INSERT_AFTER;
+
+	if (!plugin_default_version_check(version, &gcc_version)) {
+		error(G_("incompatible gcc/plugin versions"));
+		return 1;
+	}
+
+	if (strncmp(lang_hooks.name, "GNU C", 5) && !strncmp(lang_hooks.name, "GNU C+", 6)) {
+		inform(UNKNOWN_LOCATION, G_("%s supports C only, not %s"), plugin_name, lang_hooks.name);
+		enable = false;
+	}
+
+	for (i = 0; i < argc; ++i) {
+		if (!strcmp(argv[i].key, "disable")) {
+			enable = false;
+			continue;
+		}
+		if (!strcmp(argv[i].key, "performance-mode")) {
+			performance_mode = 1;
+			continue;
+		}
+		error(G_("unknown option '-fplugin-arg-%s-%s'"), plugin_name, argv[i].key);
+	}
+
+	if (strlen(randstruct_seed) != 64) {
+		error(G_("invalid seed value supplied for %s plugin"), plugin_name);
+		return 1;
+	}
+	obtained_seed = sscanf(randstruct_seed, "%016llx%016llx%016llx%016llx",
+		&shuffle_seed[0], &shuffle_seed[1], &shuffle_seed[2], &shuffle_seed[3]);
+	if (obtained_seed != 4) {
+		error(G_("Invalid seed supplied for %s plugin"), plugin_name);
+		return 1;
+	}
+
+	register_callback(plugin_name, PLUGIN_INFO, NULL, &randomize_layout_plugin_info);
+	if (enable) {
+		register_callback(plugin_name, PLUGIN_ALL_IPA_PASSES_START, check_global_variables, NULL);
+		register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &find_bad_casts_pass_info);
+		register_callback(plugin_name, PLUGIN_FINISH_TYPE, finish_type, NULL);
+		register_callback(plugin_name, PLUGIN_FINISH_DECL, randomize_layout_finish_decl, NULL);
+	}
+	register_callback(plugin_name, PLUGIN_ATTRIBUTES, register_attributes, NULL);
+
+	return 0;
+}
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v2 05/20] randstruct: Whitelist struct security_hook_heads cast
  2017-05-26 20:17 [PATCH v2 00/20] Introduce struct layout randomization plugin Kees Cook
                   ` (3 preceding siblings ...)
  2017-05-26 20:17 ` [PATCH v2 04/20] gcc-plugins: Add the randstruct plugin Kees Cook
@ 2017-05-26 20:17 ` Kees Cook
  2017-05-27  8:41   ` Christoph Hellwig
  2017-05-26 20:17 ` [PATCH v2 06/20] randstruct: Whitelist UNIXCB cast Kees Cook
                   ` (14 subsequent siblings)
  19 siblings, 1 reply; 55+ messages in thread
From: Kees Cook @ 2017-05-26 20:17 UTC (permalink / raw)
  To: kernel-hardening
  Cc: Kees Cook, Tetsuo Handa, James Morris, Laura Abbott, x86, linux-kernel

The LSM initialization routines walk security_hook_heads as an array
of struct list_head instead of via names to avoid a ton of needless
source. Whitelist this to avoid the false positive warning from the
plugin:

security/security.c: In function ‘security_init’:
security/security.c:59:20: note: found mismatched op0 struct pointer types: ‘struct list_head’ and ‘struct security_hook_heads’

  struct list_head *list = (struct list_head *) &security_hook_heads;
                    ^

Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Cc: James Morris <james.l.morris@oracle.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 scripts/gcc-plugins/randomize_layout_plugin.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/scripts/gcc-plugins/randomize_layout_plugin.c b/scripts/gcc-plugins/randomize_layout_plugin.c
index bccbec2af0e4..e126ac7874af 100644
--- a/scripts/gcc-plugins/randomize_layout_plugin.c
+++ b/scripts/gcc-plugins/randomize_layout_plugin.c
@@ -43,6 +43,8 @@ struct whitelist_entry {
 };
 
 static const struct whitelist_entry whitelist[] = {
+	/* walk struct security_hook_heads as an array of struct list_head */
+	{ "security/security.c", "list_head", "security_hook_heads" },
 	{ }
 };
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v2 06/20] randstruct: Whitelist UNIXCB cast
  2017-05-26 20:17 [PATCH v2 00/20] Introduce struct layout randomization plugin Kees Cook
                   ` (4 preceding siblings ...)
  2017-05-26 20:17 ` [PATCH v2 05/20] randstruct: Whitelist struct security_hook_heads cast Kees Cook
@ 2017-05-26 20:17 ` Kees Cook
  2017-05-26 20:20   ` Kees Cook
  2017-05-28  7:56   ` Christoph Hellwig
  2017-05-26 20:17 ` [PATCH v2 07/20] randstruct: Whitelist big_key path struct overloading Kees Cook
                   ` (13 subsequent siblings)
  19 siblings, 2 replies; 55+ messages in thread
From: Kees Cook @ 2017-05-26 20:17 UTC (permalink / raw)
  To: kernel-hardening
  Cc: Kees Cook, Hannes Frederic Sowa,
	Signed-off-by : David S . Miller, Laura Abbott, x86,
	linux-kernel

This is another false positive in bad cast detection:

net/unix/af_unix.c: In function ‘unix_skb_scm_eq’:
net/unix/af_unix.c:1621:31: note: found mismatched rhs struct pointer types: ‘struct unix_skb_parms’ and ‘char’

  const struct unix_skb_parms *u = &UNIXCB(skb);
                               ^

UNIXCB is:

	#define UNIXCB(skb)     (*(struct unix_skb_parms *)&((skb)->cb))

And ->cb is:

	char                    cb[48] __aligned(8);

This is a rather crazy cast, but appears to be safe in the face of
randomization, so whitelist it in the plugin.

Cc: Hannes Frederic Sowa <hannes@stressinduktion.org>
Cc: Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 scripts/gcc-plugins/randomize_layout_plugin.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/scripts/gcc-plugins/randomize_layout_plugin.c b/scripts/gcc-plugins/randomize_layout_plugin.c
index e126ac7874af..bf110915a5aa 100644
--- a/scripts/gcc-plugins/randomize_layout_plugin.c
+++ b/scripts/gcc-plugins/randomize_layout_plugin.c
@@ -43,6 +43,8 @@ struct whitelist_entry {
 };
 
 static const struct whitelist_entry whitelist[] = {
+	/* unix_skb_parms via UNIXCB() buffer */
+	{ "net/unix/af_unix.c", "unix_skb_parms", "char" },
 	/* walk struct security_hook_heads as an array of struct list_head */
 	{ "security/security.c", "list_head", "security_hook_heads" },
 	{ }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v2 07/20] randstruct: Whitelist big_key path struct overloading
  2017-05-26 20:17 [PATCH v2 00/20] Introduce struct layout randomization plugin Kees Cook
                   ` (5 preceding siblings ...)
  2017-05-26 20:17 ` [PATCH v2 06/20] randstruct: Whitelist UNIXCB cast Kees Cook
@ 2017-05-26 20:17 ` Kees Cook
  2017-05-28  8:12   ` Christoph Hellwig
  2017-05-26 20:17 ` [PATCH v2 08/20] randstruct: Whitelist NIU struct page overloading Kees Cook
                   ` (12 subsequent siblings)
  19 siblings, 1 reply; 55+ messages in thread
From: Kees Cook @ 2017-05-26 20:17 UTC (permalink / raw)
  To: kernel-hardening
  Cc: Kees Cook, David Howells, Laura Abbott, x86, linux-kernel

The big_key payload structure intentionally stores a struct path in
two void pointers to avoid header soup. Whitelist this case:

security/keys/big_key.c: In function ‘big_key_read’:
security/keys/big_key.c:293:16: note: found mismatched rhs struct pointer types: ‘struct path’ and ‘void *’

   struct path *path = (struct path *)&key->payload.data[big_key_path];
                ^~~~

Cc: David Howells <dhowells@redhat.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 scripts/gcc-plugins/randomize_layout_plugin.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/scripts/gcc-plugins/randomize_layout_plugin.c b/scripts/gcc-plugins/randomize_layout_plugin.c
index bf110915a5aa..5f4e59a78eeb 100644
--- a/scripts/gcc-plugins/randomize_layout_plugin.c
+++ b/scripts/gcc-plugins/randomize_layout_plugin.c
@@ -45,6 +45,8 @@ struct whitelist_entry {
 static const struct whitelist_entry whitelist[] = {
 	/* 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 list_head */
 	{ "security/security.c", "list_head", "security_hook_heads" },
 	{ }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v2 08/20] randstruct: Whitelist NIU struct page overloading
  2017-05-26 20:17 [PATCH v2 00/20] Introduce struct layout randomization plugin Kees Cook
                   ` (6 preceding siblings ...)
  2017-05-26 20:17 ` [PATCH v2 07/20] randstruct: Whitelist big_key path struct overloading Kees Cook
@ 2017-05-26 20:17 ` Kees Cook
  2017-05-28  8:15   ` Christoph Hellwig
  2017-05-26 20:17 ` [PATCH v2 09/20] randstruct: Mark various structs for randomization Kees Cook
                   ` (11 subsequent siblings)
  19 siblings, 1 reply; 55+ messages in thread
From: Kees Cook @ 2017-05-26 20:17 UTC (permalink / raw)
  To: kernel-hardening
  Cc: Kees Cook, David S . Miller, Laura Abbott, x86, linux-kernel

The NIU ethernet driver intentionally stores a page struct pointer on
top of the "mapping" field. Whitelist this case:

drivers/net/ethernet/sun/niu.c: In function ‘niu_rx_pkt_ignore’:
drivers/net/ethernet/sun/niu.c:3402:10: note: found mismatched ssa struct pointer types: ‘struct page’ and ‘struct address_space’

    *link = (struct page *) page->mapping;
    ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Cc: David S. Miller <davem@davemloft.net>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 scripts/gcc-plugins/randomize_layout_plugin.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/scripts/gcc-plugins/randomize_layout_plugin.c b/scripts/gcc-plugins/randomize_layout_plugin.c
index 5f4e59a78eeb..f777ead58ba8 100644
--- a/scripts/gcc-plugins/randomize_layout_plugin.c
+++ b/scripts/gcc-plugins/randomize_layout_plugin.c
@@ -43,6 +43,8 @@ struct whitelist_entry {
 };
 
 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 */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v2 09/20] randstruct: Mark various structs for randomization
  2017-05-26 20:17 [PATCH v2 00/20] Introduce struct layout randomization plugin Kees Cook
                   ` (7 preceding siblings ...)
  2017-05-26 20:17 ` [PATCH v2 08/20] randstruct: Whitelist NIU struct page overloading Kees Cook
@ 2017-05-26 20:17 ` Kees Cook
  2017-05-26 20:17 ` [PATCH v2 10/20] randstruct: opt-out externally exposed function pointer structs Kees Cook
                   ` (10 subsequent siblings)
  19 siblings, 0 replies; 55+ messages in thread
From: Kees Cook @ 2017-05-26 20:17 UTC (permalink / raw)
  To: kernel-hardening; +Cc: Kees Cook, Laura Abbott, x86, linux-kernel

This marks many critical kernel structures for randomization. These are
structures that have been targeted in the past in security exploits, or
contain functions pointers, pointers to function pointer tables, lists,
workqueues, ref-counters, credentials, permissions, or are otherwise
sensitive. This initial list was extracted from grsecurity.

Left out of this list is task_struct, which requires special handling
and is covered in a subsequent patch.

Signed-off-by: Kees Cook <keescook@chromium.org>
---
 arch/x86/include/asm/processor.h |  2 +-
 fs/mount.h                       |  4 ++--
 fs/namei.c                       |  2 +-
 fs/proc/internal.h               |  6 +++---
 include/linux/binfmts.h          |  4 ++--
 include/linux/cdev.h             |  2 +-
 include/linux/cred.h             |  4 ++--
 include/linux/dcache.h           |  2 +-
 include/linux/fs.h               | 17 +++++++++--------
 include/linux/fs_struct.h        |  2 +-
 include/linux/ipc.h              |  2 +-
 include/linux/ipc_namespace.h    |  2 +-
 include/linux/key-type.h         |  4 ++--
 include/linux/kmod.h             |  2 +-
 include/linux/kobject.h          |  2 +-
 include/linux/lsm_hooks.h        |  4 ++--
 include/linux/mm_types.h         |  4 ++--
 include/linux/module.h           |  4 ++--
 include/linux/mount.h            |  2 +-
 include/linux/msg.h              |  2 +-
 include/linux/path.h             |  2 +-
 include/linux/pid_namespace.h    |  2 +-
 include/linux/proc_ns.h          |  2 +-
 include/linux/sched.h            |  2 +-
 include/linux/sched/signal.h     |  2 +-
 include/linux/sem.h              |  2 +-
 include/linux/shm.h              |  2 +-
 include/linux/sysctl.h           |  2 +-
 include/linux/tty.h              |  2 +-
 include/linux/tty_driver.h       |  4 ++--
 include/linux/user_namespace.h   |  2 +-
 include/linux/utsname.h          |  2 +-
 include/net/af_unix.h            |  2 +-
 include/net/neighbour.h          |  2 +-
 include/net/net_namespace.h      |  2 +-
 include/net/sock.h               |  2 +-
 kernel/futex.c                   |  4 ++--
 security/keys/internal.h         |  2 +-
 38 files changed, 57 insertions(+), 56 deletions(-)

diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 3cada998a402..e2335edb9fc5 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -129,7 +129,7 @@ struct cpuinfo_x86 {
 	/* Index into per_cpu list: */
 	u16			cpu_index;
 	u32			microcode;
-};
+} __randomize_layout;
 
 struct cpuid_regs {
 	u32 eax, ebx, ecx, edx;
diff --git a/fs/mount.h b/fs/mount.h
index de45d9e76748..6790767d1883 100644
--- a/fs/mount.h
+++ b/fs/mount.h
@@ -16,7 +16,7 @@ struct mnt_namespace {
 	u64 event;
 	unsigned int		mounts; /* # of mounts in the namespace */
 	unsigned int		pending_mounts;
-};
+} __randomize_layout;
 
 struct mnt_pcp {
 	int mnt_count;
@@ -69,7 +69,7 @@ struct mount {
 	struct hlist_head mnt_pins;
 	struct fs_pin mnt_umount;
 	struct dentry *mnt_ex_mountpoint;
-};
+} __randomize_layout;
 
 #define MNT_NS_INTERNAL ERR_PTR(-EINVAL) /* distinct from any mnt_namespace */
 
diff --git a/fs/namei.c b/fs/namei.c
index bbb9d01e70e7..9db9c5418d90 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -524,7 +524,7 @@ struct nameidata {
 	struct inode	*link_inode;
 	unsigned	root_seq;
 	int		dfd;
-};
+} __randomize_layout;
 
 static void set_nameidata(struct nameidata *p, int dfd, struct filename *name)
 {
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index c5ae09b6c726..07b16318223f 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -51,7 +51,7 @@ struct proc_dir_entry {
 	spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */
 	u8 namelen;
 	char name[];
-};
+} __randomize_layout;
 
 union proc_op {
 	int (*proc_get_link)(struct dentry *, struct path *);
@@ -70,7 +70,7 @@ struct proc_inode {
 	struct list_head sysctl_inodes;
 	const struct proc_ns_operations *ns_ops;
 	struct inode vfs_inode;
-};
+} __randomize_layout;
 
 /*
  * General functions
@@ -279,7 +279,7 @@ struct proc_maps_private {
 #ifdef CONFIG_NUMA
 	struct mempolicy *task_mempolicy;
 #endif
-};
+} __randomize_layout;
 
 struct mm_struct *proc_mem_open(struct inode *inode, unsigned int mode);
 
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index 05488da3aee9..3ae9013eeaaa 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -46,7 +46,7 @@ struct linux_binprm {
 	unsigned interp_flags;
 	unsigned interp_data;
 	unsigned long loader, exec;
-};
+} __randomize_layout;
 
 #define BINPRM_FLAGS_ENFORCE_NONDUMP_BIT 0
 #define BINPRM_FLAGS_ENFORCE_NONDUMP (1 << BINPRM_FLAGS_ENFORCE_NONDUMP_BIT)
@@ -81,7 +81,7 @@ struct linux_binfmt {
 	int (*load_shlib)(struct file *);
 	int (*core_dump)(struct coredump_params *cprm);
 	unsigned long min_coredump;	/* minimal dump size */
-};
+} __randomize_layout;
 
 extern void __register_binfmt(struct linux_binfmt *fmt, int insert);
 
diff --git a/include/linux/cdev.h b/include/linux/cdev.h
index 408bc09ce497..cb28eb21e3ca 100644
--- a/include/linux/cdev.h
+++ b/include/linux/cdev.h
@@ -17,7 +17,7 @@ struct cdev {
 	struct list_head list;
 	dev_t dev;
 	unsigned int count;
-};
+} __randomize_layout;
 
 void cdev_init(struct cdev *, const struct file_operations *);
 
diff --git a/include/linux/cred.h b/include/linux/cred.h
index c728d515e5e2..099058e1178b 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -31,7 +31,7 @@ struct group_info {
 	atomic_t	usage;
 	int		ngroups;
 	kgid_t		gid[0];
-};
+} __randomize_layout;
 
 /**
  * get_group_info - Get a reference to a group info structure
@@ -145,7 +145,7 @@ struct cred {
 	struct user_namespace *user_ns; /* user_ns the caps and keyrings are relative to. */
 	struct group_info *group_info;	/* supplementary groups for euid/fsgid */
 	struct rcu_head	rcu;		/* RCU deletion hook */
-};
+} __randomize_layout;
 
 extern void __put_cred(struct cred *);
 extern void exit_creds(struct task_struct *);
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index d2e38dc6172c..7eb262e13d3c 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -113,7 +113,7 @@ struct dentry {
 		struct hlist_bl_node d_in_lookup_hash;	/* only for in-lookup ones */
 	 	struct rcu_head d_rcu;
 	} d_u;
-};
+} __randomize_layout;
 
 /*
  * dentry->d_lock spinlock nesting subclasses:
diff --git a/include/linux/fs.h b/include/linux/fs.h
index aa4affb38c39..f1798a4c0cfc 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -275,7 +275,7 @@ struct kiocb {
 	void (*ki_complete)(struct kiocb *iocb, long ret, long ret2);
 	void			*private;
 	int			ki_flags;
-};
+} __randomize_layout;
 
 static inline bool is_sync_kiocb(struct kiocb *kiocb)
 {
@@ -392,7 +392,7 @@ struct address_space {
 	gfp_t			gfp_mask;	/* implicit gfp mask for allocations */
 	struct list_head	private_list;	/* ditto */
 	void			*private_data;	/* ditto */
-} __attribute__((aligned(sizeof(long))));
+} __attribute__((aligned(sizeof(long)))) __randomize_layout;
 	/*
 	 * On most architectures that alignment is already the case; but
 	 * must be enforced here for CRIS, to let the least significant bit
@@ -435,7 +435,7 @@ struct block_device {
 	int			bd_fsfreeze_count;
 	/* Mutex for freeze */
 	struct mutex		bd_fsfreeze_mutex;
-};
+} __randomize_layout;
 
 /*
  * Radix-tree tags, for tagging dirty and writeback pages within the pagecache
@@ -653,7 +653,7 @@ struct inode {
 #endif
 
 	void			*i_private; /* fs or device private pointer */
-};
+} __randomize_layout;
 
 static inline unsigned int i_blocksize(const struct inode *node)
 {
@@ -868,7 +868,8 @@ struct file {
 	struct list_head	f_tfile_llink;
 #endif /* #ifdef CONFIG_EPOLL */
 	struct address_space	*f_mapping;
-} __attribute__((aligned(4)));	/* lest something weird decides that 2 is OK */
+} __randomize_layout
+  __attribute__((aligned(4)));	/* lest something weird decides that 2 is OK */
 
 struct file_handle {
 	__u32 handle_bytes;
@@ -1005,7 +1006,7 @@ struct file_lock {
 			int state;		/* state of grant or error if -ve */
 		} afs;
 	} fl_u;
-};
+} __randomize_layout;
 
 struct file_lock_context {
 	spinlock_t		flc_lock;
@@ -1404,7 +1405,7 @@ struct super_block {
 
 	spinlock_t		s_inode_wblist_lock;
 	struct list_head	s_inodes_wb;	/* writeback inodes */
-};
+} __randomize_layout;
 
 /* Helper functions so that in most cases filesystems will
  * not need to deal directly with kuid_t and kgid_t and can
@@ -1690,7 +1691,7 @@ struct file_operations {
 			u64);
 	ssize_t (*dedupe_file_range)(struct file *, u64, u64, struct file *,
 			u64);
-};
+} __randomize_layout;
 
 struct inode_operations {
 	struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int);
diff --git a/include/linux/fs_struct.h b/include/linux/fs_struct.h
index 0efc3e62843a..7a026240cbb1 100644
--- a/include/linux/fs_struct.h
+++ b/include/linux/fs_struct.h
@@ -12,7 +12,7 @@ struct fs_struct {
 	int umask;
 	int in_exec;
 	struct path root, pwd;
-};
+} __randomize_layout;
 
 extern struct kmem_cache *fs_cachep;
 
diff --git a/include/linux/ipc.h b/include/linux/ipc.h
index 71fd92d81b26..ea0eb0b5f98c 100644
--- a/include/linux/ipc.h
+++ b/include/linux/ipc.h
@@ -20,6 +20,6 @@ struct kern_ipc_perm {
 	umode_t		mode;
 	unsigned long	seq;
 	void		*security;
-} ____cacheline_aligned_in_smp;
+} ____cacheline_aligned_in_smp __randomize_layout;
 
 #endif /* _LINUX_IPC_H */
diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h
index 848e5796400e..65327ee0936b 100644
--- a/include/linux/ipc_namespace.h
+++ b/include/linux/ipc_namespace.h
@@ -61,7 +61,7 @@ struct ipc_namespace {
 	struct ucounts *ucounts;
 
 	struct ns_common ns;
-};
+} __randomize_layout;
 
 extern struct ipc_namespace init_ipc_ns;
 extern spinlock_t mq_lock;
diff --git a/include/linux/key-type.h b/include/linux/key-type.h
index 8496cf64575c..9520fc3c3b9a 100644
--- a/include/linux/key-type.h
+++ b/include/linux/key-type.h
@@ -45,7 +45,7 @@ struct key_preparsed_payload {
 	size_t		datalen;	/* Raw datalen */
 	size_t		quotalen;	/* Quota length for proposed payload */
 	time_t		expiry;		/* Expiry time of key */
-};
+} __randomize_layout;
 
 typedef int (*request_key_actor_t)(struct key_construction *key,
 				   const char *op, void *aux);
@@ -158,7 +158,7 @@ struct key_type {
 	/* internal fields */
 	struct list_head	link;		/* link in types list */
 	struct lock_class_key	lock_class;	/* key->sem lock class */
-};
+} __randomize_layout;
 
 extern struct key_type key_type_keyring;
 
diff --git a/include/linux/kmod.h b/include/linux/kmod.h
index c4e441e00db5..655082c88fd9 100644
--- a/include/linux/kmod.h
+++ b/include/linux/kmod.h
@@ -64,7 +64,7 @@ struct subprocess_info {
 	int (*init)(struct subprocess_info *info, struct cred *new);
 	void (*cleanup)(struct subprocess_info *info);
 	void *data;
-};
+} __randomize_layout;
 
 extern int
 call_usermodehelper(const char *path, char **argv, char **envp, int wait);
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index ca85cb80e99a..084513350317 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -172,7 +172,7 @@ struct kset {
 	spinlock_t list_lock;
 	struct kobject kobj;
 	const struct kset_uevent_ops *uevent_ops;
-};
+} __randomize_layout;
 
 extern void kset_init(struct kset *kset);
 extern int __must_check kset_register(struct kset *kset);
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index f7914d96e1d7..8c1182fcc6d2 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -1910,7 +1910,7 @@ struct security_hook_heads {
 	struct list_head audit_rule_match;
 	struct list_head audit_rule_free;
 #endif /* CONFIG_AUDIT */
-};
+} __randomize_layout;
 
 /*
  * Security module hook list structure.
@@ -1921,7 +1921,7 @@ struct security_hook_list {
 	struct list_head		*head;
 	union security_list_options	hook;
 	char				*lsm;
-};
+} __randomize_layout;
 
 /*
  * Initializing a security_hook_list structure takes
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 45cdb27791a3..ff151814a02d 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -342,7 +342,7 @@ struct vm_area_struct {
 	struct mempolicy *vm_policy;	/* NUMA policy for the VMA */
 #endif
 	struct vm_userfaultfd_ctx vm_userfaultfd_ctx;
-};
+} __randomize_layout;
 
 struct core_thread {
 	struct task_struct *task;
@@ -500,7 +500,7 @@ struct mm_struct {
 	atomic_long_t hugetlb_usage;
 #endif
 	struct work_struct async_put_work;
-};
+} __randomize_layout;
 
 extern struct mm_struct init_mm;
 
diff --git a/include/linux/module.h b/include/linux/module.h
index 21f56393602f..d93111d7def6 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -45,7 +45,7 @@ struct module_kobject {
 	struct kobject *drivers_dir;
 	struct module_param_attrs *mp;
 	struct completion *kobj_completion;
-};
+} __randomize_layout;
 
 struct module_attribute {
 	struct attribute attr;
@@ -475,7 +475,7 @@ struct module {
 	ctor_fn_t *ctors;
 	unsigned int num_ctors;
 #endif
-} ____cacheline_aligned;
+} ____cacheline_aligned __randomize_layout;
 #ifndef MODULE_ARCH_INIT
 #define MODULE_ARCH_INIT {}
 #endif
diff --git a/include/linux/mount.h b/include/linux/mount.h
index 8e0352af06b7..1ce85e6fd95f 100644
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -67,7 +67,7 @@ struct vfsmount {
 	struct dentry *mnt_root;	/* root of the mounted tree */
 	struct super_block *mnt_sb;	/* pointer to superblock */
 	int mnt_flags;
-};
+} __randomize_layout;
 
 struct file; /* forward dec */
 struct path;
diff --git a/include/linux/msg.h b/include/linux/msg.h
index f3f302f9c197..a001305f5a79 100644
--- a/include/linux/msg.h
+++ b/include/linux/msg.h
@@ -29,7 +29,7 @@ struct msg_queue {
 	struct list_head q_messages;
 	struct list_head q_receivers;
 	struct list_head q_senders;
-};
+} __randomize_layout;
 
 /* Helper routines for sys_msgsnd and sys_msgrcv */
 extern long do_msgsnd(int msqid, long mtype, void __user *mtext,
diff --git a/include/linux/path.h b/include/linux/path.h
index d1372186f431..cde895cc4af4 100644
--- a/include/linux/path.h
+++ b/include/linux/path.h
@@ -7,7 +7,7 @@ struct vfsmount;
 struct path {
 	struct vfsmount *mnt;
 	struct dentry *dentry;
-};
+} __randomize_layout;
 
 extern void path_get(const struct path *);
 extern void path_put(const struct path *);
diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h
index c2a989dee876..b09136f88cf4 100644
--- a/include/linux/pid_namespace.h
+++ b/include/linux/pid_namespace.h
@@ -52,7 +52,7 @@ struct pid_namespace {
 	int hide_pid;
 	int reboot;	/* group exit code if this pidns was rebooted */
 	struct ns_common ns;
-};
+} __randomize_layout;
 
 extern struct pid_namespace init_pid_ns;
 
diff --git a/include/linux/proc_ns.h b/include/linux/proc_ns.h
index 58ab28d81fc2..06844b54dfc1 100644
--- a/include/linux/proc_ns.h
+++ b/include/linux/proc_ns.h
@@ -21,7 +21,7 @@ struct proc_ns_operations {
 	int (*install)(struct nsproxy *nsproxy, struct ns_common *ns);
 	struct user_namespace *(*owner)(struct ns_common *ns);
 	struct ns_common *(*get_parent)(struct ns_common *ns);
-};
+} __randomize_layout;
 
 extern const struct proc_ns_operations netns_operations;
 extern const struct proc_ns_operations utsns_operations;
diff --git a/include/linux/sched.h b/include/linux/sched.h
index c5338510628a..b1298ad4da63 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -408,7 +408,7 @@ struct sched_rt_entity {
 	/* rq "owned" by this entity/group: */
 	struct rt_rq			*my_q;
 #endif
-};
+} __randomize_layout;
 
 struct sched_dl_entity {
 	struct rb_node			rb_node;
diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h
index c06d63b3a583..2a0dd40b15db 100644
--- a/include/linux/sched/signal.h
+++ b/include/linux/sched/signal.h
@@ -222,7 +222,7 @@ struct signal_struct {
 	struct mutex cred_guard_mutex;	/* guard against foreign influences on
 					 * credential calculations
 					 * (notably. ptrace) */
-};
+} __randomize_layout;
 
 /*
  * Bits in flags field of signal_struct.
diff --git a/include/linux/sem.h b/include/linux/sem.h
index fc7af8eaa527..a4dddb20a697 100644
--- a/include/linux/sem.h
+++ b/include/linux/sem.h
@@ -41,7 +41,7 @@ struct sem_array {
 	unsigned int		use_global_lock;/* >0: global lock required */
 
 	struct sem		sems[0];
-};
+} __randomize_layout;
 
 #ifdef CONFIG_SYSVIPC
 
diff --git a/include/linux/shm.h b/include/linux/shm.h
index 04e881829625..0fb7061ec54c 100644
--- a/include/linux/shm.h
+++ b/include/linux/shm.h
@@ -22,7 +22,7 @@ struct shmid_kernel /* private to the kernel */
 	/* The task created the shm object.  NULL if the task is dead. */
 	struct task_struct	*shm_creator;
 	struct list_head	shm_clist;	/* list by creator */
-};
+} __randomize_layout;
 
 /* shm_mode upper byte flags */
 #define	SHM_DEST	01000	/* segment will be destroyed on last detach */
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 80d07816def0..9ddeef2c03e2 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -117,7 +117,7 @@ struct ctl_table
 	struct ctl_table_poll *poll;
 	void *extra1;
 	void *extra2;
-};
+} __randomize_layout;
 
 struct ctl_node {
 	struct rb_node node;
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 5c3f01f49b10..99ecb38bac04 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -333,7 +333,7 @@ struct tty_struct {
 	/* If the tty has a pending do_SAK, queue it here - akpm */
 	struct work_struct SAK_work;
 	struct tty_port *port;
-};
+} __randomize_layout;
 
 /* Each of a tty's open files has private_data pointing to tty_file_private */
 struct tty_file_private {
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h
index b742b5e47cc2..00b2213f6a35 100644
--- a/include/linux/tty_driver.h
+++ b/include/linux/tty_driver.h
@@ -291,7 +291,7 @@ struct tty_operations {
 	void (*poll_put_char)(struct tty_driver *driver, int line, char ch);
 #endif
 	const struct file_operations *proc_fops;
-};
+} __randomize_layout;
 
 struct tty_driver {
 	int	magic;		/* magic number for this structure */
@@ -325,7 +325,7 @@ struct tty_driver {
 
 	const struct tty_operations *ops;
 	struct list_head tty_drivers;
-};
+} __randomize_layout;
 
 extern struct list_head tty_drivers;
 
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index 32354b4b4b2b..b3575ce29148 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -66,7 +66,7 @@ struct user_namespace {
 #endif
 	struct ucounts		*ucounts;
 	int ucount_max[UCOUNT_COUNTS];
-};
+} __randomize_layout;
 
 struct ucounts {
 	struct hlist_node node;
diff --git a/include/linux/utsname.h b/include/linux/utsname.h
index 60f0bb83b313..da826ed059cf 100644
--- a/include/linux/utsname.h
+++ b/include/linux/utsname.h
@@ -26,7 +26,7 @@ struct uts_namespace {
 	struct user_namespace *user_ns;
 	struct ucounts *ucounts;
 	struct ns_common ns;
-};
+} __randomize_layout;
 extern struct uts_namespace init_uts_ns;
 
 #ifdef CONFIG_UTS_NS
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index fd60eccb59a6..64e2a1e24a2c 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -36,7 +36,7 @@ struct unix_skb_parms {
 	u32			secid;		/* Security ID		*/
 #endif
 	u32			consumed;
-};
+} __randomize_layout;
 
 #define UNIXCB(skb) 	(*(struct unix_skb_parms *)&((skb)->cb))
 
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index e4dd3a214034..a62959d2b3f7 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -155,7 +155,7 @@ struct neighbour {
 	struct rcu_head		rcu;
 	struct net_device	*dev;
 	u8			primary_key[0];
-};
+} __randomize_layout;
 
 struct neigh_ops {
 	int			family;
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index fe80bb48ab1f..a224196d16ac 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -147,7 +147,7 @@ struct net {
 #endif
 	struct sock		*diag_nlsk;
 	atomic_t		fnhe_genid;
-};
+} __randomize_layout;
 
 #include <linux/seq_file_net.h>
 
diff --git a/include/net/sock.h b/include/net/sock.h
index 12b2912de420..1b035dbb95d9 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1120,7 +1120,7 @@ struct proto {
 	atomic_t		socks;
 #endif
 	int			(*diag_destroy)(struct sock *sk, int err);
-};
+} __randomize_layout;
 
 int proto_register(struct proto *prot, int alloc_slab);
 void proto_unregister(struct proto *prot);
diff --git a/kernel/futex.c b/kernel/futex.c
index b8ae87d227da..0a865bc119c6 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -212,7 +212,7 @@ struct futex_pi_state {
 	atomic_t refcount;
 
 	union futex_key key;
-};
+} __randomize_layout;
 
 /**
  * struct futex_q - The hashed futex queue entry, one per waiting task
@@ -246,7 +246,7 @@ struct futex_q {
 	struct rt_mutex_waiter *rt_waiter;
 	union futex_key *requeue_pi_key;
 	u32 bitset;
-};
+} __randomize_layout;
 
 static const struct futex_q futex_q_init = {
 	/* list gets initialized in queue_me()*/
diff --git a/security/keys/internal.h b/security/keys/internal.h
index c0f8682eba69..6494954e9980 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -197,7 +197,7 @@ struct request_key_auth {
 	void			*callout_info;
 	size_t			callout_len;
 	pid_t			pid;
-};
+} __randomize_layout;
 
 extern struct key_type key_type_request_key_auth;
 extern struct key *request_key_auth_new(struct key *target,
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v2 10/20] randstruct: opt-out externally exposed function pointer structs
  2017-05-26 20:17 [PATCH v2 00/20] Introduce struct layout randomization plugin Kees Cook
                   ` (8 preceding siblings ...)
  2017-05-26 20:17 ` [PATCH v2 09/20] randstruct: Mark various structs for randomization Kees Cook
@ 2017-05-26 20:17 ` Kees Cook
  2017-05-26 20:17 ` [PATCH v2 11/20] randstruct: Disable randomization of ACPICA structs Kees Cook
                   ` (9 subsequent siblings)
  19 siblings, 0 replies; 55+ messages in thread
From: Kees Cook @ 2017-05-26 20:17 UTC (permalink / raw)
  To: kernel-hardening; +Cc: Kees Cook, Laura Abbott, x86, linux-kernel

Some function pointer structures are used externally to the kernel, like
the paravirt structures. These should never be randomized, so mark them as
such. This set was extracted from grsecurity.

Signed-off-by: Kees Cook <keescook@chromium.org>
---
 arch/arm/include/asm/cacheflush.h     |  2 +-
 arch/x86/include/asm/paravirt_types.h | 16 ++++++++--------
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h
index d69bebf697e7..74504b154256 100644
--- a/arch/arm/include/asm/cacheflush.h
+++ b/arch/arm/include/asm/cacheflush.h
@@ -116,7 +116,7 @@ struct cpu_cache_fns {
 	void (*dma_unmap_area)(const void *, size_t, int);
 
 	void (*dma_flush_range)(const void *, const void *);
-};
+} __no_randomize_layout;
 
 /*
  * Select the calling method
diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h
index 7465d6fe336f..96c7e3cf43fa 100644
--- a/arch/x86/include/asm/paravirt_types.h
+++ b/arch/x86/include/asm/paravirt_types.h
@@ -83,7 +83,7 @@ struct pv_init_ops {
 	 */
 	unsigned (*patch)(u8 type, u16 clobber, void *insnbuf,
 			  unsigned long addr, unsigned len);
-};
+} __no_randomize_layout;
 
 
 struct pv_lazy_ops {
@@ -91,12 +91,12 @@ struct pv_lazy_ops {
 	void (*enter)(void);
 	void (*leave)(void);
 	void (*flush)(void);
-};
+} __no_randomize_layout;
 
 struct pv_time_ops {
 	unsigned long long (*sched_clock)(void);
 	unsigned long long (*steal_clock)(int cpu);
-};
+} __no_randomize_layout;
 
 struct pv_cpu_ops {
 	/* hooks for various privileged instructions */
@@ -175,7 +175,7 @@ struct pv_cpu_ops {
 
 	void (*start_context_switch)(struct task_struct *prev);
 	void (*end_context_switch)(struct task_struct *next);
-};
+} __no_randomize_layout;
 
 struct pv_irq_ops {
 	/*
@@ -198,7 +198,7 @@ struct pv_irq_ops {
 #ifdef CONFIG_X86_64
 	void (*adjust_exception_frame)(void);
 #endif
-};
+} __no_randomize_layout;
 
 struct pv_mmu_ops {
 	unsigned long (*read_cr2)(void);
@@ -306,7 +306,7 @@ struct pv_mmu_ops {
 	   an mfn.  We can tell which is which from the index. */
 	void (*set_fixmap)(unsigned /* enum fixed_addresses */ idx,
 			   phys_addr_t phys, pgprot_t flags);
-};
+} __no_randomize_layout;
 
 struct arch_spinlock;
 #ifdef CONFIG_SMP
@@ -323,7 +323,7 @@ struct pv_lock_ops {
 	void (*kick)(int cpu);
 
 	struct paravirt_callee_save vcpu_is_preempted;
-};
+} __no_randomize_layout;
 
 /* This contains all the paravirt structures: we get a convenient
  * number for each function using the offset which we use to indicate
@@ -335,7 +335,7 @@ struct paravirt_patch_template {
 	struct pv_irq_ops pv_irq_ops;
 	struct pv_mmu_ops pv_mmu_ops;
 	struct pv_lock_ops pv_lock_ops;
-};
+} __no_randomize_layout;
 
 extern struct pv_info pv_info;
 extern struct pv_init_ops pv_init_ops;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v2 11/20] randstruct: Disable randomization of ACPICA structs
  2017-05-26 20:17 [PATCH v2 00/20] Introduce struct layout randomization plugin Kees Cook
                   ` (9 preceding siblings ...)
  2017-05-26 20:17 ` [PATCH v2 10/20] randstruct: opt-out externally exposed function pointer structs Kees Cook
@ 2017-05-26 20:17 ` Kees Cook
  2017-05-27  8:42   ` Christoph Hellwig
  2017-05-26 20:17 ` [PATCH v2 12/20] sgi-xp: Use designated initializers Kees Cook
                   ` (8 subsequent siblings)
  19 siblings, 1 reply; 55+ messages in thread
From: Kees Cook @ 2017-05-26 20:17 UTC (permalink / raw)
  To: kernel-hardening; +Cc: Kees Cook, Laura Abbott, x86, linux-kernel

Since the ACPICA source is maintained externally to the kernel, we can
neither switch it to designated initializers nor mark it
__no_randomize_layout. Until ACPICA-upstream changes[1] land to handle the
designated initialization, explicitly skip it in the plugin.

[1] https://github.com/acpica/acpica/pull/248

Signed-off-by: Kees Cook <keescook@chromium.org>
---
 scripts/gcc-plugins/randomize_layout_plugin.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/scripts/gcc-plugins/randomize_layout_plugin.c b/scripts/gcc-plugins/randomize_layout_plugin.c
index f777ead58ba8..e6e02a40d522 100644
--- a/scripts/gcc-plugins/randomize_layout_plugin.c
+++ b/scripts/gcc-plugins/randomize_layout_plugin.c
@@ -346,6 +346,10 @@ static int relayout_struct(tree type)
 	    !strcmp((const char *)ORIG_TYPE_NAME(type), "RAWPCIFACTORY"))
 		return 0;
 
+	/* Skip ACPICA structs until refreshed with designated_init. */
+	if (!strcmp((const char *)ORIG_TYPE_NAME(type), "acpi_sleep_functions"))
+		return 0;
+
 	/* throw out any structs in uapi */
 	xloc = expand_location(DECL_SOURCE_LOCATION(TYPE_FIELDS(type)));
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v2 12/20] sgi-xp: Use designated initializers
  2017-05-26 20:17 [PATCH v2 00/20] Introduce struct layout randomization plugin Kees Cook
                   ` (10 preceding siblings ...)
  2017-05-26 20:17 ` [PATCH v2 11/20] randstruct: Disable randomization of ACPICA structs Kees Cook
@ 2017-05-26 20:17 ` Kees Cook
  2017-05-27  8:44   ` Christoph Hellwig
  2017-05-26 20:17 ` [PATCH v2 13/20] drm/amdgpu: " Kees Cook
                   ` (7 subsequent siblings)
  19 siblings, 1 reply; 55+ messages in thread
From: Kees Cook @ 2017-05-26 20:17 UTC (permalink / raw)
  To: kernel-hardening; +Cc: Kees Cook, Laura Abbott, x86, linux-kernel

Prepare to mark sensitive kernel structures for randomization by making
sure they're using designated initializers. These were identified during
allyesconfig builds of x86, arm, and arm64, with most initializer fixes
extracted from grsecurity.

To avoid casting, this implements dummy functions with full function
prototypes.

Signed-off-by: Kees Cook <keescook@chromium.org>
Acked-by: Robin Holt <robinmholt@gmail.com>
---
 drivers/misc/sgi-xp/xp_main.c | 59 ++++++++++++++++++++++++++++---------------
 1 file changed, 39 insertions(+), 20 deletions(-)

diff --git a/drivers/misc/sgi-xp/xp_main.c b/drivers/misc/sgi-xp/xp_main.c
index 01be66d02ca8..bb47f9d9b68a 100644
--- a/drivers/misc/sgi-xp/xp_main.c
+++ b/drivers/misc/sgi-xp/xp_main.c
@@ -71,20 +71,44 @@ EXPORT_SYMBOL_GPL(xpc_registrations);
 /*
  * Initialize the XPC interface to indicate that XPC isn't loaded.
  */
-static enum xp_retval
-xpc_notloaded(void)
+static void xpc_notloaded_connect(int ch_number)
+{ }
+
+static void xpc_notloaded_disconnect(int ch_number)
+{ }
+
+static enum xp_retval xpc_notloaded_send(short partid, int ch_number,
+					 u32 flags, void *payload,
+					 u16 payload_size)
+{
+	return xpNotLoaded;
+}
+
+static enum xp_retval xpc_notloaded_send_notify(short partid, int ch_number,
+						u32 flags, void *payload,
+						u16 payload_size,
+						xpc_notify_func func,
+						void *key)
+{
+	return xpNotLoaded;
+}
+
+static void xpc_notloaded_received(short partid, int ch_number, void *payload)
+{ }
+
+static enum xp_retval xpc_notloaded_partid_to_nasids(short partid,
+						     void *nasid_mask)
 {
 	return xpNotLoaded;
 }
 
 struct xpc_interface xpc_interface = {
-	(void (*)(int))xpc_notloaded,
-	(void (*)(int))xpc_notloaded,
-	(enum xp_retval(*)(short, int, u32, void *, u16))xpc_notloaded,
-	(enum xp_retval(*)(short, int, u32, void *, u16, xpc_notify_func,
-			   void *))xpc_notloaded,
-	(void (*)(short, int, void *))xpc_notloaded,
-	(enum xp_retval(*)(short, void *))xpc_notloaded
+	.connect = xpc_notloaded_connect,
+	.disconnect = xpc_notloaded_disconnect,
+	.send = xpc_notloaded_send,
+	.send_notify = xpc_notloaded_send_notify,
+	.received = xpc_notloaded_received,
+	.partid_to_nasids = xpc_notloaded_partid_to_nasids
 };
 EXPORT_SYMBOL_GPL(xpc_interface);
 
@@ -115,17 +139,12 @@ EXPORT_SYMBOL_GPL(xpc_set_interface);
 void
 xpc_clear_interface(void)
 {
-	xpc_interface.connect = (void (*)(int))xpc_notloaded;
-	xpc_interface.disconnect = (void (*)(int))xpc_notloaded;
-	xpc_interface.send = (enum xp_retval(*)(short, int, u32, void *, u16))
-	    xpc_notloaded;
-	xpc_interface.send_notify = (enum xp_retval(*)(short, int, u32, void *,
-						       u16, xpc_notify_func,
-						       void *))xpc_notloaded;
-	xpc_interface.received = (void (*)(short, int, void *))
-	    xpc_notloaded;
-	xpc_interface.partid_to_nasids = (enum xp_retval(*)(short, void *))
-	    xpc_notloaded;
+	xpc_interface.connect = xpc_notloaded_connect;
+	xpc_interface.disconnect = xpc_notloaded_disconnect;
+	xpc_interface.send = xpc_notloaded_send;
+	xpc_interface.send_notify = xpc_notloaded_send_notify;
+	xpc_interface.received = xpc_notloaded_received;
+	xpc_interface.partid_to_nasids = xpc_notloaded_partid_to_nasids;
 }
 EXPORT_SYMBOL_GPL(xpc_clear_interface);
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v2 13/20] drm/amdgpu: Use designated initializers
  2017-05-26 20:17 [PATCH v2 00/20] Introduce struct layout randomization plugin Kees Cook
                   ` (11 preceding siblings ...)
  2017-05-26 20:17 ` [PATCH v2 12/20] sgi-xp: Use designated initializers Kees Cook
@ 2017-05-26 20:17 ` Kees Cook
  2017-05-26 20:17 ` [PATCH v2 14/20] drm/amd/powerplay: " Kees Cook
                   ` (6 subsequent siblings)
  19 siblings, 0 replies; 55+ messages in thread
From: Kees Cook @ 2017-05-26 20:17 UTC (permalink / raw)
  To: kernel-hardening
  Cc: Kees Cook, Alex Deucher, Christian König, Laura Abbott, x86,
	linux-kernel

The randstruct plugin requires structures that are entirely function
pointers be initialized using designated initializers.

Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: Christian König <christian.koenig@amd.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
index a4831fe0223b..a2c59a08b2bd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
@@ -220,9 +220,9 @@ static void amdgpu_vram_mgr_debug(struct ttm_mem_type_manager *man,
 }
 
 const struct ttm_mem_type_manager_func amdgpu_vram_mgr_func = {
-	amdgpu_vram_mgr_init,
-	amdgpu_vram_mgr_fini,
-	amdgpu_vram_mgr_new,
-	amdgpu_vram_mgr_del,
-	amdgpu_vram_mgr_debug
+	.init		= amdgpu_vram_mgr_init,
+	.takedown	= amdgpu_vram_mgr_fini,
+	.get_node	= amdgpu_vram_mgr_new,
+	.put_node	= amdgpu_vram_mgr_del,
+	.debug		= amdgpu_vram_mgr_debug
 };
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v2 14/20] drm/amd/powerplay: Use designated initializers
  2017-05-26 20:17 [PATCH v2 00/20] Introduce struct layout randomization plugin Kees Cook
                   ` (12 preceding siblings ...)
  2017-05-26 20:17 ` [PATCH v2 13/20] drm/amdgpu: " Kees Cook
@ 2017-05-26 20:17 ` Kees Cook
  2017-05-27  8:47   ` Christoph Hellwig
  2017-05-26 20:17 ` [PATCH v2 15/20] mtk-vcodec: " Kees Cook
                   ` (5 subsequent siblings)
  19 siblings, 1 reply; 55+ messages in thread
From: Kees Cook @ 2017-05-26 20:17 UTC (permalink / raw)
  To: kernel-hardening
  Cc: Kees Cook, Christian König, Eric Huang, Alex Deucher,
	Laura Abbott, x86, linux-kernel

The randstruct plugin requires designated initializers for structures
that are entirely function pointers.

Cc: Christian König <christian.koenig@amd.com>
Cc: Eric Huang <JinHuiEric.Huang@amd.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 .../gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c   | 28 ++++++++++++++--------
 1 file changed, 18 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c
index d5f53d04fa08..cfa187185dcc 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c
@@ -709,17 +709,22 @@ static int tf_vega10_thermal_disable_alert(struct pp_hwmgr *hwmgr,
 
 static struct phm_master_table_item
 vega10_thermal_start_thermal_controller_master_list[] = {
-	{NULL, tf_vega10_thermal_initialize},
-	{NULL, tf_vega10_thermal_set_temperature_range},
-	{NULL, tf_vega10_thermal_enable_alert},
+	{ .isFunctionNeededInRuntimeTable = NULL,
+	  .tableFunction = tf_vega10_thermal_initialize },
+	{ .isFunctionNeededInRuntimeTable = NULL,
+	  .tableFunction = tf_vega10_thermal_set_temperature_range },
+	{ .isFunctionNeededInRuntimeTable = NULL,
+	  .tableFunction = tf_vega10_thermal_enable_alert },
 /* We should restrict performance levels to low before we halt the SMC.
  * On the other hand we are still in boot state when we do this
  * so it would be pointless.
  * If this assumption changes we have to revisit this table.
  */
-	{NULL, tf_vega10_thermal_setup_fan_table},
-	{NULL, tf_vega10_thermal_start_smc_fan_control},
-	{NULL, NULL}
+	{ .isFunctionNeededInRuntimeTable = NULL,
+	  .tableFunction = tf_vega10_thermal_setup_fan_table },
+	{ .isFunctionNeededInRuntimeTable = NULL,
+	  .tableFunction = tf_vega10_thermal_start_smc_fan_control },
+	{ }
 };
 
 static struct phm_master_table_header
@@ -731,10 +736,13 @@ vega10_thermal_start_thermal_controller_master = {
 
 static struct phm_master_table_item
 vega10_thermal_set_temperature_range_master_list[] = {
-	{NULL, tf_vega10_thermal_disable_alert},
-	{NULL, tf_vega10_thermal_set_temperature_range},
-	{NULL, tf_vega10_thermal_enable_alert},
-	{NULL, NULL}
+	{ .isFunctionNeededInRuntimeTable = NULL,
+	  .tableFunction = tf_vega10_thermal_disable_alert },
+	{ .isFunctionNeededInRuntimeTable = NULL,
+	  .tableFunction = tf_vega10_thermal_set_temperature_range },
+	{ .isFunctionNeededInRuntimeTable = NULL,
+	  .tableFunction = tf_vega10_thermal_enable_alert },
+	{ }
 };
 
 struct phm_master_table_header
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v2 15/20] mtk-vcodec: Use designated initializers
  2017-05-26 20:17 [PATCH v2 00/20] Introduce struct layout randomization plugin Kees Cook
                   ` (13 preceding siblings ...)
  2017-05-26 20:17 ` [PATCH v2 14/20] drm/amd/powerplay: " Kees Cook
@ 2017-05-26 20:17 ` Kees Cook
  2017-05-26 20:17 ` [PATCH v2 16/20] ntfs: Use ERR_CAST() to avoid cross-structure cast Kees Cook
                   ` (4 subsequent siblings)
  19 siblings, 0 replies; 55+ messages in thread
From: Kees Cook @ 2017-05-26 20:17 UTC (permalink / raw)
  To: kernel-hardening
  Cc: Kees Cook, Wu-Cheng Li, PC Chen, Tiffany Lin, Hans Verkuil,
	Mauro Carvalho Chehab, Laura Abbott, x86, linux-kernel

The randstruct plugin requires designated initializers for structures
that are entirely function pointers.

Cc: Wu-Cheng Li <wuchengli@chromium.org>
Cc: PC Chen <pc.chen@mediatek.com>
Cc: Tiffany Lin <tiffany.lin@mediatek.com>
Cc: Hans Verkuil <hans.verkuil@cisco.com>
Cc: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c | 8 ++++----
 drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c  | 8 ++++----
 drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c  | 8 ++++----
 3 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c b/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c
index 57a842ff3097..b7731b18ecae 100644
--- a/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c
+++ b/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c
@@ -493,10 +493,10 @@ static int vdec_h264_get_param(unsigned long h_vdec,
 }
 
 static struct vdec_common_if vdec_h264_if = {
-	vdec_h264_init,
-	vdec_h264_decode,
-	vdec_h264_get_param,
-	vdec_h264_deinit,
+	.init		= vdec_h264_init,
+	.decode		= vdec_h264_decode,
+	.get_param	= vdec_h264_get_param,
+	.deinit		= vdec_h264_deinit,
 };
 
 struct vdec_common_if *get_h264_dec_comm_if(void);
diff --git a/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c
index 6e7a62ae0842..b9fad6a48879 100644
--- a/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c
+++ b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c
@@ -620,10 +620,10 @@ static void vdec_vp8_deinit(unsigned long h_vdec)
 }
 
 static struct vdec_common_if vdec_vp8_if = {
-	vdec_vp8_init,
-	vdec_vp8_decode,
-	vdec_vp8_get_param,
-	vdec_vp8_deinit,
+	.init		= vdec_vp8_init,
+	.decode		= vdec_vp8_decode,
+	.get_param	= vdec_vp8_get_param,
+	.deinit		= vdec_vp8_deinit,
 };
 
 struct vdec_common_if *get_vp8_dec_comm_if(void);
diff --git a/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c
index 5539b1853f16..1daee1207469 100644
--- a/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c
+++ b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c
@@ -979,10 +979,10 @@ static int vdec_vp9_get_param(unsigned long h_vdec,
 }
 
 static struct vdec_common_if vdec_vp9_if = {
-	vdec_vp9_init,
-	vdec_vp9_decode,
-	vdec_vp9_get_param,
-	vdec_vp9_deinit,
+	.init		= vdec_vp9_init,
+	.decode		= vdec_vp9_decode,
+	.get_param	= vdec_vp9_get_param,
+	.deinit		= vdec_vp9_deinit,
 };
 
 struct vdec_common_if *get_vp9_dec_comm_if(void);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v2 16/20] ntfs: Use ERR_CAST() to avoid cross-structure cast
  2017-05-26 20:17 [PATCH v2 00/20] Introduce struct layout randomization plugin Kees Cook
                   ` (14 preceding siblings ...)
  2017-05-26 20:17 ` [PATCH v2 15/20] mtk-vcodec: " Kees Cook
@ 2017-05-26 20:17 ` Kees Cook
  2017-05-26 20:17 ` [PATCH v2 17/20] ocfs2: " Kees Cook
                   ` (3 subsequent siblings)
  19 siblings, 0 replies; 55+ messages in thread
From: Kees Cook @ 2017-05-26 20:17 UTC (permalink / raw)
  To: kernel-hardening
  Cc: Kees Cook, Anton Altaparmakov, Andrew Morton, Laura Abbott, x86,
	linux-kernel

When trying to propagate an error result, the error return path attempts
to retain the error, but does this with an open cast across very different
types, which the upcoming structure layout randomization plugin flags as
being potentially dangerous in the face of randomization. This is a false
positive, but what this code actually wants to do is use ERR_CAST() to
retain the error value.

Cc: Anton Altaparmakov <anton@tuxera.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 fs/ntfs/namei.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c
index 358258364616..4690cd75d8d7 100644
--- a/fs/ntfs/namei.c
+++ b/fs/ntfs/namei.c
@@ -159,7 +159,7 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent,
 					PTR_ERR(dent_inode));
 		kfree(name);
 		/* Return the error code. */
-		return (struct dentry *)dent_inode;
+		return ERR_CAST(dent_inode);
 	}
 	/* It is guaranteed that @name is no longer allocated at this point. */
 	if (MREF_ERR(mref) == -ENOENT) {
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v2 17/20] ocfs2: Use ERR_CAST() to avoid cross-structure cast
  2017-05-26 20:17 [PATCH v2 00/20] Introduce struct layout randomization plugin Kees Cook
                   ` (15 preceding siblings ...)
  2017-05-26 20:17 ` [PATCH v2 16/20] ntfs: Use ERR_CAST() to avoid cross-structure cast Kees Cook
@ 2017-05-26 20:17 ` Kees Cook
  2017-05-26 20:17 ` [PATCH v2 18/20] randstruct: Enable function pointer struct detection Kees Cook
                   ` (2 subsequent siblings)
  19 siblings, 0 replies; 55+ messages in thread
From: Kees Cook @ 2017-05-26 20:17 UTC (permalink / raw)
  To: kernel-hardening
  Cc: Kees Cook, Mark Fasheh, Joel Becker, Laura Abbott, x86, linux-kernel

When trying to propagate an error result, the error return path attempts
to retain the error, but does this with an open cast across very different
types, which the upcoming structure layout randomization plugin flags as
being potentially dangerous in the face of randomization. This is a false
positive, but what this code actually wants to do is use ERR_CAST() to
retain the error value.

Cc: Mark Fasheh <mfasheh@versity.com>
Cc: Joel Becker <jlbec@evilplan.org>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 fs/ocfs2/export.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/ocfs2/export.c b/fs/ocfs2/export.c
index 827fc9809bc2..9f88188060db 100644
--- a/fs/ocfs2/export.c
+++ b/fs/ocfs2/export.c
@@ -119,7 +119,7 @@ static struct dentry *ocfs2_get_dentry(struct super_block *sb,
 
 	if (IS_ERR(inode)) {
 		mlog_errno(PTR_ERR(inode));
-		result = (void *)inode;
+		result = ERR_CAST(inode);
 		goto bail;
 	}
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v2 18/20] randstruct: Enable function pointer struct detection
  2017-05-26 20:17 [PATCH v2 00/20] Introduce struct layout randomization plugin Kees Cook
                   ` (16 preceding siblings ...)
  2017-05-26 20:17 ` [PATCH v2 17/20] ocfs2: " Kees Cook
@ 2017-05-26 20:17 ` Kees Cook
  2017-05-26 20:17 ` [PATCH v2 19/20] [RFC] task_struct: Allow randomized layout Kees Cook
  2017-05-26 20:17 ` [PATCH v2 20/20] ACPICA: Use designated initializers Kees Cook
  19 siblings, 0 replies; 55+ messages in thread
From: Kees Cook @ 2017-05-26 20:17 UTC (permalink / raw)
  To: kernel-hardening; +Cc: Kees Cook, Laura Abbott, x86, linux-kernel

This enables the automatic structure selection logic in the randstruct
GCC plugin. The selection logic randomizes all structures that contain
only function pointers, unless marked with __no_randomize_layout.

Signed-off-by: Kees Cook <keescook@chromium.org>
---
 arch/Kconfig                                  | 12 +++++++-----
 scripts/gcc-plugins/randomize_layout_plugin.c |  3 ---
 2 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/arch/Kconfig b/arch/Kconfig
index 3eac97a4c7b3..f4597dbd0631 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -448,11 +448,13 @@ config GCC_PLUGIN_RANDSTRUCT
 	depends on GCC_PLUGINS
 	select MODVERSIONS if MODULES
 	help
-	  If you say Y here, the layouts of structures explicitly
-	  marked by __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.
+	  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
diff --git a/scripts/gcc-plugins/randomize_layout_plugin.c b/scripts/gcc-plugins/randomize_layout_plugin.c
index e6e02a40d522..bb2c6789c4b7 100644
--- a/scripts/gcc-plugins/randomize_layout_plugin.c
+++ b/scripts/gcc-plugins/randomize_layout_plugin.c
@@ -437,9 +437,6 @@ static int is_pure_ops_struct(const_tree node)
 
 	gcc_assert(TREE_CODE(node) == RECORD_TYPE || TREE_CODE(node) == UNION_TYPE);
 
-	/* XXX: Do not apply randomization to all-ftpr structs yet. */
-	return 0;
-
 	for (field = TYPE_FIELDS(node); field; field = TREE_CHAIN(field)) {
 		const_tree fieldtype = get_field_type(field);
 		enum tree_code code = TREE_CODE(fieldtype);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v2 19/20] [RFC] task_struct: Allow randomized layout
  2017-05-26 20:17 [PATCH v2 00/20] Introduce struct layout randomization plugin Kees Cook
                   ` (17 preceding siblings ...)
  2017-05-26 20:17 ` [PATCH v2 18/20] randstruct: Enable function pointer struct detection Kees Cook
@ 2017-05-26 20:17 ` Kees Cook
  2017-05-26 20:23   ` Linus Torvalds
  2017-05-26 20:17 ` [PATCH v2 20/20] ACPICA: Use designated initializers Kees Cook
  19 siblings, 1 reply; 55+ messages in thread
From: Kees Cook @ 2017-05-26 20:17 UTC (permalink / raw)
  To: kernel-hardening
  Cc: Kees Cook, Linus Torvalds, Laura Abbott, x86, linux-kernel

This marks most of the layout of task_struct as randomizable, but leaves
thread_info and scheduler state untouched at the start, and thread_struct
untouched at the end.

Other parts of the kernel use unnamed structures, but the 0-day builder
using gcc-4.4 blows up on static initializers. Officially, it's documented
as only working on gcc 4.6 and later, which further confuses me:
	https://gcc.gnu.org/wiki/C11Status
The structure layout randomization already requires gcc 4.7, but instead
of depending on the plugin being enabled, just check the gcc versions
for wider build testing. (But I'd rather find a way to avoid the #ifdef
entirely.)

One question about formatting remains: should this patch indent all the
randomized fields, due to the added unnamed struct, which would make
this patch white-space huge, or should I leave the indentation level
alone, to avoid massive churn? I opted for making the patch more readable,
but can easily do the indentation here or as a separate patch. It's not
obvious to me what is the least invasive change to make...

Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 include/linux/sched.h | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/include/linux/sched.h b/include/linux/sched.h
index b1298ad4da63..a9f7f957169c 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -490,6 +490,12 @@ struct task_struct {
 #endif
 	/* -1 unrunnable, 0 runnable, >0 stopped: */
 	volatile long			state;
+
+	/* This begins the randomizable portion of task_struct... */
+#if GCC_VERSION >= 40600
+	struct {
+#endif
+
 	void				*stack;
 	atomic_t			usage;
 	/* Per task flags (PF_*), defined further below: */
@@ -1052,6 +1058,14 @@ struct task_struct {
 	/* Used by LSM modules for access restriction: */
 	void				*security;
 #endif
+
+	/*
+	 * New fields for task_struct should be added above here.
+	 */
+#if GCC_VERSION >= 40600
+	} __randomize_layout;
+#endif
+
 	/* CPU-specific state of this task: */
 	struct thread_struct		thread;
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v2 20/20] ACPICA: Use designated initializers
  2017-05-26 20:17 [PATCH v2 00/20] Introduce struct layout randomization plugin Kees Cook
                   ` (18 preceding siblings ...)
  2017-05-26 20:17 ` [PATCH v2 19/20] [RFC] task_struct: Allow randomized layout Kees Cook
@ 2017-05-26 20:17 ` Kees Cook
  2017-05-28  7:45   ` Christoph Hellwig
  19 siblings, 1 reply; 55+ messages in thread
From: Kees Cook @ 2017-05-26 20:17 UTC (permalink / raw)
  To: kernel-hardening
  Cc: Kees Cook, Bob Moore, Lv Zheng, Rafael J . Wysocki, Laura Abbott,
	x86, linux-kernel

The struct layout randomization plugin detects and randomizes any structs
that contain only function pointers. Once layout is randomized, all
initialization must be designated or the compiler will misalign the
assignments. This switches all the ACPICA function pointer struct to
use designated initializers, using the proposed upstream ACPICA macro:
https://github.com/acpica/acpica/pull/248/

Cc: Bob Moore <robert.moore@intel.com>
Cc: Lv Zheng <lv.zheng@intel.com>
Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 drivers/acpi/acpica/hwxfsleep.c               | 14 +++++++++-----
 include/acpi/platform/acenv.h                 |  4 ++++
 include/acpi/platform/aclinux.h               |  2 ++
 scripts/gcc-plugins/randomize_layout_plugin.c |  4 ----
 4 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/drivers/acpi/acpica/hwxfsleep.c b/drivers/acpi/acpica/hwxfsleep.c
index 5733b1167e46..558fe4cdf29a 100644
--- a/drivers/acpi/acpica/hwxfsleep.c
+++ b/drivers/acpi/acpica/hwxfsleep.c
@@ -70,11 +70,15 @@ static acpi_status acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id);
 /* Legacy functions are optional, based upon ACPI_REDUCED_HARDWARE */
 
 static struct acpi_sleep_functions acpi_sleep_dispatch[] = {
-	{ACPI_HW_OPTIONAL_FUNCTION(acpi_hw_legacy_sleep),
-	 acpi_hw_extended_sleep},
-	{ACPI_HW_OPTIONAL_FUNCTION(acpi_hw_legacy_wake_prep),
-	 acpi_hw_extended_wake_prep},
-	{ACPI_HW_OPTIONAL_FUNCTION(acpi_hw_legacy_wake), acpi_hw_extended_wake}
+	{ACPI_STRUCT_INIT (legacy_function,
+			   ACPI_HW_OPTIONAL_FUNCTION (acpi_hw_legacy_sleep)),
+	 ACPI_STRUCT_INIT (extended_function, acpi_hw_extended_sleep) },
+	{ACPI_STRUCT_INIT (legacy_function,
+			   ACPI_HW_OPTIONAL_FUNCTION (acpi_hw_legacy_wake_prep)),
+	 ACPI_STRUCT_INIT (extended_function, acpi_hw_extended_wake_prep) },
+	{ACPI_STRUCT_INIT (legacy_function,
+			   ACPI_HW_OPTIONAL_FUNCTION (acpi_hw_legacy_wake)),
+	 ACPI_STRUCT_INIT (extended_function, acpi_hw_extended_wake) }
 };
 
 /*
diff --git a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h
index 09994b063243..912563c66948 100644
--- a/include/acpi/platform/acenv.h
+++ b/include/acpi/platform/acenv.h
@@ -382,4 +382,8 @@
 #define ACPI_INIT_FUNCTION
 #endif
 
+#ifndef ACPI_STRUCT_INIT
+#define ACPI_STRUCT_INIT(field, value) value
+#endif
+
 #endif				/* __ACENV_H__ */
diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h
index a39e3f67616f..047f13865608 100644
--- a/include/acpi/platform/aclinux.h
+++ b/include/acpi/platform/aclinux.h
@@ -178,6 +178,8 @@
 #define ACPI_MSG_BIOS_ERROR     KERN_ERR "ACPI BIOS Error (bug): "
 #define ACPI_MSG_BIOS_WARNING   KERN_WARNING "ACPI BIOS Warning (bug): "
 
+#define ACPI_STRUCT_INIT(field, value)	.field = value
+
 #else				/* !__KERNEL__ */
 
 #define ACPI_USE_STANDARD_HEADERS
diff --git a/scripts/gcc-plugins/randomize_layout_plugin.c b/scripts/gcc-plugins/randomize_layout_plugin.c
index bb2c6789c4b7..e1526554487e 100644
--- a/scripts/gcc-plugins/randomize_layout_plugin.c
+++ b/scripts/gcc-plugins/randomize_layout_plugin.c
@@ -346,10 +346,6 @@ static int relayout_struct(tree type)
 	    !strcmp((const char *)ORIG_TYPE_NAME(type), "RAWPCIFACTORY"))
 		return 0;
 
-	/* Skip ACPICA structs until refreshed with designated_init. */
-	if (!strcmp((const char *)ORIG_TYPE_NAME(type), "acpi_sleep_functions"))
-		return 0;
-
 	/* throw out any structs in uapi */
 	xloc = expand_location(DECL_SOURCE_LOCATION(TYPE_FIELDS(type)));
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 06/20] randstruct: Whitelist UNIXCB cast
  2017-05-26 20:17 ` [PATCH v2 06/20] randstruct: Whitelist UNIXCB cast Kees Cook
@ 2017-05-26 20:20   ` Kees Cook
  2017-05-28  7:56   ` Christoph Hellwig
  1 sibling, 0 replies; 55+ messages in thread
From: Kees Cook @ 2017-05-26 20:20 UTC (permalink / raw)
  To: kernel-hardening
  Cc: Kees Cook, Hannes Frederic Sowa,
	Signed-off-by : David S . Miller, Laura Abbott, x86, LKML

On Fri, May 26, 2017 at 1:17 PM, Kees Cook <keescook@chromium.org> wrote:
> This is another false positive in bad cast detection:
>
> net/unix/af_unix.c: In function ‘unix_skb_scm_eq’:
> net/unix/af_unix.c:1621:31: note: found mismatched rhs struct pointer types: ‘struct unix_skb_parms’ and ‘char’
>
>   const struct unix_skb_parms *u = &UNIXCB(skb);
>                                ^
>
> UNIXCB is:
>
>         #define UNIXCB(skb)     (*(struct unix_skb_parms *)&((skb)->cb))
>
> And ->cb is:
>
>         char                    cb[48] __aligned(8);
>
> This is a rather crazy cast, but appears to be safe in the face of
> randomization, so whitelist it in the plugin.
>
> Cc: Hannes Frederic Sowa <hannes@stressinduktion.org>
> Cc: Signed-off-by: David S. Miller <davem@davemloft.net>

Argh, paste-o. I was adding git history folks here to Cc, pardon the
glitch. This should be Cc: and absolutely not a S-o-B from Dave.

-Kees

> Signed-off-by: Kees Cook <keescook@chromium.org>
> ---
>  scripts/gcc-plugins/randomize_layout_plugin.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/scripts/gcc-plugins/randomize_layout_plugin.c b/scripts/gcc-plugins/randomize_layout_plugin.c
> index e126ac7874af..bf110915a5aa 100644
> --- a/scripts/gcc-plugins/randomize_layout_plugin.c
> +++ b/scripts/gcc-plugins/randomize_layout_plugin.c
> @@ -43,6 +43,8 @@ struct whitelist_entry {
>  };
>
>  static const struct whitelist_entry whitelist[] = {
> +       /* unix_skb_parms via UNIXCB() buffer */
> +       { "net/unix/af_unix.c", "unix_skb_parms", "char" },
>         /* walk struct security_hook_heads as an array of struct list_head */
>         { "security/security.c", "list_head", "security_hook_heads" },
>         { }
> --
> 2.7.4
>



-- 
Kees Cook
Pixel Security

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 19/20] [RFC] task_struct: Allow randomized layout
  2017-05-26 20:17 ` [PATCH v2 19/20] [RFC] task_struct: Allow randomized layout Kees Cook
@ 2017-05-26 20:23   ` Linus Torvalds
  2017-05-26 20:32     ` Kees Cook
  0 siblings, 1 reply; 55+ messages in thread
From: Linus Torvalds @ 2017-05-26 20:23 UTC (permalink / raw)
  To: Kees Cook
  Cc: kernel-hardening, Laura Abbott, the arch/x86 maintainers,
	Linux Kernel Mailing List

On Fri, May 26, 2017 at 1:17 PM, Kees Cook <keescook@chromium.org> wrote:
> This marks most of the layout of task_struct as randomizable, but leaves
> thread_info and scheduler state untouched at the start, and thread_struct
> untouched at the end.

I think you want to abstract this out somehow, because this is both
ugly and bad:

> +       /* This begins the randomizable portion of task_struct... */
> +#if GCC_VERSION >= 40600
> +       struct {
> +#endif

when you could instead just introduce something like

#if GCC_VERSION >= 40600
  #define randomized_struct_fields_start struct {
  #define randomized_struct_fields_end } __randomize_layout;
#else
  #define randomized_struct_fields_start
  #define randomized_struct_fields_end
#endif

and then this pattern is
 (a) more-or-less self-documenting
 (b) usable in other places too.
 (c) maybe some future compiler wants that struct field to have some
"randomize-me attribute" or something

Hmm?

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 19/20] [RFC] task_struct: Allow randomized layout
  2017-05-26 20:23   ` Linus Torvalds
@ 2017-05-26 20:32     ` Kees Cook
  0 siblings, 0 replies; 55+ messages in thread
From: Kees Cook @ 2017-05-26 20:32 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: kernel-hardening, Laura Abbott, the arch/x86 maintainers,
	Linux Kernel Mailing List

On Fri, May 26, 2017 at 1:23 PM, Linus Torvalds
<torvalds@linux-foundation.org> wrote:
> On Fri, May 26, 2017 at 1:17 PM, Kees Cook <keescook@chromium.org> wrote:
>> This marks most of the layout of task_struct as randomizable, but leaves
>> thread_info and scheduler state untouched at the start, and thread_struct
>> untouched at the end.
>
> I think you want to abstract this out somehow, because this is both
> ugly and bad:
>
>> +       /* This begins the randomizable portion of task_struct... */
>> +#if GCC_VERSION >= 40600
>> +       struct {
>> +#endif
>
> when you could instead just introduce something like
>
> #if GCC_VERSION >= 40600
>   #define randomized_struct_fields_start struct {
>   #define randomized_struct_fields_end } __randomize_layout;
> #else
>   #define randomized_struct_fields_start
>   #define randomized_struct_fields_end
> #endif
>
> and then this pattern is
>  (a) more-or-less self-documenting
>  (b) usable in other places too.
>  (c) maybe some future compiler wants that struct field to have some
> "randomize-me attribute" or something
>
> Hmm?

There were so many options and they all seems weird for various
reason. :) I'll use your idea, it looks much cleaner, thanks!

-Kees

-- 
Kees Cook
Pixel Security

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 05/20] randstruct: Whitelist struct security_hook_heads cast
  2017-05-26 20:17 ` [PATCH v2 05/20] randstruct: Whitelist struct security_hook_heads cast Kees Cook
@ 2017-05-27  8:41   ` Christoph Hellwig
  2017-05-27 20:09     ` Kees Cook
  0 siblings, 1 reply; 55+ messages in thread
From: Christoph Hellwig @ 2017-05-27  8:41 UTC (permalink / raw)
  To: Kees Cook
  Cc: kernel-hardening, Tetsuo Handa, James Morris, Laura Abbott, x86,
	linux-kernel

On Fri, May 26, 2017 at 01:17:09PM -0700, Kees Cook wrote:
> The LSM initialization routines walk security_hook_heads as an array
> of struct list_head instead of via names to avoid a ton of needless
> source. Whitelist this to avoid the false positive warning from the
> plugin:

I think this crap just needs to be fixed properly.  If not it almost
defeats the protections as the "security" ops are just about everywhere.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 11/20] randstruct: Disable randomization of ACPICA structs
  2017-05-26 20:17 ` [PATCH v2 11/20] randstruct: Disable randomization of ACPICA structs Kees Cook
@ 2017-05-27  8:42   ` Christoph Hellwig
  2017-05-27 20:03     ` Kees Cook
  0 siblings, 1 reply; 55+ messages in thread
From: Christoph Hellwig @ 2017-05-27  8:42 UTC (permalink / raw)
  To: Kees Cook; +Cc: kernel-hardening, Laura Abbott, x86, linux-kernel

On Fri, May 26, 2017 at 01:17:15PM -0700, Kees Cook wrote:
> Since the ACPICA source is maintained externally to the kernel, we can
> neither switch it to designated initializers nor mark it
> __no_randomize_layout. Until ACPICA-upstream changes[1] land to handle the
> designated initialization, explicitly skip it in the plugin.
> 
> [1] https://github.com/acpica/acpica/pull/248

I'd just overried the ACPIA bullshit process and just include these
changes, as they are a major improvement independent of any
reandomization.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 12/20] sgi-xp: Use designated initializers
  2017-05-26 20:17 ` [PATCH v2 12/20] sgi-xp: Use designated initializers Kees Cook
@ 2017-05-27  8:44   ` Christoph Hellwig
  0 siblings, 0 replies; 55+ messages in thread
From: Christoph Hellwig @ 2017-05-27  8:44 UTC (permalink / raw)
  To: Kees Cook; +Cc: kernel-hardening, Laura Abbott, x86, linux-kernel

On Fri, May 26, 2017 at 01:17:16PM -0700, Kees Cook wrote:
> Prepare to mark sensitive kernel structures for randomization by making
> sure they're using designated initializers. These were identified during
> allyesconfig builds of x86, arm, and arm64, with most initializer fixes
> extracted from grsecurity.
> 
> To avoid casting, this implements dummy functions with full function
> prototypes.

Can we get this in ASAP?

> +static void xpc_notloaded_connect(int ch_number)
> +{ }
> +
> +static void xpc_notloaded_disconnect(int ch_number)
> +{ }

Also it might be a good idea to just check in the caller if the
methods are defined instead of having all these dummys.  A branch
is usually cheaper than an indirect call, AND it leads to less code,
AND is is less fragile.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 14/20] drm/amd/powerplay: Use designated initializers
  2017-05-26 20:17 ` [PATCH v2 14/20] drm/amd/powerplay: " Kees Cook
@ 2017-05-27  8:47   ` Christoph Hellwig
  2017-05-27 20:10     ` Kees Cook
  0 siblings, 1 reply; 55+ messages in thread
From: Christoph Hellwig @ 2017-05-27  8:47 UTC (permalink / raw)
  To: Kees Cook
  Cc: kernel-hardening, Christian König, Eric Huang, Alex Deucher,
	Laura Abbott, x86, linux-kernel

> +	{ .isFunctionNeededInRuntimeTable = NULL,
> +	  .tableFunction = tf_vega10_thermal_initialize },

I'd say drop the NULL initializations as they are implicit anyway.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 11/20] randstruct: Disable randomization of ACPICA structs
  2017-05-27  8:42   ` Christoph Hellwig
@ 2017-05-27 20:03     ` Kees Cook
  2017-05-28  4:55       ` Christoph Hellwig
  0 siblings, 1 reply; 55+ messages in thread
From: Kees Cook @ 2017-05-27 20:03 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: kernel-hardening, Laura Abbott, x86, LKML, Bob Moore, Lv Zheng,
	Rafael J. Wysocki

On Sat, May 27, 2017 at 1:42 AM, Christoph Hellwig <hch@infradead.org> wrote:
> On Fri, May 26, 2017 at 01:17:15PM -0700, Kees Cook wrote:
>> Since the ACPICA source is maintained externally to the kernel, we can
>> neither switch it to designated initializers nor mark it
>> __no_randomize_layout. Until ACPICA-upstream changes[1] land to handle the
>> designated initialization, explicitly skip it in the plugin.
>>
>> [1] https://github.com/acpica/acpica/pull/248
>
> I'd just overried the ACPIA bullshit process and just include these
> changes, as they are a major improvement independent of any
> reandomization.

Well... I'd rather not. It's been explicitly NAKed by them already,
which is why I sent the upstream solution (though it's being ignored
currently).

I don't want this to block randstruct any longer, so that's why I took
a whitelisting approach here.

-Kees

-- 
Kees Cook
Pixel Security

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 05/20] randstruct: Whitelist struct security_hook_heads cast
  2017-05-27  8:41   ` Christoph Hellwig
@ 2017-05-27 20:09     ` Kees Cook
  2017-05-27 22:04       ` Tetsuo Handa
  2017-05-30 10:34       ` James Morris
  0 siblings, 2 replies; 55+ messages in thread
From: Kees Cook @ 2017-05-27 20:09 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: kernel-hardening, Tetsuo Handa, James Morris, Laura Abbott, x86,
	LKML, linux-security-module

On Sat, May 27, 2017 at 1:41 AM, Christoph Hellwig <hch@infradead.org> wrote:
> On Fri, May 26, 2017 at 01:17:09PM -0700, Kees Cook wrote:
>> The LSM initialization routines walk security_hook_heads as an array
>> of struct list_head instead of via names to avoid a ton of needless
>> source. Whitelist this to avoid the false positive warning from the
>> plugin:
>
> I think this crap just needs to be fixed properly.  If not it almost
> defeats the protections as the "security" ops are just about everywhere.

There's nothing unsafe about 3dfc9b02864b19f4dab376f14479ee4ad1de6c9e,
it just avoids tons of needless code. Tetsuo has some other ideas for
cleaning it up further, but I don't like it because it removes
compile-time verification of function types. There have been a lot of
trade-offs in getting this working correctly, so I don't have any
problem with how it looks currently. It's just a collision of
assumptions between randstruct (omg, you're accessing a randomized
struct with a different struct!) and the security head list (all
entries are lists, and we're just initializing them).

-Kees

-- 
Kees Cook
Pixel Security

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 14/20] drm/amd/powerplay: Use designated initializers
  2017-05-27  8:47   ` Christoph Hellwig
@ 2017-05-27 20:10     ` Kees Cook
  0 siblings, 0 replies; 55+ messages in thread
From: Kees Cook @ 2017-05-27 20:10 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: kernel-hardening, Christian König, Eric Huang, Alex Deucher,
	Laura Abbott, x86, LKML

On Sat, May 27, 2017 at 1:47 AM, Christoph Hellwig <hch@infradead.org> wrote:
>> +     { .isFunctionNeededInRuntimeTable = NULL,
>> +       .tableFunction = tf_vega10_thermal_initialize },
>
> I'd say drop the NULL initializations as they are implicit anyway.

Oh, dur, yeah, I'll improve this.

-Kees

-- 
Kees Cook
Pixel Security

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 05/20] randstruct: Whitelist struct security_hook_heads cast
  2017-05-27 20:09     ` Kees Cook
@ 2017-05-27 22:04       ` Tetsuo Handa
  2017-05-28  0:43         ` [kernel-hardening] " Kees Cook
  2017-05-30 10:34       ` James Morris
  1 sibling, 1 reply; 55+ messages in thread
From: Tetsuo Handa @ 2017-05-27 22:04 UTC (permalink / raw)
  To: keescook, hch
  Cc: kernel-hardening, james.l.morris, labbott, x86, linux-kernel,
	linux-security-module

Kees Cook wrote:
> On Sat, May 27, 2017 at 1:41 AM, Christoph Hellwig <hch@infradead.org> wrote:
> > On Fri, May 26, 2017 at 01:17:09PM -0700, Kees Cook wrote:
> >> The LSM initialization routines walk security_hook_heads as an array
> >> of struct list_head instead of via names to avoid a ton of needless
> >> source. Whitelist this to avoid the false positive warning from the
> >> plugin:
> >
> > I think this crap just needs to be fixed properly.  If not it almost
> > defeats the protections as the "security" ops are just about everywhere.
> 
> There's nothing unsafe about 3dfc9b02864b19f4dab376f14479ee4ad1de6c9e,
> it just avoids tons of needless code. Tetsuo has some other ideas for
> cleaning it up further, but I don't like it because it removes
> compile-time verification of function types.

Excuse me, but why you think that compile-time verification of function
types is removed?

-	{ .head = &security_hook_heads.HEAD, .hook = { .HEAD = HOOK } }
+	{ .idx = LSM_##HEAD, .hook = { .HEAD = HOOK } }

This change removes dependency on absolute address of security_hook_heads
being known at compile-time. If function types of .hook.HEAD and HOOK
mismatches, the compiler can still warn it.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [kernel-hardening] Re: [PATCH v2 05/20] randstruct: Whitelist struct security_hook_heads cast
  2017-05-27 22:04       ` Tetsuo Handa
@ 2017-05-28  0:43         ` Kees Cook
  0 siblings, 0 replies; 55+ messages in thread
From: Kees Cook @ 2017-05-28  0:43 UTC (permalink / raw)
  To: Tetsuo Handa
  Cc: Christoph Hellwig, kernel-hardening, James Morris, Laura Abbott,
	x86, LKML, linux-security-module

On Sat, May 27, 2017 at 3:04 PM, Tetsuo Handa
<penguin-kernel@i-love.sakura.ne.jp> wrote:
> Kees Cook wrote:
>> On Sat, May 27, 2017 at 1:41 AM, Christoph Hellwig <hch@infradead.org> wrote:
>> > On Fri, May 26, 2017 at 01:17:09PM -0700, Kees Cook wrote:
>> >> The LSM initialization routines walk security_hook_heads as an array
>> >> of struct list_head instead of via names to avoid a ton of needless
>> >> source. Whitelist this to avoid the false positive warning from the
>> >> plugin:
>> >
>> > I think this crap just needs to be fixed properly.  If not it almost
>> > defeats the protections as the "security" ops are just about everywhere.
>>
>> There's nothing unsafe about 3dfc9b02864b19f4dab376f14479ee4ad1de6c9e,
>> it just avoids tons of needless code. Tetsuo has some other ideas for
>> cleaning it up further, but I don't like it because it removes
>> compile-time verification of function types.
>
> Excuse me, but why you think that compile-time verification of function
> types is removed?
>
> -       { .head = &security_hook_heads.HEAD, .hook = { .HEAD = HOOK } }
> +       { .idx = LSM_##HEAD, .hook = { .HEAD = HOOK } }
>
> This change removes dependency on absolute address of security_hook_heads
> being known at compile-time. If function types of .hook.HEAD and HOOK
> mismatches, the compiler can still warn it.

Sorry, misremembered, that was the other patch. I'll go review this
current one...

-Kees

-- 
Kees Cook
Pixel Security

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 11/20] randstruct: Disable randomization of ACPICA structs
  2017-05-27 20:03     ` Kees Cook
@ 2017-05-28  4:55       ` Christoph Hellwig
  0 siblings, 0 replies; 55+ messages in thread
From: Christoph Hellwig @ 2017-05-28  4:55 UTC (permalink / raw)
  To: Kees Cook
  Cc: Christoph Hellwig, kernel-hardening, Laura Abbott, x86, LKML,
	Bob Moore, Lv Zheng, Rafael J. Wysocki

On Sat, May 27, 2017 at 01:03:23PM -0700, Kees Cook wrote:
> On Sat, May 27, 2017 at 1:42 AM, Christoph Hellwig <hch@infradead.org> wrote:
> > On Fri, May 26, 2017 at 01:17:15PM -0700, Kees Cook wrote:
> >> Since the ACPICA source is maintained externally to the kernel, we can
> >> neither switch it to designated initializers nor mark it
> >> __no_randomize_layout. Until ACPICA-upstream changes[1] land to handle the
> >> designated initialization, explicitly skip it in the plugin.
> >>
> >> [1] https://github.com/acpica/acpica/pull/248
> >
> > I'd just overried the ACPIA bullshit process and just include these
> > changes, as they are a major improvement independent of any
> > reandomization.
> 
> Well... I'd rather not. It's been explicitly NAKed by them already,
> which is why I sent the upstream solution (though it's being ignored
> currently).

Send it to linux-keernel again and we'll override their bulllshit.
We can make exceptions from our coding style and preference just because
they are idiots.  And the whole ACPI mess needs urgent de-obsfucation
anyway.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 20/20] ACPICA: Use designated initializers
  2017-05-26 20:17 ` [PATCH v2 20/20] ACPICA: Use designated initializers Kees Cook
@ 2017-05-28  7:45   ` Christoph Hellwig
  0 siblings, 0 replies; 55+ messages in thread
From: Christoph Hellwig @ 2017-05-28  7:45 UTC (permalink / raw)
  To: Kees Cook
  Cc: kernel-hardening, Bob Moore, Lv Zheng, Rafael J . Wysocki,
	Laura Abbott, x86, linux-kernel

The right fix is to get rid of the idiotic dispatch table entirely,
something like the minimally tested patch below:

---
>From e8046f6507c2ed60bc501a0c0caa5a3f15f5e3e4 Mon Sep 17 00:00:00 2001
From: Christoph Hellwig <hch@lst.de>
Date: Sun, 28 May 2017 09:53:45 +0300
Subject: acpi: get rid of acpi_sleep_dispatch

No need for the array of structs of function pointers when we can just
call the handfull of functions directly.

This could be further cleaned up if acpi_gbl_reduced_hardware was defined
true in the ACPI_REDUCED_HARDWARE case, but that's material for the next
round.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 drivers/acpi/acpica/hwxfsleep.c | 89 +++++++++--------------------------------
 include/acpi/actypes.h          |  9 -----
 2 files changed, 18 insertions(+), 80 deletions(-)

diff --git a/drivers/acpi/acpica/hwxfsleep.c b/drivers/acpi/acpica/hwxfsleep.c
index 5733b1167e46..66fa3ebddd57 100644
--- a/drivers/acpi/acpica/hwxfsleep.c
+++ b/drivers/acpi/acpica/hwxfsleep.c
@@ -57,26 +57,6 @@ acpi_hw_set_firmware_waking_vector(struct acpi_table_facs *facs,
 				   acpi_physical_address physical_address64);
 #endif
 
-static acpi_status acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id);
-
-/*
- * Dispatch table used to efficiently branch to the various sleep
- * functions.
- */
-#define ACPI_SLEEP_FUNCTION_ID         0
-#define ACPI_WAKE_PREP_FUNCTION_ID     1
-#define ACPI_WAKE_FUNCTION_ID          2
-
-/* Legacy functions are optional, based upon ACPI_REDUCED_HARDWARE */
-
-static struct acpi_sleep_functions acpi_sleep_dispatch[] = {
-	{ACPI_HW_OPTIONAL_FUNCTION(acpi_hw_legacy_sleep),
-	 acpi_hw_extended_sleep},
-	{ACPI_HW_OPTIONAL_FUNCTION(acpi_hw_legacy_wake_prep),
-	 acpi_hw_extended_wake_prep},
-	{ACPI_HW_OPTIONAL_FUNCTION(acpi_hw_legacy_wake), acpi_hw_extended_wake}
-};
-
 /*
  * These functions are removed for the ACPI_REDUCED_HARDWARE case:
  *      acpi_set_firmware_waking_vector
@@ -236,53 +216,6 @@ acpi_status acpi_enter_sleep_state_s4bios(void)
 
 ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios)
 #endif				/* !ACPI_REDUCED_HARDWARE */
-/*******************************************************************************
- *
- * FUNCTION:    acpi_hw_sleep_dispatch
- *
- * PARAMETERS:  sleep_state         - Which sleep state to enter/exit
- *              function_id         - Sleep, wake_prep, or Wake
- *
- * RETURN:      Status from the invoked sleep handling function.
- *
- * DESCRIPTION: Dispatch a sleep/wake request to the appropriate handling
- *              function.
- *
- ******************************************************************************/
-static acpi_status acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id)
-{
-	acpi_status status;
-	struct acpi_sleep_functions *sleep_functions =
-	    &acpi_sleep_dispatch[function_id];
-
-#if (!ACPI_REDUCED_HARDWARE)
-	/*
-	 * If the Hardware Reduced flag is set (from the FADT), we must
-	 * use the extended sleep registers (FADT). Note: As per the ACPI
-	 * specification, these extended registers are to be used for HW-reduced
-	 * platforms only. They are not general-purpose replacements for the
-	 * legacy PM register sleep support.
-	 */
-	if (acpi_gbl_reduced_hardware) {
-		status = sleep_functions->extended_function(sleep_state);
-	} else {
-		/* Legacy sleep */
-
-		status = sleep_functions->legacy_function(sleep_state);
-	}
-
-	return (status);
-
-#else
-	/*
-	 * For the case where reduced-hardware-only code is being generated,
-	 * we know that only the extended sleep registers are available
-	 */
-	status = sleep_functions->extended_function(sleep_state);
-	return (status);
-
-#endif				/* !ACPI_REDUCED_HARDWARE */
-}
 
 /*******************************************************************************
  *
@@ -389,7 +322,12 @@ acpi_status acpi_enter_sleep_state(u8 sleep_state)
 		return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
 	}
 
-	status = acpi_hw_sleep_dispatch(sleep_state, ACPI_SLEEP_FUNCTION_ID);
+#if !ACPI_REDUCED_HARDWARE
+	if (!acpi_gbl_reduced_hardware)
+		status = acpi_hw_legacy_sleep(sleep_state);
+	else
+#endif
+		status = acpi_hw_extended_sleep(sleep_state);
 	return_ACPI_STATUS(status);
 }
 
@@ -415,8 +353,12 @@ acpi_status acpi_leave_sleep_state_prep(u8 sleep_state)
 
 	ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep);
 
-	status =
-	    acpi_hw_sleep_dispatch(sleep_state, ACPI_WAKE_PREP_FUNCTION_ID);
+#if !ACPI_REDUCED_HARDWARE
+	if (!acpi_gbl_reduced_hardware)
+		status = acpi_hw_legacy_wake_prep(sleep_state);
+	else
+#endif
+		status = acpi_hw_extended_wake_prep(sleep_state);
 	return_ACPI_STATUS(status);
 }
 
@@ -440,7 +382,12 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state)
 
 	ACPI_FUNCTION_TRACE(acpi_leave_sleep_state);
 
-	status = acpi_hw_sleep_dispatch(sleep_state, ACPI_WAKE_FUNCTION_ID);
+#if !ACPI_REDUCED_HARDWARE
+	if (!acpi_gbl_reduced_hardware)
+		status = acpi_hw_legacy_wake(sleep_state);
+	else
+#endif
+		status = acpi_hw_extended_wake(sleep_state);
 	return_ACPI_STATUS(status);
 }
 
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
index d549e31c6d18..cfcb3abc65b9 100644
--- a/include/acpi/actypes.h
+++ b/include/acpi/actypes.h
@@ -894,15 +894,6 @@ typedef u8 acpi_adr_space_type;
 #define ACPI_ENABLE_EVENT                       1
 #define ACPI_DISABLE_EVENT                      0
 
-/* Sleep function dispatch */
-
-typedef acpi_status (*acpi_sleep_function) (u8 sleep_state);
-
-struct acpi_sleep_functions {
-	acpi_sleep_function legacy_function;
-	acpi_sleep_function extended_function;
-};
-
 /*
  * External ACPI object definition
  */
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 01/20] NFS: Avoid cross-structure casting
  2017-05-26 20:17 ` [PATCH v2 01/20] NFS: Avoid cross-structure casting Kees Cook
@ 2017-05-28  7:53   ` Christoph Hellwig
  2017-05-28 16:55     ` Kees Cook
  0 siblings, 1 reply; 55+ messages in thread
From: Christoph Hellwig @ 2017-05-28  7:53 UTC (permalink / raw)
  To: Kees Cook; +Cc: kernel-hardening, Laura Abbott, x86, linux-kernel

On Fri, May 26, 2017 at 01:17:05PM -0700, Kees Cook wrote:
> When the call to nfs_devname() fails, the error path attempts to retain
> the error via the mnt variable, but this requires a cast across very
> different types (char * to struct vfsmount *), which the upcoming
> structure layout randomization plugin flags as being potentially
> dangerous in the face of randomization. This is a false positive, but
> what this code actually wants to do is retain the error value, so this
> patch explicitly sets it, instead of using what seems to be an
> unexpected cast.
> 
> Signed-off-by: Kees Cook <keescook@chromium.org>
> Acked-by: Trond Myklebust <trond.myklebust@primarydata.com>

Looks good:

Reviewed-by: Christoph Hellwig <hch@lst.de>

And I think we should get this (and the other cast patches) in ASAP,
independent of the fat of the randstruct plugin.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 06/20] randstruct: Whitelist UNIXCB cast
  2017-05-26 20:17 ` [PATCH v2 06/20] randstruct: Whitelist UNIXCB cast Kees Cook
  2017-05-26 20:20   ` Kees Cook
@ 2017-05-28  7:56   ` Christoph Hellwig
  1 sibling, 0 replies; 55+ messages in thread
From: Christoph Hellwig @ 2017-05-28  7:56 UTC (permalink / raw)
  To: Kees Cook
  Cc: kernel-hardening, Hannes Frederic Sowa,
	Signed-off-by : David S . Miller, Laura Abbott, x86,
	linux-kernel

On Fri, May 26, 2017 at 01:17:10PM -0700, Kees Cook wrote:
> This is another false positive in bad cast detection:
> 
> net/unix/af_unix.c: In function ‘unix_skb_scm_eq’:
> net/unix/af_unix.c:1621:31: note: found mismatched rhs struct pointer types: ‘struct unix_skb_parms’ and ‘char’
> 
>   const struct unix_skb_parms *u = &UNIXCB(skb);
>                                ^
> 
> UNIXCB is:
> 
> 	#define UNIXCB(skb)     (*(struct unix_skb_parms *)&((skb)->cb))
> 
> And ->cb is:
> 
> 	char                    cb[48] __aligned(8);
> 
> This is a rather crazy cast, but appears to be safe in the face of
> randomization, so whitelist it in the plugin.

We have a lot of network protocol that use the ->cb area, which makes me
wonder why this one would be so special.

It seems like everyone is just using a plain cast to a pointer without
doing the address taking trick that doesn't make sense for arrays
anyway.

Maybe we just need to fix up the af_unix code to work the same as all
other protocols?

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 07/20] randstruct: Whitelist big_key path struct overloading
  2017-05-26 20:17 ` [PATCH v2 07/20] randstruct: Whitelist big_key path struct overloading Kees Cook
@ 2017-05-28  8:12   ` Christoph Hellwig
  2017-05-28 16:59     ` Kees Cook
  0 siblings, 1 reply; 55+ messages in thread
From: Christoph Hellwig @ 2017-05-28  8:12 UTC (permalink / raw)
  To: Kees Cook
  Cc: kernel-hardening, David Howells, Laura Abbott, x86, linux-kernel

What about the untested patch below to just fix the issue?

---
>From e9eb519c854d2f3d16a4def492577a883246e290 Mon Sep 17 00:00:00 2001
From: Christoph Hellwig <hch@lst.de>
Date: Sun, 28 May 2017 11:03:34 +0300
Subject: security/keys: don't cast union key_payload

Instead store the individual pointers in struct path.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 security/keys/big_key.c | 35 ++++++++++++++++++++---------------
 1 file changed, 20 insertions(+), 15 deletions(-)

diff --git a/security/keys/big_key.c b/security/keys/big_key.c
index 835c1ab30d01..06f2cd07dbd7 100644
--- a/security/keys/big_key.c
+++ b/security/keys/big_key.c
@@ -26,8 +26,8 @@
  */
 enum {
 	big_key_data,
-	big_key_path,
-	big_key_path_2nd_part,
+	big_key_path_mnt,
+	big_key_path_dentry,
 	big_key_len,
 };
 
@@ -118,12 +118,16 @@ static int big_key_crypt(enum big_key_op op, u8 *data, size_t datalen, u8 *key)
 	return ret;
 }
 
+#define PATH_FROM_PAYLOAD(p) {				\
+	.mnt	= (p)->data[big_key_path_mnt],		\
+	.dentry	= (p)->data[big_key_path_dentry],	\
+}
+
 /*
  * Preparse a big key
  */
 int big_key_preparse(struct key_preparsed_payload *prep)
 {
-	struct path *path = (struct path *)&prep->payload.data[big_key_path];
 	struct file *file;
 	u8 *enckey;
 	u8 *data = NULL;
@@ -190,9 +194,10 @@ int big_key_preparse(struct key_preparsed_payload *prep)
 		/* Pin the mount and dentry to the key so that we can open it again
 		 * later
 		 */
+		path_get(&file->f_path);
 		prep->payload.data[big_key_data] = enckey;
-		*path = file->f_path;
-		path_get(path);
+		prep->payload.data[big_key_path_mnt] = file->f_path.mnt;
+		prep->payload.data[big_key_path_dentry] = file->f_path.dentry;
 		fput(file);
 		kfree(data);
 	} else {
@@ -222,9 +227,9 @@ int big_key_preparse(struct key_preparsed_payload *prep)
 void big_key_free_preparse(struct key_preparsed_payload *prep)
 {
 	if (prep->datalen > BIG_KEY_FILE_THRESHOLD) {
-		struct path *path = (struct path *)&prep->payload.data[big_key_path];
+		struct path path = PATH_FROM_PAYLOAD(&prep->payload);
 
-		path_put(path);
+		path_put(&path);
 	}
 	kfree(prep->payload.data[big_key_data]);
 }
@@ -235,13 +240,13 @@ void big_key_free_preparse(struct key_preparsed_payload *prep)
  */
 void big_key_revoke(struct key *key)
 {
-	struct path *path = (struct path *)&key->payload.data[big_key_path];
+	struct path path = PATH_FROM_PAYLOAD(&key->payload);
 
 	/* clear the quota */
 	key_payload_reserve(key, 0);
 	if (key_is_instantiated(key) &&
 	    (size_t)key->payload.data[big_key_len] > BIG_KEY_FILE_THRESHOLD)
-		vfs_truncate(path, 0);
+		vfs_truncate(&path, 0);
 }
 
 /*
@@ -252,11 +257,11 @@ void big_key_destroy(struct key *key)
 	size_t datalen = (size_t)key->payload.data[big_key_len];
 
 	if (datalen > BIG_KEY_FILE_THRESHOLD) {
-		struct path *path = (struct path *)&key->payload.data[big_key_path];
+		struct path path = PATH_FROM_PAYLOAD(&key->payload);
 
-		path_put(path);
-		path->mnt = NULL;
-		path->dentry = NULL;
+		path_put(&path);
+		key->payload.data[big_key_path_mnt] = NULL;
+		key->payload.data[big_key_path_dentry] = NULL;
 	}
 	kfree(key->payload.data[big_key_data]);
 	key->payload.data[big_key_data] = NULL;
@@ -290,7 +295,7 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
 		return datalen;
 
 	if (datalen > BIG_KEY_FILE_THRESHOLD) {
-		struct path *path = (struct path *)&key->payload.data[big_key_path];
+		struct path path = PATH_FROM_PAYLOAD(&key->payload);
 		struct file *file;
 		u8 *data;
 		u8 *enckey = (u8 *)key->payload.data[big_key_data];
@@ -300,7 +305,7 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
 		if (!data)
 			return -ENOMEM;
 
-		file = dentry_open(path, O_RDONLY, current_cred());
+		file = dentry_open(&path, O_RDONLY, current_cred());
 		if (IS_ERR(file)) {
 			ret = PTR_ERR(file);
 			goto error;
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 08/20] randstruct: Whitelist NIU struct page overloading
  2017-05-26 20:17 ` [PATCH v2 08/20] randstruct: Whitelist NIU struct page overloading Kees Cook
@ 2017-05-28  8:15   ` Christoph Hellwig
  2017-05-28 17:35     ` Kees Cook
  2017-05-28 17:37     ` Kees Cook
  0 siblings, 2 replies; 55+ messages in thread
From: Christoph Hellwig @ 2017-05-28  8:15 UTC (permalink / raw)
  To: Kees Cook
  Cc: kernel-hardening, David S . Miller, Laura Abbott, x86, linux-kernel

On Fri, May 26, 2017 at 01:17:12PM -0700, Kees Cook wrote:
> The NIU ethernet driver intentionally stores a page struct pointer on
> top of the "mapping" field. Whitelist this case:
> 
> drivers/net/ethernet/sun/niu.c: In function ‘niu_rx_pkt_ignore’:
> drivers/net/ethernet/sun/niu.c:3402:10: note: found mismatched ssa struct pointer types: ‘struct page’ and ‘struct address_space’
> 
>     *link = (struct page *) page->mapping;
>     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> 
> Cc: David S. Miller <davem@davemloft.net>
> Signed-off-by: Kees Cook <keescook@chromium.org>

The driver really needs to stop doing this anyway.  It would be good
to send this out to linux-mm and netdev to come up with a better scheme.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 01/20] NFS: Avoid cross-structure casting
  2017-05-28  7:53   ` Christoph Hellwig
@ 2017-05-28 16:55     ` Kees Cook
  0 siblings, 0 replies; 55+ messages in thread
From: Kees Cook @ 2017-05-28 16:55 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: kernel-hardening, Laura Abbott, x86, LKML

On Sun, May 28, 2017 at 12:53 AM, Christoph Hellwig <hch@infradead.org> wrote:
> On Fri, May 26, 2017 at 01:17:05PM -0700, Kees Cook wrote:
>> When the call to nfs_devname() fails, the error path attempts to retain
>> the error via the mnt variable, but this requires a cast across very
>> different types (char * to struct vfsmount *), which the upcoming
>> structure layout randomization plugin flags as being potentially
>> dangerous in the face of randomization. This is a false positive, but
>> what this code actually wants to do is retain the error value, so this
>> patch explicitly sets it, instead of using what seems to be an
>> unexpected cast.
>>
>> Signed-off-by: Kees Cook <keescook@chromium.org>
>> Acked-by: Trond Myklebust <trond.myklebust@primarydata.com>
>
> Looks good:
>
> Reviewed-by: Christoph Hellwig <hch@lst.de>
>
> And I think we should get this (and the other cast patches) in ASAP,
> independent of the fat of the randstruct plugin.

Should I send a pull request to Linus for these for v4.12?

-Kees

-- 
Kees Cook
Pixel Security

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 07/20] randstruct: Whitelist big_key path struct overloading
  2017-05-28  8:12   ` Christoph Hellwig
@ 2017-05-28 16:59     ` Kees Cook
  2017-06-19 19:24       ` Kees Cook
  0 siblings, 1 reply; 55+ messages in thread
From: Kees Cook @ 2017-05-28 16:59 UTC (permalink / raw)
  To: Christoph Hellwig, David Howells
  Cc: kernel-hardening, Laura Abbott, x86, LKML

On Sun, May 28, 2017 at 1:12 AM, Christoph Hellwig <hch@infradead.org> wrote:
> What about the untested patch below to just fix the issue?
>
> ---
> From e9eb519c854d2f3d16a4def492577a883246e290 Mon Sep 17 00:00:00 2001
> From: Christoph Hellwig <hch@lst.de>
> Date: Sun, 28 May 2017 11:03:34 +0300
> Subject: security/keys: don't cast union key_payload
>
> Instead store the individual pointers in struct path.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>

Yeah, this is less invasive than what I'd proposed to David to fix it
earlier. David, does this look okay to you?

Reviewed-by: Kees Cook <keescook@chromium.org>

-Kees

> ---
>  security/keys/big_key.c | 35 ++++++++++++++++++++---------------
>  1 file changed, 20 insertions(+), 15 deletions(-)
>
> diff --git a/security/keys/big_key.c b/security/keys/big_key.c
> index 835c1ab30d01..06f2cd07dbd7 100644
> --- a/security/keys/big_key.c
> +++ b/security/keys/big_key.c
> @@ -26,8 +26,8 @@
>   */
>  enum {
>         big_key_data,
> -       big_key_path,
> -       big_key_path_2nd_part,
> +       big_key_path_mnt,
> +       big_key_path_dentry,
>         big_key_len,
>  };
>
> @@ -118,12 +118,16 @@ static int big_key_crypt(enum big_key_op op, u8 *data, size_t datalen, u8 *key)
>         return ret;
>  }
>
> +#define PATH_FROM_PAYLOAD(p) {                         \
> +       .mnt    = (p)->data[big_key_path_mnt],          \
> +       .dentry = (p)->data[big_key_path_dentry],       \
> +}
> +
>  /*
>   * Preparse a big key
>   */
>  int big_key_preparse(struct key_preparsed_payload *prep)
>  {
> -       struct path *path = (struct path *)&prep->payload.data[big_key_path];
>         struct file *file;
>         u8 *enckey;
>         u8 *data = NULL;
> @@ -190,9 +194,10 @@ int big_key_preparse(struct key_preparsed_payload *prep)
>                 /* Pin the mount and dentry to the key so that we can open it again
>                  * later
>                  */
> +               path_get(&file->f_path);
>                 prep->payload.data[big_key_data] = enckey;
> -               *path = file->f_path;
> -               path_get(path);
> +               prep->payload.data[big_key_path_mnt] = file->f_path.mnt;
> +               prep->payload.data[big_key_path_dentry] = file->f_path.dentry;
>                 fput(file);
>                 kfree(data);
>         } else {
> @@ -222,9 +227,9 @@ int big_key_preparse(struct key_preparsed_payload *prep)
>  void big_key_free_preparse(struct key_preparsed_payload *prep)
>  {
>         if (prep->datalen > BIG_KEY_FILE_THRESHOLD) {
> -               struct path *path = (struct path *)&prep->payload.data[big_key_path];
> +               struct path path = PATH_FROM_PAYLOAD(&prep->payload);
>
> -               path_put(path);
> +               path_put(&path);
>         }
>         kfree(prep->payload.data[big_key_data]);
>  }
> @@ -235,13 +240,13 @@ void big_key_free_preparse(struct key_preparsed_payload *prep)
>   */
>  void big_key_revoke(struct key *key)
>  {
> -       struct path *path = (struct path *)&key->payload.data[big_key_path];
> +       struct path path = PATH_FROM_PAYLOAD(&key->payload);
>
>         /* clear the quota */
>         key_payload_reserve(key, 0);
>         if (key_is_instantiated(key) &&
>             (size_t)key->payload.data[big_key_len] > BIG_KEY_FILE_THRESHOLD)
> -               vfs_truncate(path, 0);
> +               vfs_truncate(&path, 0);
>  }
>
>  /*
> @@ -252,11 +257,11 @@ void big_key_destroy(struct key *key)
>         size_t datalen = (size_t)key->payload.data[big_key_len];
>
>         if (datalen > BIG_KEY_FILE_THRESHOLD) {
> -               struct path *path = (struct path *)&key->payload.data[big_key_path];
> +               struct path path = PATH_FROM_PAYLOAD(&key->payload);
>
> -               path_put(path);
> -               path->mnt = NULL;
> -               path->dentry = NULL;
> +               path_put(&path);
> +               key->payload.data[big_key_path_mnt] = NULL;
> +               key->payload.data[big_key_path_dentry] = NULL;
>         }
>         kfree(key->payload.data[big_key_data]);
>         key->payload.data[big_key_data] = NULL;
> @@ -290,7 +295,7 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
>                 return datalen;
>
>         if (datalen > BIG_KEY_FILE_THRESHOLD) {
> -               struct path *path = (struct path *)&key->payload.data[big_key_path];
> +               struct path path = PATH_FROM_PAYLOAD(&key->payload);
>                 struct file *file;
>                 u8 *data;
>                 u8 *enckey = (u8 *)key->payload.data[big_key_data];
> @@ -300,7 +305,7 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
>                 if (!data)
>                         return -ENOMEM;
>
> -               file = dentry_open(path, O_RDONLY, current_cred());
> +               file = dentry_open(&path, O_RDONLY, current_cred());
>                 if (IS_ERR(file)) {
>                         ret = PTR_ERR(file);
>                         goto error;
> --
> 2.11.0
>



-- 
Kees Cook
Pixel Security

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 08/20] randstruct: Whitelist NIU struct page overloading
  2017-05-28  8:15   ` Christoph Hellwig
@ 2017-05-28 17:35     ` Kees Cook
  2017-05-28 17:37     ` Kees Cook
  1 sibling, 0 replies; 55+ messages in thread
From: Kees Cook @ 2017-05-28 17:35 UTC (permalink / raw)
  To: Christoph Hellwig, linux-mm, Network Development
  Cc: kernel-hardening, David S . Miller, Laura Abbott, x86, LKML

On Sun, May 28, 2017 at 1:15 AM, Christoph Hellwig <hch@infradead.org> wrote:
> On Fri, May 26, 2017 at 01:17:12PM -0700, Kees Cook wrote:
>> The NIU ethernet driver intentionally stores a page struct pointer on
>> top of the "mapping" field. Whitelist this case:
>>
>> drivers/net/ethernet/sun/niu.c: In function ‘niu_rx_pkt_ignore’:
>> drivers/net/ethernet/sun/niu.c:3402:10: note: found mismatched ssa struct pointer types: ‘struct page’ and ‘struct address_space’
>>
>>     *link = (struct page *) page->mapping;
>>     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>
>> Cc: David S. Miller <davem@davemloft.net>
>> Signed-off-by: Kees Cook <keescook@chromium.org>
>
> The driver really needs to stop doing this anyway.  It would be good
> to send this out to linux-mm and netdev to come up with a better scheme.

Added to To. :) I couldn't understand why it was doing what it was
doing, hence the whitelist entry.

-Kees

-- 
Kees Cook
Pixel Security

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 08/20] randstruct: Whitelist NIU struct page overloading
  2017-05-28  8:15   ` Christoph Hellwig
  2017-05-28 17:35     ` Kees Cook
@ 2017-05-28 17:37     ` Kees Cook
  1 sibling, 0 replies; 55+ messages in thread
From: Kees Cook @ 2017-05-28 17:37 UTC (permalink / raw)
  To: Christoph Hellwig, Linux-MM, Network Development
  Cc: kernel-hardening, David S . Miller, Laura Abbott, x86, LKML

[trying again with correct linux-mm address...]

On Sun, May 28, 2017 at 1:15 AM, Christoph Hellwig <hch@infradead.org> wrote:
> On Fri, May 26, 2017 at 01:17:12PM -0700, Kees Cook wrote:
>> The NIU ethernet driver intentionally stores a page struct pointer on
>> top of the "mapping" field. Whitelist this case:
>>
>> drivers/net/ethernet/sun/niu.c: In function ‘niu_rx_pkt_ignore’:
>> drivers/net/ethernet/sun/niu.c:3402:10: note: found mismatched ssa struct pointer types: ‘struct page’ and ‘struct address_space’
>>
>>     *link = (struct page *) page->mapping;
>>     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>
>> Cc: David S. Miller <davem@davemloft.net>
>> Signed-off-by: Kees Cook <keescook@chromium.org>
>
> The driver really needs to stop doing this anyway.  It would be good
> to send this out to linux-mm and netdev to come up with a better scheme.

Added to To. :) I couldn't understand why it was doing what it was
doing, hence the whitelist entry.

-Kees

-- 
Kees Cook
Pixel Security

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 05/20] randstruct: Whitelist struct security_hook_heads cast
  2017-05-27 20:09     ` Kees Cook
  2017-05-27 22:04       ` Tetsuo Handa
@ 2017-05-30 10:34       ` James Morris
  1 sibling, 0 replies; 55+ messages in thread
From: James Morris @ 2017-05-30 10:34 UTC (permalink / raw)
  To: Kees Cook
  Cc: Christoph Hellwig, kernel-hardening, Tetsuo Handa, James Morris,
	Laura Abbott, x86, LKML, linux-security-module

On Sat, 27 May 2017, Kees Cook wrote:

> On Sat, May 27, 2017 at 1:41 AM, Christoph Hellwig <hch@infradead.org> wrote:
> > On Fri, May 26, 2017 at 01:17:09PM -0700, Kees Cook wrote:
> >> The LSM initialization routines walk security_hook_heads as an array
> >> of struct list_head instead of via names to avoid a ton of needless
> >> source. Whitelist this to avoid the false positive warning from the
> >> plugin:
> >
> > I think this crap just needs to be fixed properly.  If not it almost
> > defeats the protections as the "security" ops are just about everywhere.
> 
> There's nothing unsafe about 3dfc9b02864b19f4dab376f14479ee4ad1de6c9e,
> it just avoids tons of needless code. 

Removing needless code is a security feature, ideally.

> Tetsuo has some other ideas for
> cleaning it up further, but I don't like it because it removes
> compile-time verification of function types. There have been a lot of
> trade-offs in getting this working correctly, so I don't have any
> problem with how it looks currently. It's just a collision of
> assumptions between randstruct (omg, you're accessing a randomized
> struct with a different struct!) and the security head list (all
> entries are lists, and we're just initializing them).

Fix randstruct perhaps, rather than modifying kernel code to shut it up.

-- 
James Morris
<jmorris@namei.org>

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 07/20] randstruct: Whitelist big_key path struct overloading
  2017-05-28 16:59     ` Kees Cook
@ 2017-06-19 19:24       ` Kees Cook
  2017-09-07  7:20         ` Christoph Hellwig
  0 siblings, 1 reply; 55+ messages in thread
From: Kees Cook @ 2017-06-19 19:24 UTC (permalink / raw)
  To: Christoph Hellwig, David Howells
  Cc: kernel-hardening, Laura Abbott, x86, LKML

On Sun, May 28, 2017 at 9:59 AM, Kees Cook <keescook@chromium.org> wrote:
> On Sun, May 28, 2017 at 1:12 AM, Christoph Hellwig <hch@infradead.org> wrote:
>> What about the untested patch below to just fix the issue?
>>
>> ---
>> From e9eb519c854d2f3d16a4def492577a883246e290 Mon Sep 17 00:00:00 2001
>> From: Christoph Hellwig <hch@lst.de>
>> Date: Sun, 28 May 2017 11:03:34 +0300
>> Subject: security/keys: don't cast union key_payload
>>
>> Instead store the individual pointers in struct path.
>>
>> Signed-off-by: Christoph Hellwig <hch@lst.de>
>
> Yeah, this is less invasive than what I'd proposed to David to fix it
> earlier. David, does this look okay to you?
>
> Reviewed-by: Kees Cook <keescook@chromium.org>

David, if you can Ack this, I'll carry it in my tree.

Thanks!

-Kees

>
> -Kees
>
>> ---
>>  security/keys/big_key.c | 35 ++++++++++++++++++++---------------
>>  1 file changed, 20 insertions(+), 15 deletions(-)
>>
>> diff --git a/security/keys/big_key.c b/security/keys/big_key.c
>> index 835c1ab30d01..06f2cd07dbd7 100644
>> --- a/security/keys/big_key.c
>> +++ b/security/keys/big_key.c
>> @@ -26,8 +26,8 @@
>>   */
>>  enum {
>>         big_key_data,
>> -       big_key_path,
>> -       big_key_path_2nd_part,
>> +       big_key_path_mnt,
>> +       big_key_path_dentry,
>>         big_key_len,
>>  };
>>
>> @@ -118,12 +118,16 @@ static int big_key_crypt(enum big_key_op op, u8 *data, size_t datalen, u8 *key)
>>         return ret;
>>  }
>>
>> +#define PATH_FROM_PAYLOAD(p) {                         \
>> +       .mnt    = (p)->data[big_key_path_mnt],          \
>> +       .dentry = (p)->data[big_key_path_dentry],       \
>> +}
>> +
>>  /*
>>   * Preparse a big key
>>   */
>>  int big_key_preparse(struct key_preparsed_payload *prep)
>>  {
>> -       struct path *path = (struct path *)&prep->payload.data[big_key_path];
>>         struct file *file;
>>         u8 *enckey;
>>         u8 *data = NULL;
>> @@ -190,9 +194,10 @@ int big_key_preparse(struct key_preparsed_payload *prep)
>>                 /* Pin the mount and dentry to the key so that we can open it again
>>                  * later
>>                  */
>> +               path_get(&file->f_path);
>>                 prep->payload.data[big_key_data] = enckey;
>> -               *path = file->f_path;
>> -               path_get(path);
>> +               prep->payload.data[big_key_path_mnt] = file->f_path.mnt;
>> +               prep->payload.data[big_key_path_dentry] = file->f_path.dentry;
>>                 fput(file);
>>                 kfree(data);
>>         } else {
>> @@ -222,9 +227,9 @@ int big_key_preparse(struct key_preparsed_payload *prep)
>>  void big_key_free_preparse(struct key_preparsed_payload *prep)
>>  {
>>         if (prep->datalen > BIG_KEY_FILE_THRESHOLD) {
>> -               struct path *path = (struct path *)&prep->payload.data[big_key_path];
>> +               struct path path = PATH_FROM_PAYLOAD(&prep->payload);
>>
>> -               path_put(path);
>> +               path_put(&path);
>>         }
>>         kfree(prep->payload.data[big_key_data]);
>>  }
>> @@ -235,13 +240,13 @@ void big_key_free_preparse(struct key_preparsed_payload *prep)
>>   */
>>  void big_key_revoke(struct key *key)
>>  {
>> -       struct path *path = (struct path *)&key->payload.data[big_key_path];
>> +       struct path path = PATH_FROM_PAYLOAD(&key->payload);
>>
>>         /* clear the quota */
>>         key_payload_reserve(key, 0);
>>         if (key_is_instantiated(key) &&
>>             (size_t)key->payload.data[big_key_len] > BIG_KEY_FILE_THRESHOLD)
>> -               vfs_truncate(path, 0);
>> +               vfs_truncate(&path, 0);
>>  }
>>
>>  /*
>> @@ -252,11 +257,11 @@ void big_key_destroy(struct key *key)
>>         size_t datalen = (size_t)key->payload.data[big_key_len];
>>
>>         if (datalen > BIG_KEY_FILE_THRESHOLD) {
>> -               struct path *path = (struct path *)&key->payload.data[big_key_path];
>> +               struct path path = PATH_FROM_PAYLOAD(&key->payload);
>>
>> -               path_put(path);
>> -               path->mnt = NULL;
>> -               path->dentry = NULL;
>> +               path_put(&path);
>> +               key->payload.data[big_key_path_mnt] = NULL;
>> +               key->payload.data[big_key_path_dentry] = NULL;
>>         }
>>         kfree(key->payload.data[big_key_data]);
>>         key->payload.data[big_key_data] = NULL;
>> @@ -290,7 +295,7 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
>>                 return datalen;
>>
>>         if (datalen > BIG_KEY_FILE_THRESHOLD) {
>> -               struct path *path = (struct path *)&key->payload.data[big_key_path];
>> +               struct path path = PATH_FROM_PAYLOAD(&key->payload);
>>                 struct file *file;
>>                 u8 *data;
>>                 u8 *enckey = (u8 *)key->payload.data[big_key_data];
>> @@ -300,7 +305,7 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
>>                 if (!data)
>>                         return -ENOMEM;
>>
>> -               file = dentry_open(path, O_RDONLY, current_cred());
>> +               file = dentry_open(&path, O_RDONLY, current_cred());
>>                 if (IS_ERR(file)) {
>>                         ret = PTR_ERR(file);
>>                         goto error;
>> --
>> 2.11.0
>>
>
>
>
> --
> Kees Cook
> Pixel Security



-- 
Kees Cook
Pixel Security

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 04/20] gcc-plugins: Add the randstruct plugin
  2017-05-26 20:17 ` [PATCH v2 04/20] gcc-plugins: Add the randstruct plugin Kees Cook
@ 2017-06-29 22:08   ` Arnd Bergmann
  2017-06-29 22:53     ` Kees Cook
  0 siblings, 1 reply; 55+ messages in thread
From: Arnd Bergmann @ 2017-06-29 22:08 UTC (permalink / raw)
  To: Kees Cook
  Cc: Kernel Hardening, Laura Abbott, the arch/x86 maintainers,
	Linux Kernel Mailing List

On Fri, May 26, 2017 at 10:17 PM, Kees Cook <keescook@chromium.org> wrote:
> This feature is ported from grsecurity. The implementation is almost
> entirely identical to the original code written by the PaX Team and
> Brad Spengler.

Hi Kees,

I noticed new build errors that bisected back to this patch, which has
now showed up
in linux-next again:


/git/arm-soc/arch/arm/kernel/entry-armv.S: Assembler messages:
/git/arm-soc/arch/arm/kernel/entry-armv.S:800: Error: bad immediate
value for offset (4644)
/git/arm-soc/scripts/Makefile.build:403: recipe for target
'arch/arm/kernel/entry-armv.o' failed
make[3]: *** [arch/arm/kernel/entry-armv.o] Error 1
/git/arm-soc/arch/arm/kernel/entry-armv.S: Assembler messages:
/git/arm-soc/arch/arm/kernel/entry-armv.S:800: Error: bad immediate
value for offset (5584)
/git/arm-soc/scripts/Makefile.build:403: recipe for target
'arch/arm/kernel/entry-armv.o' failed
make[3]: *** [arch/arm/kernel/entry-armv.o] Error 1
/git/arm-soc/arch/arm/mm/tlb-v4.S: Assembler messages:
/git/arm-soc/arch/arm/mm/tlb-v4.S:35: Error: bad immediate value for
offset (4928)
/git/arm-soc/scripts/Makefile.build:403: recipe for target
'arch/arm/mm/tlb-v4.o' failed
make[3]: *** [arch/arm/mm/tlb-v4.o] Error 1
/git/arm-soc/arch/arm/mm/tlb-v4wbi.S: Assembler messages:
/git/arm-soc/arch/arm/mm/tlb-v4wbi.S:34: Error: bad immediate value
for offset (4928)
/git/arm-soc/scripts/Makefile.build:403: recipe for target
'arch/arm/mm/tlb-v4wbi.o' failed

So far, that's the only thing that goes wrong for me though, and this
is probably
easy to fix.

        Arnd

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 04/20] gcc-plugins: Add the randstruct plugin
  2017-06-29 22:08   ` Arnd Bergmann
@ 2017-06-29 22:53     ` Kees Cook
  2017-06-30  0:04       ` Kees Cook
  2017-06-30  7:35       ` Arnd Bergmann
  0 siblings, 2 replies; 55+ messages in thread
From: Kees Cook @ 2017-06-29 22:53 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Kernel Hardening, Laura Abbott, the arch/x86 maintainers,
	Linux Kernel Mailing List

On Thu, Jun 29, 2017 at 3:08 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Fri, May 26, 2017 at 10:17 PM, Kees Cook <keescook@chromium.org> wrote:
> I noticed new build errors that bisected back to this patch, which has
> now showed up
> in linux-next again:

(FWIW this is randstruct not initify, and has been in -next for a
couple weeks now.)

> /git/arm-soc/arch/arm/kernel/entry-armv.S: Assembler messages:
> /git/arm-soc/arch/arm/kernel/entry-armv.S:800: Error: bad immediate
> value for offset (4644)
> /git/arm-soc/scripts/Makefile.build:403: recipe for target
> 'arch/arm/kernel/entry-armv.o' failed
> make[3]: *** [arch/arm/kernel/entry-armv.o] Error 1
> /git/arm-soc/arch/arm/kernel/entry-armv.S: Assembler messages:
> /git/arm-soc/arch/arm/kernel/entry-armv.S:800: Error: bad immediate
> value for offset (5584)

arch/arm/kernel/entry-armv.S:   ldr     r7, [r7, #TSK_STACK_CANARY]
arch/arm/kernel/asm-offsets.c:  DEFINE(TSK_STACK_CANARY,
offsetof(struct task_struct, stack_canary));

This would imply that stack_canary got randomized to an offset within
struct task_struct beyond the "ldr" immediate range (4096). Yay for
giant structs.

I'm surprised this didn't bisect to "task_struct: Allow randomized layout".

> /git/arm-soc/scripts/Makefile.build:403: recipe for target
> 'arch/arm/kernel/entry-armv.o' failed
> make[3]: *** [arch/arm/kernel/entry-armv.o] Error 1
> /git/arm-soc/arch/arm/mm/tlb-v4.S: Assembler messages:
> /git/arm-soc/arch/arm/mm/tlb-v4.S:35: Error: bad immediate value for
> offset (4928)

Similar:

        act_mm  r3                              @ get current->active_mm
...
        .macro  act_mm, rd
        ldr     \rd, [\rd, #TSK_ACTIVE_MM]
...
kernel/asm-offsets.c:  DEFINE(TSK_ACTIVE_MM,
offsetof(struct task_struct, active_mm));

> /git/arm-soc/scripts/Makefile.build:403: recipe for target
> 'arch/arm/mm/tlb-v4.o' failed
> make[3]: *** [arch/arm/mm/tlb-v4.o] Error 1
> /git/arm-soc/arch/arm/mm/tlb-v4wbi.S: Assembler messages:
> /git/arm-soc/arch/arm/mm/tlb-v4wbi.S:34: Error: bad immediate value
> for offset (4928)
> /git/arm-soc/scripts/Makefile.build:403: recipe for target
> 'arch/arm/mm/tlb-v4wbi.o' failed

Same as above.

> So far, that's the only thing that goes wrong for me though, and this
> is probably
> easy to fix.

Thanks for letting me know! These haven't shown up in my tests since I
haven't gotten "unlucky" in randomizing the task_struct, it seems.

I see a few possible solutions:

- ignore it and try your build again with a fresh tree and a new
randomization seed ;)
- remove "depends on !COMPILE_TEST" from
GCC_PLUGIN_RANDSTRUCT_PERFORMANCE, which will leave most stuff near
their original locations
- add a new annotation __randomize_cacheline which performs the same
logic as above, but only for the marked structure
- build new logic to keep certain fields (with some special marking)
within a given range of their original position
- rewrite the ARM code to handle larger immediates

The first obviously won't fly. The second just bypasses the problem
forcing it to be exposed by other people later. The third is likely
easiest to do now, but reduces the effectiveness of randomization for
architectures that don't have sensitive immediate values. The fourth
sounds not generally useful. The fifth may be unacceptable to arm
maintainers due to performance impacts.

Can you verify that reverting "task_struct: Allow randomized layout"
fixes a bugged build for you?

-Kees

-- 
Kees Cook
Pixel Security

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 04/20] gcc-plugins: Add the randstruct plugin
  2017-06-29 22:53     ` Kees Cook
@ 2017-06-30  0:04       ` Kees Cook
  2017-06-30  7:35       ` Arnd Bergmann
  1 sibling, 0 replies; 55+ messages in thread
From: Kees Cook @ 2017-06-30  0:04 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Kernel Hardening, Laura Abbott, the arch/x86 maintainers,
	Linux Kernel Mailing List

On Thu, Jun 29, 2017 at 3:53 PM, Kees Cook <keescook@chromium.org> wrote:
> I see a few possible solutions:

Or this ugly hack:

diff --git a/include/linux/sched.h b/include/linux/sched.h
index e2ad3531e7fe..5d131f9f1dac 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -749,6 +749,19 @@ struct task_struct {
        /* Namespaces: */
        struct nsproxy                  *nsproxy;

+#ifdef CONFIG_ARM
+       /*
+        * Since task_struct is gigantic, some asmoffset locations
+        * (e.g. TSK_STACK_CANARY) for a randomized field may exceed
+        * an architecture's instruction immediate values. As a
+        * work-around to avoid changing the performance characteristics
+        * of the assembly, split the randomization into two groups,
+        * keeping the "early" fields within range of the immediates.
+        */
+       randomized_struct_fields_end
+       randomized_struct_fields_start
+#endif
+
        /* Signal handlers: */
        struct signal_struct            *signal;
        struct sighand_struct           *sighand;


I suspect updating the ARM assembly (CONFIG-conditionally) to accept
>4095 offsets is probably the best solution.

-Kees

-- 
Kees Cook
Pixel Security

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 04/20] gcc-plugins: Add the randstruct plugin
  2017-06-29 22:53     ` Kees Cook
  2017-06-30  0:04       ` Kees Cook
@ 2017-06-30  7:35       ` Arnd Bergmann
  2017-06-30  7:55         ` Ard Biesheuvel
  1 sibling, 1 reply; 55+ messages in thread
From: Arnd Bergmann @ 2017-06-30  7:35 UTC (permalink / raw)
  To: Kees Cook
  Cc: Kernel Hardening, Laura Abbott, the arch/x86 maintainers,
	Linux Kernel Mailing List, Ard Biesheuvel,
	Russell King - ARM Linux, Nicolas Pitre, Will Deacon

On Fri, Jun 30, 2017 at 12:53 AM, Kees Cook <keescook@chromium.org> wrote:
> On Thu, Jun 29, 2017 at 3:08 PM, Arnd Bergmann <arnd@arndb.de> wrote:
>> On Fri, May 26, 2017 at 10:17 PM, Kees Cook <keescook@chromium.org> wrote:
>> I noticed new build errors that bisected back to this patch, which has
>> now showed up
>> in linux-next again:
>
> (FWIW this is randstruct not initify, and has been in -next for a
> couple weeks now.)

I first saw it last week and only now got around to looking any deeper,
as I had assumed that one of my own patches caused it.

>> /git/arm-soc/arch/arm/kernel/entry-armv.S: Assembler messages:
>> /git/arm-soc/arch/arm/kernel/entry-armv.S:800: Error: bad immediate
>> value for offset (4644)
>> /git/arm-soc/scripts/Makefile.build:403: recipe for target
>> 'arch/arm/kernel/entry-armv.o' failed
>> make[3]: *** [arch/arm/kernel/entry-armv.o] Error 1
>> /git/arm-soc/arch/arm/kernel/entry-armv.S: Assembler messages:
>> /git/arm-soc/arch/arm/kernel/entry-armv.S:800: Error: bad immediate
>> value for offset (5584)
>
> arch/arm/kernel/entry-armv.S:   ldr     r7, [r7, #TSK_STACK_CANARY]
> arch/arm/kernel/asm-offsets.c:  DEFINE(TSK_STACK_CANARY,
> offsetof(struct task_struct, stack_canary));
>
> This would imply that stack_canary got randomized to an offset within
> struct task_struct beyond the "ldr" immediate range (4096). Yay for
> giant structs.
>
> I'm surprised this didn't bisect to "task_struct: Allow randomized layout".

The bisection was a bit tricky, it's very possible that this should have
been the one to report.

>> /git/arm-soc/scripts/Makefile.build:403: recipe for target
>> 'arch/arm/kernel/entry-armv.o' failed
>> make[3]: *** [arch/arm/kernel/entry-armv.o] Error 1
>> /git/arm-soc/arch/arm/mm/tlb-v4.S: Assembler messages:
>> /git/arm-soc/arch/arm/mm/tlb-v4.S:35: Error: bad immediate value for
>> offset (4928)
>
> Similar:
>
>         act_mm  r3                              @ get current->active_mm
> ...
>         .macro  act_mm, rd
>         ldr     \rd, [\rd, #TSK_ACTIVE_MM]
> ...
> kernel/asm-offsets.c:  DEFINE(TSK_ACTIVE_MM,
> offsetof(struct task_struct, active_mm));
>
>> /git/arm-soc/scripts/Makefile.build:403: recipe for target
>> 'arch/arm/mm/tlb-v4.o' failed
>> make[3]: *** [arch/arm/mm/tlb-v4.o] Error 1
>> /git/arm-soc/arch/arm/mm/tlb-v4wbi.S: Assembler messages:
>> /git/arm-soc/arch/arm/mm/tlb-v4wbi.S:34: Error: bad immediate value
>> for offset (4928)
>> /git/arm-soc/scripts/Makefile.build:403: recipe for target
>> 'arch/arm/mm/tlb-v4wbi.o' failed
>
> Same as above.
>
>> So far, that's the only thing that goes wrong for me though, and this
>> is probably
>> easy to fix.
>
> Thanks for letting me know! These haven't shown up in my tests since I
> haven't gotten "unlucky" in randomizing the task_struct, it seems.

I've only hit it a couple of times a few thousand builds.

> I see a few possible solutions:
>
> - ignore it and try your build again with a fresh tree and a new
> randomization seed ;)
> - remove "depends on !COMPILE_TEST" from
> GCC_PLUGIN_RANDSTRUCT_PERFORMANCE, which will leave most stuff near
> their original locations
> - add a new annotation __randomize_cacheline which performs the same
> logic as above, but only for the marked structure
> - build new logic to keep certain fields (with some special marking)
> within a given range of their original position
> - rewrite the ARM code to handle larger immediates
>
> The first obviously won't fly. The second just bypasses the problem
> forcing it to be exposed by other people later. The third is likely
> easiest to do now, but reduces the effectiveness of randomization for
> architectures that don't have sensitive immediate values. The fourth
> sounds not generally useful. The fifth may be unacceptable to arm
> maintainers due to performance impacts.

I was thinking of the fifth solution, but don't know exactly how to
do it. If performance is a concern, I guess we could have separate
implementations for randstruct and traditional builds.

I've added a few more people to Cc that may know exactly how to
do it right.

> Can you verify that reverting "task_struct: Allow randomized layout"
> fixes a bugged build for you?

Confirmed.

      Arnd

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 04/20] gcc-plugins: Add the randstruct plugin
  2017-06-30  7:35       ` Arnd Bergmann
@ 2017-06-30  7:55         ` Ard Biesheuvel
  2017-06-30  8:27           ` Arnd Bergmann
  0 siblings, 1 reply; 55+ messages in thread
From: Ard Biesheuvel @ 2017-06-30  7:55 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Kees Cook, Kernel Hardening, Laura Abbott,
	the arch/x86 maintainers, Linux Kernel Mailing List,
	Russell King - ARM Linux, Nicolas Pitre, Will Deacon

On 30 June 2017 at 07:35, Arnd Bergmann <arnd@arndb.de> wrote:
> On Fri, Jun 30, 2017 at 12:53 AM, Kees Cook <keescook@chromium.org> wrote:
>> On Thu, Jun 29, 2017 at 3:08 PM, Arnd Bergmann <arnd@arndb.de> wrote:
>>> On Fri, May 26, 2017 at 10:17 PM, Kees Cook <keescook@chromium.org> wrote:
>>> I noticed new build errors that bisected back to this patch, which has
>>> now showed up
>>> in linux-next again:
>>
>> (FWIW this is randstruct not initify, and has been in -next for a
>> couple weeks now.)
>
> I first saw it last week and only now got around to looking any deeper,
> as I had assumed that one of my own patches caused it.
>
>>> /git/arm-soc/arch/arm/kernel/entry-armv.S: Assembler messages:
>>> /git/arm-soc/arch/arm/kernel/entry-armv.S:800: Error: bad immediate
>>> value for offset (4644)
>>> /git/arm-soc/scripts/Makefile.build:403: recipe for target
>>> 'arch/arm/kernel/entry-armv.o' failed
>>> make[3]: *** [arch/arm/kernel/entry-armv.o] Error 1
>>> /git/arm-soc/arch/arm/kernel/entry-armv.S: Assembler messages:
>>> /git/arm-soc/arch/arm/kernel/entry-armv.S:800: Error: bad immediate
>>> value for offset (5584)
>>
>> arch/arm/kernel/entry-armv.S:   ldr     r7, [r7, #TSK_STACK_CANARY]
>> arch/arm/kernel/asm-offsets.c:  DEFINE(TSK_STACK_CANARY,
>> offsetof(struct task_struct, stack_canary));
>>
>> This would imply that stack_canary got randomized to an offset within
>> struct task_struct beyond the "ldr" immediate range (4096). Yay for
>> giant structs.
>>
>> I'm surprised this didn't bisect to "task_struct: Allow randomized layout".
>
> The bisection was a bit tricky, it's very possible that this should have
> been the one to report.
>
>>> /git/arm-soc/scripts/Makefile.build:403: recipe for target
>>> 'arch/arm/kernel/entry-armv.o' failed
>>> make[3]: *** [arch/arm/kernel/entry-armv.o] Error 1
>>> /git/arm-soc/arch/arm/mm/tlb-v4.S: Assembler messages:
>>> /git/arm-soc/arch/arm/mm/tlb-v4.S:35: Error: bad immediate value for
>>> offset (4928)
>>
>> Similar:
>>
>>         act_mm  r3                              @ get current->active_mm
>> ...
>>         .macro  act_mm, rd
>>         ldr     \rd, [\rd, #TSK_ACTIVE_MM]
>> ...
>> kernel/asm-offsets.c:  DEFINE(TSK_ACTIVE_MM,
>> offsetof(struct task_struct, active_mm));
>>
>>> /git/arm-soc/scripts/Makefile.build:403: recipe for target
>>> 'arch/arm/mm/tlb-v4.o' failed
>>> make[3]: *** [arch/arm/mm/tlb-v4.o] Error 1
>>> /git/arm-soc/arch/arm/mm/tlb-v4wbi.S: Assembler messages:
>>> /git/arm-soc/arch/arm/mm/tlb-v4wbi.S:34: Error: bad immediate value
>>> for offset (4928)
>>> /git/arm-soc/scripts/Makefile.build:403: recipe for target
>>> 'arch/arm/mm/tlb-v4wbi.o' failed
>>
>> Same as above.
>>
>>> So far, that's the only thing that goes wrong for me though, and this
>>> is probably
>>> easy to fix.
>>
>> Thanks for letting me know! These haven't shown up in my tests since I
>> haven't gotten "unlucky" in randomizing the task_struct, it seems.
>
> I've only hit it a couple of times a few thousand builds.
>
>> I see a few possible solutions:
>>
>> - ignore it and try your build again with a fresh tree and a new
>> randomization seed ;)
>> - remove "depends on !COMPILE_TEST" from
>> GCC_PLUGIN_RANDSTRUCT_PERFORMANCE, which will leave most stuff near
>> their original locations
>> - add a new annotation __randomize_cacheline which performs the same
>> logic as above, but only for the marked structure
>> - build new logic to keep certain fields (with some special marking)
>> within a given range of their original position
>> - rewrite the ARM code to handle larger immediates
>>
>> The first obviously won't fly. The second just bypasses the problem
>> forcing it to be exposed by other people later. The third is likely
>> easiest to do now, but reduces the effectiveness of randomization for
>> architectures that don't have sensitive immediate values. The fourth
>> sounds not generally useful. The fifth may be unacceptable to arm
>> maintainers due to performance impacts.
>
> I was thinking of the fifth solution, but don't know exactly how to
> do it. If performance is a concern, I guess we could have separate
> implementations for randstruct and traditional builds.
>

Does this not apply to *all* entries in asm-offsets? If so, I don't
see how it is tractable to fix this in the code, unless we add some
instrumentation to asm-offsets to whitelist some huge structs and
error out on new ones. Or perhaps there's really only a handful?

In any case, these particular examples are fairly straightforward,
since there is no need to preserve the register's value.

ldr     r7, [r7, #TSK_STACK_CANARY]

could be replaced with

.if TSK_STACK_CANARAY >= PAGE_SIZE
add r7, r7, #TSK_STACK_CANARY & PAGE_MASK
.endif
ldr r7, [r7, #TSK_STACK_CANARY & ~PAGE_MASK]

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 04/20] gcc-plugins: Add the randstruct plugin
  2017-06-30  7:55         ` Ard Biesheuvel
@ 2017-06-30  8:27           ` Arnd Bergmann
  2017-06-30 14:41             ` Kees Cook
  0 siblings, 1 reply; 55+ messages in thread
From: Arnd Bergmann @ 2017-06-30  8:27 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Kees Cook, Kernel Hardening, Laura Abbott,
	the arch/x86 maintainers, Linux Kernel Mailing List,
	Russell King - ARM Linux, Nicolas Pitre, Will Deacon

On Fri, Jun 30, 2017 at 9:55 AM, Ard Biesheuvel
<ard.biesheuvel@linaro.org> wrote:
> On 30 June 2017 at 07:35, Arnd Bergmann <arnd@arndb.de> wrote:
>> On Fri, Jun 30, 2017 at 12:53 AM, Kees Cook <keescook@chromium.org> wrote:
>>> The first obviously won't fly. The second just bypasses the problem
>>> forcing it to be exposed by other people later. The third is likely
>>> easiest to do now, but reduces the effectiveness of randomization for
>>> architectures that don't have sensitive immediate values. The fourth
>>> sounds not generally useful. The fifth may be unacceptable to arm
>>> maintainers due to performance impacts.
>>
>> I was thinking of the fifth solution, but don't know exactly how to
>> do it. If performance is a concern, I guess we could have separate
>> implementations for randstruct and traditional builds.
>>
>
> Does this not apply to *all* entries in asm-offsets? If so, I don't
> see how it is tractable to fix this in the code, unless we add some
> instrumentation to asm-offsets to whitelist some huge structs and
> error out on new ones. Or perhaps there's really only a handful?

I think the other structs are all small enough:

* thread_info is at most 720 bytes (including crunch+vfp3, which
  you wouldn't find in one combined kernel) and not randomized
  at the moment
* pt_regs is 72 bytes and I don't see how that would be randomized
* machine_desc would be a candidate for randomizing, but is only
  108 bytes
* proc_info_list is 52 bytes and not currently randomized
* vm_area_struct is randomized but only 96 bytes.
* task_struct is clearly large enough, but we only use TSK_ACTIVE_MM
  and TSK_STACK_CANARY, both can be fixed with your trick.

> In any case, these particular examples are fairly straightforward,
> since there is no need to preserve the register's value.
>
> ldr     r7, [r7, #TSK_STACK_CANARY]
>
> could be replaced with
>
> .if TSK_STACK_CANARAY >= PAGE_SIZE
> add r7, r7, #TSK_STACK_CANARY & PAGE_MASK
> .endif
> ldr r7, [r7, #TSK_STACK_CANARY & ~PAGE_MASK]

Nice!

      Arnd

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 04/20] gcc-plugins: Add the randstruct plugin
  2017-06-30  8:27           ` Arnd Bergmann
@ 2017-06-30 14:41             ` Kees Cook
  2017-06-30 15:22               ` Arnd Bergmann
  0 siblings, 1 reply; 55+ messages in thread
From: Kees Cook @ 2017-06-30 14:41 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Ard Biesheuvel, Kernel Hardening, Laura Abbott,
	the arch/x86 maintainers, Linux Kernel Mailing List,
	Russell King - ARM Linux, Nicolas Pitre, Will Deacon

On Fri, Jun 30, 2017 at 1:27 AM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Fri, Jun 30, 2017 at 9:55 AM, Ard Biesheuvel
> <ard.biesheuvel@linaro.org> wrote:
>> On 30 June 2017 at 07:35, Arnd Bergmann <arnd@arndb.de> wrote:
>>> On Fri, Jun 30, 2017 at 12:53 AM, Kees Cook <keescook@chromium.org> wrote:
>>>> The first obviously won't fly. The second just bypasses the problem
>>>> forcing it to be exposed by other people later. The third is likely
>>>> easiest to do now, but reduces the effectiveness of randomization for
>>>> architectures that don't have sensitive immediate values. The fourth
>>>> sounds not generally useful. The fifth may be unacceptable to arm
>>>> maintainers due to performance impacts.
>>>
>>> I was thinking of the fifth solution, but don't know exactly how to
>>> do it. If performance is a concern, I guess we could have separate
>>> implementations for randstruct and traditional builds.
>>>
>>
>> Does this not apply to *all* entries in asm-offsets? If so, I don't
>> see how it is tractable to fix this in the code, unless we add some
>> instrumentation to asm-offsets to whitelist some huge structs and
>> error out on new ones. Or perhaps there's really only a handful?
>
> I think the other structs are all small enough:
>
> * thread_info is at most 720 bytes (including crunch+vfp3, which
>   you wouldn't find in one combined kernel) and not randomized
>   at the moment
> * pt_regs is 72 bytes and I don't see how that would be randomized
> * machine_desc would be a candidate for randomizing, but is only
>   108 bytes
> * proc_info_list is 52 bytes and not currently randomized
> * vm_area_struct is randomized but only 96 bytes.
> * task_struct is clearly large enough, but we only use TSK_ACTIVE_MM
>   and TSK_STACK_CANARY, both can be fixed with your trick.

Yup, that matches what I found. task_struct is the only truly giant struct.

>> In any case, these particular examples are fairly straightforward,
>> since there is no need to preserve the register's value.
>>
>> ldr     r7, [r7, #TSK_STACK_CANARY]
>>
>> could be replaced with
>>
>> .if TSK_STACK_CANARAY >= PAGE_SIZE
>> add r7, r7, #TSK_STACK_CANARY & PAGE_MASK
>> .endif
>> ldr r7, [r7, #TSK_STACK_CANARY & ~PAGE_MASK]
>
> Nice!

Oh, very cool. This'll make it only an asm change in the case where
it's required for randstruct. Perfect. I'll send a patch and carry it
in the randstruct tree.

(In looking at this, it seems tsk_mm is unused in mm/proc-macros.S, so
I'll remove that code unless someone sees something I don't.)

-Kees

-- 
Kees Cook
Pixel Security

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 04/20] gcc-plugins: Add the randstruct plugin
  2017-06-30 14:41             ` Kees Cook
@ 2017-06-30 15:22               ` Arnd Bergmann
  0 siblings, 0 replies; 55+ messages in thread
From: Arnd Bergmann @ 2017-06-30 15:22 UTC (permalink / raw)
  To: Kees Cook
  Cc: Ard Biesheuvel, Kernel Hardening, Laura Abbott,
	the arch/x86 maintainers, Linux Kernel Mailing List,
	Russell King - ARM Linux, Nicolas Pitre, Will Deacon

On Fri, Jun 30, 2017 at 4:41 PM, Kees Cook <keescook@chromium.org> wrote:
> On Fri, Jun 30, 2017 at 1:27 AM, Arnd Bergmann <arnd@arndb.de> wrote:
>> On Fri, Jun 30, 2017 at 9:55 AM, Ard Biesheuvel
>> <ard.biesheuvel@linaro.org> wrote:
>>> On 30 June 2017 at 07:35, Arnd Bergmann <arnd@arndb.de> wrote:
>>>> On Fri, Jun 30, 2017 at 12:53 AM, Kees Cook <keescook@chromium.org> wrote:
>>>>> The first obviously won't fly. The second just bypasses the problem
>>>>> forcing it to be exposed by other people later. The third is likely
>>>>> easiest to do now, but reduces the effectiveness of randomization for
>>>>> architectures that don't have sensitive immediate values. The fourth
>>>>> sounds not generally useful. The fifth may be unacceptable to arm
>>>>> maintainers due to performance impacts.
>>>>
>>>> I was thinking of the fifth solution, but don't know exactly how to
>>>> do it. If performance is a concern, I guess we could have separate
>>>> implementations for randstruct and traditional builds.
>>>>
>>>
>>> Does this not apply to *all* entries in asm-offsets? If so, I don't
>>> see how it is tractable to fix this in the code, unless we add some
>>> instrumentation to asm-offsets to whitelist some huge structs and
>>> error out on new ones. Or perhaps there's really only a handful?
>>
>> I think the other structs are all small enough:
>>
>> * thread_info is at most 720 bytes (including crunch+vfp3, which
>>   you wouldn't find in one combined kernel) and not randomized
>>   at the moment
>> * pt_regs is 72 bytes and I don't see how that would be randomized
>> * machine_desc would be a candidate for randomizing, but is only
>>   108 bytes
>> * proc_info_list is 52 bytes and not currently randomized
>> * vm_area_struct is randomized but only 96 bytes.
>> * task_struct is clearly large enough, but we only use TSK_ACTIVE_MM
>>   and TSK_STACK_CANARY, both can be fixed with your trick.
>
> Yup, that matches what I found. task_struct is the only truly giant struct.
>
>>> In any case, these particular examples are fairly straightforward,
>>> since there is no need to preserve the register's value.
>>>
>>> ldr     r7, [r7, #TSK_STACK_CANARY]
>>>
>>> could be replaced with
>>>
>>> .if TSK_STACK_CANARAY >= PAGE_SIZE
>>> add r7, r7, #TSK_STACK_CANARY & PAGE_MASK
>>> .endif
>>> ldr r7, [r7, #TSK_STACK_CANARY & ~PAGE_MASK]
>>
>> Nice!
>
> Oh, very cool. This'll make it only an asm change in the case where
> it's required for randstruct. Perfect. I'll send a patch and carry it
> in the randstruct tree.
>
> (In looking at this, it seems tsk_mm is unused in mm/proc-macros.S, so
> I'll remove that code unless someone sees something I don't.)

Ah, I missed that. This is what I have committed locally
(sorry, doesn't apply because gmail). Note that I had to
compare against PAGE_MASK here rather than PAGE_SIZE,
which contains a 'ul' postfix that the assembler doesn't like.

I'll send another copy to the list separately later today,
once my randconfig builds complete (there have been some
other regressions in the last few days, this one seems fine now).

       Arnd

commit 3b6308404cd40edcff9f5e2aacd3cff9b67d660c
Author: Arnd Bergmann <arnd@arndb.de>
Date:   Fri Jun 30 13:50:23 2017 +0200

    ARM: fix randomized task_struct

    With the new task struct randomization, we can run into a build
    failure for certain random seeds:

    arch/arm/kernel/entry-armv.S: Assembler messages:
    arch/arm/kernel/entry-armv.S:803: Error: bad immediate value for
offset (4096)

    Only two constants in asm-offset.h are affected, and I'm changing
    both of them here to work correctly in all configurations.

    Suggested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
    Fixes: c33d8b12fbbd ("task_struct: Allow randomized layout")
    Signed-off-by: Arnd Bergmann <arnd@arndb.de>

diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 9f157e7c51e7..db6d22b23bd8 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -797,7 +797,10 @@ ENTRY(__switch_to)
 #if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
        ldr     r7, [r2, #TI_TASK]
        ldr     r8, =__stack_chk_guard
-       ldr     r7, [r7, #TSK_STACK_CANARY]
+       .if (TSK_STACK_CANARY > PAGE_MASK)
+       add     r7, r7, #TSK_STACK_CANARY & PAGE_MASK
+       .endif
+       ldr     r7, [r7, #TSK_STACK_CANARY & ~PAGE_MASK]
 #endif
 #ifdef CONFIG_CPU_USE_DOMAINS
        mcr     p15, 0, r6, c3, c0, 0           @ Set domain register
diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S
index 0d40c285bd86..c7bd8fcf16a7 100644
--- a/arch/arm/mm/proc-macros.S
+++ b/arch/arm/mm/proc-macros.S
@@ -37,7 +37,10 @@
        bic     \rd, sp, #8128
        bic     \rd, \rd, #63
        ldr     \rd, [\rd, #TI_TASK]
-       ldr     \rd, [\rd, #TSK_ACTIVE_MM]
+       .if (TSK_ACTIVE_MM > PAGE_MASK)
+       add     \rd, \rd, #TSK_ACTIVE_MM & PAGE_MASK
+       .endif
+       ldr     \rd, [\rd, #TSK_ACTIVE_MM & ~PAGE_MASK]
        .endm

 /*

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 07/20] randstruct: Whitelist big_key path struct overloading
  2017-06-19 19:24       ` Kees Cook
@ 2017-09-07  7:20         ` Christoph Hellwig
  2017-09-07 22:55           ` Kees Cook
  0 siblings, 1 reply; 55+ messages in thread
From: Christoph Hellwig @ 2017-09-07  7:20 UTC (permalink / raw)
  To: Kees Cook
  Cc: Christoph Hellwig, David Howells, kernel-hardening, Laura Abbott,
	x86, LKML

On Mon, Jun 19, 2017 at 12:24:13PM -0700, Kees Cook wrote:
> David, if you can Ack this, I'll carry it in my tree.

This didn't seem to make it anywhere and we got the sad blacklist
entry instead..

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v2 07/20] randstruct: Whitelist big_key path struct overloading
  2017-09-07  7:20         ` Christoph Hellwig
@ 2017-09-07 22:55           ` Kees Cook
  0 siblings, 0 replies; 55+ messages in thread
From: Kees Cook @ 2017-09-07 22:55 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: David Howells, kernel-hardening, Laura Abbott, x86, LKML

On Thu, Sep 7, 2017 at 12:20 AM, Christoph Hellwig <hch@infradead.org> wrote:
> On Mon, Jun 19, 2017 at 12:24:13PM -0700, Kees Cook wrote:
>> David, if you can Ack this, I'll carry it in my tree.
>
> This didn't seem to make it anywhere and we got the sad blacklist
> entry instead..

David, thoughts? It seems like a nice solution. If you don't object, I
could carry it in -next (and remove the randstruct whitelist entry)?

-Kees

-- 
Kees Cook
Pixel Security

^ permalink raw reply	[flat|nested] 55+ messages in thread

end of thread, other threads:[~2017-09-07 22:55 UTC | newest]

Thread overview: 55+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-26 20:17 [PATCH v2 00/20] Introduce struct layout randomization plugin Kees Cook
2017-05-26 20:17 ` [PATCH v2 01/20] NFS: Avoid cross-structure casting Kees Cook
2017-05-28  7:53   ` Christoph Hellwig
2017-05-28 16:55     ` Kees Cook
2017-05-26 20:17 ` [PATCH v2 02/20] gcc-plugins: Detail c-common.h location for GCC 4.6 Kees Cook
2017-05-26 20:17 ` [PATCH v2 03/20] compiler: Add __designated_init annotation Kees Cook
2017-05-26 20:17 ` [PATCH v2 04/20] gcc-plugins: Add the randstruct plugin Kees Cook
2017-06-29 22:08   ` Arnd Bergmann
2017-06-29 22:53     ` Kees Cook
2017-06-30  0:04       ` Kees Cook
2017-06-30  7:35       ` Arnd Bergmann
2017-06-30  7:55         ` Ard Biesheuvel
2017-06-30  8:27           ` Arnd Bergmann
2017-06-30 14:41             ` Kees Cook
2017-06-30 15:22               ` Arnd Bergmann
2017-05-26 20:17 ` [PATCH v2 05/20] randstruct: Whitelist struct security_hook_heads cast Kees Cook
2017-05-27  8:41   ` Christoph Hellwig
2017-05-27 20:09     ` Kees Cook
2017-05-27 22:04       ` Tetsuo Handa
2017-05-28  0:43         ` [kernel-hardening] " Kees Cook
2017-05-30 10:34       ` James Morris
2017-05-26 20:17 ` [PATCH v2 06/20] randstruct: Whitelist UNIXCB cast Kees Cook
2017-05-26 20:20   ` Kees Cook
2017-05-28  7:56   ` Christoph Hellwig
2017-05-26 20:17 ` [PATCH v2 07/20] randstruct: Whitelist big_key path struct overloading Kees Cook
2017-05-28  8:12   ` Christoph Hellwig
2017-05-28 16:59     ` Kees Cook
2017-06-19 19:24       ` Kees Cook
2017-09-07  7:20         ` Christoph Hellwig
2017-09-07 22:55           ` Kees Cook
2017-05-26 20:17 ` [PATCH v2 08/20] randstruct: Whitelist NIU struct page overloading Kees Cook
2017-05-28  8:15   ` Christoph Hellwig
2017-05-28 17:35     ` Kees Cook
2017-05-28 17:37     ` Kees Cook
2017-05-26 20:17 ` [PATCH v2 09/20] randstruct: Mark various structs for randomization Kees Cook
2017-05-26 20:17 ` [PATCH v2 10/20] randstruct: opt-out externally exposed function pointer structs Kees Cook
2017-05-26 20:17 ` [PATCH v2 11/20] randstruct: Disable randomization of ACPICA structs Kees Cook
2017-05-27  8:42   ` Christoph Hellwig
2017-05-27 20:03     ` Kees Cook
2017-05-28  4:55       ` Christoph Hellwig
2017-05-26 20:17 ` [PATCH v2 12/20] sgi-xp: Use designated initializers Kees Cook
2017-05-27  8:44   ` Christoph Hellwig
2017-05-26 20:17 ` [PATCH v2 13/20] drm/amdgpu: " Kees Cook
2017-05-26 20:17 ` [PATCH v2 14/20] drm/amd/powerplay: " Kees Cook
2017-05-27  8:47   ` Christoph Hellwig
2017-05-27 20:10     ` Kees Cook
2017-05-26 20:17 ` [PATCH v2 15/20] mtk-vcodec: " Kees Cook
2017-05-26 20:17 ` [PATCH v2 16/20] ntfs: Use ERR_CAST() to avoid cross-structure cast Kees Cook
2017-05-26 20:17 ` [PATCH v2 17/20] ocfs2: " Kees Cook
2017-05-26 20:17 ` [PATCH v2 18/20] randstruct: Enable function pointer struct detection Kees Cook
2017-05-26 20:17 ` [PATCH v2 19/20] [RFC] task_struct: Allow randomized layout Kees Cook
2017-05-26 20:23   ` Linus Torvalds
2017-05-26 20:32     ` Kees Cook
2017-05-26 20:17 ` [PATCH v2 20/20] ACPICA: Use designated initializers Kees Cook
2017-05-28  7:45   ` Christoph Hellwig

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).