Thread (14 messages) 14 messages, 3 authors, 2016-05-30

Re: [PATCH v1 1/3] Add the latent_entropy gcc plugin

From: Kees Cook <hidden>
Date: 2016-05-24 17:32:21
Also in: linux-kbuild, lkml

On Mon, May 23, 2016 at 3:15 PM, Emese Revfy [off-list ref] wrote:
This plugin mitigates the problem of the kernel having too little entropy during
and after boot for generating crypto keys.

It creates a local variable in every marked function. The value of this variable is
modified by randomly chosen operations (add, xor and rol) and
random values (gcc generates them at compile time and the stack pointer at runtime).
It depends on the control flow (e.g., loops, conditions).

Before the function returns the plugin writes this local variable
into the latent_entropy global variable. The value of this global variable is
added to the kernel entropy pool in do_one_initcall() and _do_fork().
I'm excited to see this! This looks like it'll help a lot with early
entropy, which is something that'll be a problem for some
architectures that are trying to do early randomish things (e.g. the
heap layout randomization, various canaries, etc).

Do you have any good examples of a before/after case of early
randomness being fixed by this?
quoted hunk ↗ jump to hunk
Based on work created by the PaX Team.

Signed-off-by: Emese Revfy <redacted>
---
 arch/Kconfig                                |  17 ++
 arch/powerpc/kernel/Makefile                |   8 +-
 include/linux/random.h                      |   8 +
 init/main.c                                 |   1 +
 kernel/fork.c                               |   1 +
 mm/page_alloc.c                             |   5 +
 scripts/Makefile.gcc-plugins                |  10 +-
 scripts/gcc-plugins/Makefile                |   1 +
 scripts/gcc-plugins/latent_entropy_plugin.c | 446 ++++++++++++++++++++++++++++
 9 files changed, 491 insertions(+), 6 deletions(-)
 create mode 100644 scripts/gcc-plugins/latent_entropy_plugin.c
diff --git a/arch/Kconfig b/arch/Kconfig
index 5feadad..74489df 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -393,6 +393,23 @@ config GCC_PLUGIN_SANCOV
          gcc-4.5 on). It is based on the commit "Add fuzzing coverage support"
          by Dmitry Vyukov <dvyukov@google.com>.

+config GCC_PLUGIN_LATENT_ENTROPY
+       bool "latent entropy"
+       depends on GCC_PLUGINS
+       help
+         By saying Y here the kernel will instrument some kernel code to
+         extract some entropy from both original and artificially created
+         program state.  This will help especially embedded systems where
+         there is little 'natural' source of entropy normally.  The cost
+         is some slowdown of the boot process and fork and irq processing.
Can "some" be more well quantified?
+
+         Note that entropy extracted this way is not known to be cryptographically
+         secure!
maybe add ", but should be good enough for canaries and other secrets." ?
quoted hunk ↗ jump to hunk
+
+         This plugin was ported from grsecurity/PaX. More information at:
+          * https://grsecurity.net/
+          * https://pax.grsecurity.net/
+
 config HAVE_CC_STACKPROTECTOR
        bool
        help
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 2da380f..6c7e448 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -16,10 +16,10 @@ endif

 ifdef CONFIG_FUNCTION_TRACER
 # Do not trace early boot code
-CFLAGS_REMOVE_cputable.o = -mno-sched-epilog $(CC_FLAGS_FTRACE)
-CFLAGS_REMOVE_prom_init.o = -mno-sched-epilog $(CC_FLAGS_FTRACE)
-CFLAGS_REMOVE_btext.o = -mno-sched-epilog $(CC_FLAGS_FTRACE)
-CFLAGS_REMOVE_prom.o = -mno-sched-epilog $(CC_FLAGS_FTRACE)
+CFLAGS_REMOVE_cputable.o = -mno-sched-epilog $(CC_FLAGS_FTRACE) $(DISABLE_LATENT_ENTROPY_PLUGIN)
+CFLAGS_REMOVE_prom_init.o = -mno-sched-epilog $(CC_FLAGS_FTRACE) $(DISABLE_LATENT_ENTROPY_PLUGIN)
+CFLAGS_REMOVE_btext.o = -mno-sched-epilog $(CC_FLAGS_FTRACE) $(DISABLE_LATENT_ENTROPY_PLUGIN)
+CFLAGS_REMOVE_prom.o = -mno-sched-epilog $(CC_FLAGS_FTRACE) $(DISABLE_LATENT_ENTROPY_PLUGIN)
 # do not trace tracer code
 CFLAGS_REMOVE_ftrace.o = -mno-sched-epilog $(CC_FLAGS_FTRACE)
 # timers used by tracing
diff --git a/include/linux/random.h b/include/linux/random.h
index e47e533..379f4bc 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -18,6 +18,14 @@ struct random_ready_callback {
 };

 extern void add_device_randomness(const void *, unsigned int);
+
+static inline void add_latent_entropy(void)
+{
+#ifdef CONFIG_GCC_PLUGIN_LATENT_ENTROPY
+       add_device_randomness((const void *)&latent_entropy, sizeof(latent_entropy));
+#endif
+}
+
Traditionally the code style of #ifdef arrangement in header files
uses an "#else" since there's usually other code to wrap in it, and it
results in small future diffs:

#ifdef CONFIG_GCC_PLUGIN_LATENT_ENTROPY
static inline void add_latent_entropy(void)
{
       add_device_randomness((const void *)&latent_entropy,
sizeof(latent_entropy));
}
#else
static inline void add_latent_entropy(void) { }
#endif

Also, does this matter that it's non-atomic? It seems like the u64
below is being written to by multiple threads and even read by
multiple threads. Am I misunderstanding something?
quoted hunk ↗ jump to hunk
[...]
new file mode 100644
index 0000000..7295c39
--- /dev/null
+++ b/scripts/gcc-plugins/latent_entropy_plugin.c
I feel like most of the functions in this plugin could use some more
comments about what each one does.

-Kees

-- 
Kees Cook
Chrome OS & Brillo Security

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help