Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1393761 > unrolled thread

[PATCH v3 1/4] x86, boot: Refactor KASLR entropy functions

Started byThomas Garnier <thgarnie@google.com>
First post2016-05-03 21:40 +0200
Last post2016-05-10 22:20 +0200
Articles 3 — 2 participants

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  [PATCH v3 1/4] x86, boot: Refactor KASLR entropy functions Thomas Garnier <thgarnie@google.com> - 2016-05-03 21:40 +0200
    Re: [PATCH v3 1/4] x86, boot: Refactor KASLR entropy functions Kees Cook <keescook@chromium.org> - 2016-05-10 21:10 +0200
      Re: [PATCH v3 1/4] x86, boot: Refactor KASLR entropy functions Thomas Garnier <thgarnie@google.com> - 2016-05-10 22:20 +0200

#1393761 — [PATCH v3 1/4] x86, boot: Refactor KASLR entropy functions

FromThomas Garnier <thgarnie@google.com>
Date2016-05-03 21:40 +0200
Subject[PATCH v3 1/4] x86, boot: Refactor KASLR entropy functions
Message-ID<ruOkN-5Mr-1@gated-at.bofh.it>
Move the KASLR entropy functions in x86/libray to be used in early
kernel boot for KASLR memory randomization.

Signed-off-by: Thomas Garnier <thgarnie@google.com>
---
Based on next-20160502
---
 arch/x86/boot/compressed/kaslr.c | 76 +++-----------------------------------
 arch/x86/include/asm/kaslr.h     |  6 +++
 arch/x86/lib/Makefile            |  1 +
 arch/x86/lib/kaslr.c             | 79 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 91 insertions(+), 71 deletions(-)
 create mode 100644 arch/x86/include/asm/kaslr.h
 create mode 100644 arch/x86/lib/kaslr.c

diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
index 8741a6d..0bdee23 100644
--- a/arch/x86/boot/compressed/kaslr.c
+++ b/arch/x86/boot/compressed/kaslr.c
@@ -11,10 +11,6 @@
  */
 #include "misc.h"
 
-#include <asm/msr.h>
-#include <asm/archrandom.h>
-#include <asm/e820.h>
-
 #include <generated/compile.h>
 #include <linux/module.h>
 #include <linux/uts.h>
@@ -25,26 +21,6 @@
 static const char build_str[] = UTS_RELEASE " (" LINUX_COMPILE_BY "@"
 		LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION;
 
-#define I8254_PORT_CONTROL	0x43
-#define I8254_PORT_COUNTER0	0x40
-#define I8254_CMD_READBACK	0xC0
-#define I8254_SELECT_COUNTER0	0x02
-#define I8254_STATUS_NOTREADY	0x40
-static inline u16 i8254(void)
-{
-	u16 status, timer;
-
-	do {
-		outb(I8254_PORT_CONTROL,
-		     I8254_CMD_READBACK | I8254_SELECT_COUNTER0);
-		status = inb(I8254_PORT_COUNTER0);
-		timer  = inb(I8254_PORT_COUNTER0);
-		timer |= inb(I8254_PORT_COUNTER0) << 8;
-	} while (status & I8254_STATUS_NOTREADY);
-
-	return timer;
-}
-
 static unsigned long rotate_xor(unsigned long hash, const void *area,
 				size_t size)
 {
@@ -61,7 +37,7 @@ static unsigned long rotate_xor(unsigned long hash, const void *area,
 }
 
 /* Attempt to create a simple but unpredictable starting entropy. */
-static unsigned long get_random_boot(void)
+static unsigned long get_boot_seed(void)
 {
 	unsigned long hash = 0;
 
@@ -71,50 +47,6 @@ static unsigned long get_random_boot(void)
 	return hash;
 }
 
-static unsigned long get_random_long(void)
-{
-#ifdef CONFIG_X86_64
-	const unsigned long mix_const = 0x5d6008cbf3848dd3UL;
-#else
-	const unsigned long mix_const = 0x3f39e593UL;
-#endif
-	unsigned long raw, random = get_random_boot();
-	bool use_i8254 = true;
-
-	debug_putstr("KASLR using");
-
-	if (has_cpuflag(X86_FEATURE_RDRAND)) {
-		debug_putstr(" RDRAND");
-		if (rdrand_long(&raw)) {
-			random ^= raw;
-			use_i8254 = false;
-		}
-	}
-
-	if (has_cpuflag(X86_FEATURE_TSC)) {
-		debug_putstr(" RDTSC");
-		raw = rdtsc();
-
-		random ^= raw;
-		use_i8254 = false;
-	}
-
-	if (use_i8254) {
-		debug_putstr(" i8254");
-		random ^= i8254();
-	}
-
-	/* Circular multiply for better bit diffusion */
-	asm("mul %3"
-	    : "=a" (random), "=d" (raw)
-	    : "a" (random), "rm" (mix_const));
-	random += raw;
-
-	debug_putstr("...\n");
-
-	return random;
-}
-
 struct mem_vector {
 	unsigned long start;
 	unsigned long size;
@@ -122,7 +54,6 @@ struct mem_vector {
 
 #define MEM_AVOID_MAX 5
 static struct mem_vector mem_avoid[MEM_AVOID_MAX];
-
 static bool mem_contains(struct mem_vector *region, struct mem_vector *item)
 {
 	/* Item at least partially before region. */
@@ -229,13 +160,16 @@ static void slots_append(unsigned long addr)
 	slots[slot_max++] = addr;
 }
 
+#define KASLR_COMPRESSED_BOOT
+#include "../../lib/kaslr.c"
+
 static unsigned long slots_fetch_random(void)
 {
 	/* Handle case of no slots stored. */
 	if (slot_max == 0)
 		return 0;
 
-	return slots[get_random_long() % slot_max];
+	return slots[kaslr_get_random_boot_long() % slot_max];
 }
 
 static void process_e820_entry(struct e820entry *entry,
diff --git a/arch/x86/include/asm/kaslr.h b/arch/x86/include/asm/kaslr.h
new file mode 100644
index 0000000..2ae1429
--- /dev/null
+++ b/arch/x86/include/asm/kaslr.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_KASLR_H_
+#define _ASM_KASLR_H_
+
+unsigned long kaslr_get_random_boot_long(void);
+
+#endif
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index 72a5767..cfa6d07 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -24,6 +24,7 @@ lib-y += usercopy_$(BITS).o usercopy.o getuser.o putuser.o
 lib-y += memcpy_$(BITS).o
 lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
 lib-$(CONFIG_INSTRUCTION_DECODER) += insn.o inat.o
+lib-$(CONFIG_RANDOMIZE_BASE) += kaslr.o
 
 obj-y += msr.o msr-reg.o msr-reg-export.o
 
diff --git a/arch/x86/lib/kaslr.c b/arch/x86/lib/kaslr.c
new file mode 100644
index 0000000..ffb22ba
--- /dev/null
+++ b/arch/x86/lib/kaslr.c
@@ -0,0 +1,79 @@
+#include <asm/kaslr.h>
+#include <asm/msr.h>
+#include <asm/archrandom.h>
+#include <asm/e820.h>
+#include <asm/io.h>
+
+/* Replace boot functions on library build */
+#ifndef KASLR_COMPRESSED_BOOT
+#include <asm/cpufeature.h>
+#include <asm/setup.h>
+
+#define debug_putstr(v)
+#define has_cpuflag(f) boot_cpu_has(f)
+#define get_boot_seed() kaslr_offset()
+#endif
+
+#define I8254_PORT_CONTROL	0x43
+#define I8254_PORT_COUNTER0	0x40
+#define I8254_CMD_READBACK	0xC0
+#define I8254_SELECT_COUNTER0	0x02
+#define I8254_STATUS_NOTREADY	0x40
+static inline u16 i8254(void)
+{
+	u16 status, timer;
+
+	do {
+		outb(I8254_PORT_CONTROL,
+		     I8254_CMD_READBACK | I8254_SELECT_COUNTER0);
+		status = inb(I8254_PORT_COUNTER0);
+		timer  = inb(I8254_PORT_COUNTER0);
+		timer |= inb(I8254_PORT_COUNTER0) << 8;
+	} while (status & I8254_STATUS_NOTREADY);
+
+	return timer;
+}
+
+unsigned long kaslr_get_random_boot_long(void)
+{
+#ifdef CONFIG_X86_64
+	const unsigned long mix_const = 0x5d6008cbf3848dd3UL;
+#else
+	const unsigned long mix_const = 0x3f39e593UL;
+#endif
+	unsigned long raw, random = get_boot_seed();
+	bool use_i8254 = true;
+
+	debug_putstr("KASLR using");
+
+	if (has_cpuflag(X86_FEATURE_RDRAND)) {
+		debug_putstr(" RDRAND");
+		if (rdrand_long(&raw)) {
+			random ^= raw;
+			use_i8254 = false;
+		}
+	}
+
+	if (has_cpuflag(X86_FEATURE_TSC)) {
+		debug_putstr(" RDTSC");
+		raw = rdtsc();
+
+		random ^= raw;
+		use_i8254 = false;
+	}
+
+	if (use_i8254) {
+		debug_putstr(" i8254");
+		random ^= i8254();
+	}
+
+	/* Circular multiply for better bit diffusion */
+	asm("mul %3"
+	    : "=a" (random), "=d" (raw)
+	    : "a" (random), "rm" (mix_const));
+	random += raw;
+
+	debug_putstr("...\n");
+
+	return random;
+}
-- 
2.8.0.rc3.226.g39d4020

[toc] | [next] | [standalone]


#1398423

FromKees Cook <keescook@chromium.org>
Date2016-05-10 21:10 +0200
Message-ID<rxlcB-uF-1@gated-at.bofh.it>
In reply to#1393761
On Tue, May 3, 2016 at 12:31 PM, Thomas Garnier <thgarnie@google.com> wrote:
> Move the KASLR entropy functions in x86/libray to be used in early
> kernel boot for KASLR memory randomization.
>
> Signed-off-by: Thomas Garnier <thgarnie@google.com>
> ---
> Based on next-20160502
> ---
>  arch/x86/boot/compressed/kaslr.c | 76 +++-----------------------------------
>  arch/x86/include/asm/kaslr.h     |  6 +++
>  arch/x86/lib/Makefile            |  1 +
>  arch/x86/lib/kaslr.c             | 79 ++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 91 insertions(+), 71 deletions(-)
>  create mode 100644 arch/x86/include/asm/kaslr.h
>  create mode 100644 arch/x86/lib/kaslr.c
>
> diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
> index 8741a6d..0bdee23 100644
> --- a/arch/x86/boot/compressed/kaslr.c
> +++ b/arch/x86/boot/compressed/kaslr.c
> @@ -11,10 +11,6 @@
>   */
>  #include "misc.h"
>
> -#include <asm/msr.h>
> -#include <asm/archrandom.h>
> -#include <asm/e820.h>
> -
>  #include <generated/compile.h>
>  #include <linux/module.h>
>  #include <linux/uts.h>
> @@ -25,26 +21,6 @@
>  static const char build_str[] = UTS_RELEASE " (" LINUX_COMPILE_BY "@"
>                 LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION;
>
> -#define I8254_PORT_CONTROL     0x43
> -#define I8254_PORT_COUNTER0    0x40
> -#define I8254_CMD_READBACK     0xC0
> -#define I8254_SELECT_COUNTER0  0x02
> -#define I8254_STATUS_NOTREADY  0x40
> -static inline u16 i8254(void)
> -{
> -       u16 status, timer;
> -
> -       do {
> -               outb(I8254_PORT_CONTROL,
> -                    I8254_CMD_READBACK | I8254_SELECT_COUNTER0);
> -               status = inb(I8254_PORT_COUNTER0);
> -               timer  = inb(I8254_PORT_COUNTER0);
> -               timer |= inb(I8254_PORT_COUNTER0) << 8;
> -       } while (status & I8254_STATUS_NOTREADY);
> -
> -       return timer;
> -}
> -
>  static unsigned long rotate_xor(unsigned long hash, const void *area,
>                                 size_t size)
>  {
> @@ -61,7 +37,7 @@ static unsigned long rotate_xor(unsigned long hash, const void *area,
>  }
>
>  /* Attempt to create a simple but unpredictable starting entropy. */
> -static unsigned long get_random_boot(void)
> +static unsigned long get_boot_seed(void)
>  {
>         unsigned long hash = 0;
>
> @@ -71,50 +47,6 @@ static unsigned long get_random_boot(void)
>         return hash;
>  }
>
> -static unsigned long get_random_long(void)
> -{
> -#ifdef CONFIG_X86_64
> -       const unsigned long mix_const = 0x5d6008cbf3848dd3UL;
> -#else
> -       const unsigned long mix_const = 0x3f39e593UL;
> -#endif
> -       unsigned long raw, random = get_random_boot();
> -       bool use_i8254 = true;
> -
> -       debug_putstr("KASLR using");
> -
> -       if (has_cpuflag(X86_FEATURE_RDRAND)) {
> -               debug_putstr(" RDRAND");
> -               if (rdrand_long(&raw)) {
> -                       random ^= raw;
> -                       use_i8254 = false;
> -               }
> -       }
> -
> -       if (has_cpuflag(X86_FEATURE_TSC)) {
> -               debug_putstr(" RDTSC");
> -               raw = rdtsc();
> -
> -               random ^= raw;
> -               use_i8254 = false;
> -       }
> -
> -       if (use_i8254) {
> -               debug_putstr(" i8254");
> -               random ^= i8254();
> -       }
> -
> -       /* Circular multiply for better bit diffusion */
> -       asm("mul %3"
> -           : "=a" (random), "=d" (raw)
> -           : "a" (random), "rm" (mix_const));
> -       random += raw;
> -
> -       debug_putstr("...\n");
> -
> -       return random;
> -}
> -
>  struct mem_vector {
>         unsigned long start;
>         unsigned long size;
> @@ -122,7 +54,6 @@ struct mem_vector {
>
>  #define MEM_AVOID_MAX 5
>  static struct mem_vector mem_avoid[MEM_AVOID_MAX];
> -
>  static bool mem_contains(struct mem_vector *region, struct mem_vector *item)
>  {
>         /* Item at least partially before region. */
> @@ -229,13 +160,16 @@ static void slots_append(unsigned long addr)
>         slots[slot_max++] = addr;
>  }
>
> +#define KASLR_COMPRESSED_BOOT
> +#include "../../lib/kaslr.c"
> +
>  static unsigned long slots_fetch_random(void)
>  {
>         /* Handle case of no slots stored. */
>         if (slot_max == 0)
>                 return 0;
>
> -       return slots[get_random_long() % slot_max];
> +       return slots[kaslr_get_random_boot_long() % slot_max];
>  }
>
>  static void process_e820_entry(struct e820entry *entry,
> diff --git a/arch/x86/include/asm/kaslr.h b/arch/x86/include/asm/kaslr.h
> new file mode 100644
> index 0000000..2ae1429
> --- /dev/null
> +++ b/arch/x86/include/asm/kaslr.h
> @@ -0,0 +1,6 @@
> +#ifndef _ASM_KASLR_H_
> +#define _ASM_KASLR_H_
> +
> +unsigned long kaslr_get_random_boot_long(void);
> +
> +#endif
> diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
> index 72a5767..cfa6d07 100644
> --- a/arch/x86/lib/Makefile
> +++ b/arch/x86/lib/Makefile
> @@ -24,6 +24,7 @@ lib-y += usercopy_$(BITS).o usercopy.o getuser.o putuser.o
>  lib-y += memcpy_$(BITS).o
>  lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
>  lib-$(CONFIG_INSTRUCTION_DECODER) += insn.o inat.o
> +lib-$(CONFIG_RANDOMIZE_BASE) += kaslr.o
>
>  obj-y += msr.o msr-reg.o msr-reg-export.o
>
> diff --git a/arch/x86/lib/kaslr.c b/arch/x86/lib/kaslr.c
> new file mode 100644
> index 0000000..ffb22ba
> --- /dev/null
> +++ b/arch/x86/lib/kaslr.c
> @@ -0,0 +1,79 @@

Please add a file header comment here to describe what's contained and
that it is used in both regular and compressed kernels.

> +#include <asm/kaslr.h>
> +#include <asm/msr.h>
> +#include <asm/archrandom.h>
> +#include <asm/e820.h>
> +#include <asm/io.h>
> +
> +/* Replace boot functions on library build */

I'd expand this comment a bit, something like:

/*
 * When built for the regular kernel, several functions need to be stubbed out
 * or changed to their regular kernel equivalent.
 */

> +#ifndef KASLR_COMPRESSED_BOOT
> +#include <asm/cpufeature.h>
> +#include <asm/setup.h>
> +
> +#define debug_putstr(v)

Hmmm, I don't think this should be removed. Using these routines
should be uncommon, and it'd be nice to retain the debugging output
from them. Can this be refactored into an early printk, or is that
stuff not available yet? If it's not available, I can live with this
going silent, but it'd be nice to not lose it for the memory
randomization.

> +#define has_cpuflag(f) boot_cpu_has(f)
> +#define get_boot_seed() kaslr_offset()

Hmmm... this replacement seed feels like it has much less entropy.
Also, if RANDOMIZE_MEMORY is decoupled from RANDOMIZE_BASE, this will
not be cool. :) But I don't feel to strongly about the config coupling
-- I just wanted to see RANDOMIZE_MEMORY on by default if
RANDOMIZE_BASE is too.

> +#endif
> +
> +#define I8254_PORT_CONTROL     0x43
> +#define I8254_PORT_COUNTER0    0x40
> +#define I8254_CMD_READBACK     0xC0
> +#define I8254_SELECT_COUNTER0  0x02
> +#define I8254_STATUS_NOTREADY  0x40
> +static inline u16 i8254(void)
> +{
> +       u16 status, timer;
> +
> +       do {
> +               outb(I8254_PORT_CONTROL,
> +                    I8254_CMD_READBACK | I8254_SELECT_COUNTER0);
> +               status = inb(I8254_PORT_COUNTER0);
> +               timer  = inb(I8254_PORT_COUNTER0);
> +               timer |= inb(I8254_PORT_COUNTER0) << 8;
> +       } while (status & I8254_STATUS_NOTREADY);
> +
> +       return timer;
> +}
> +
> +unsigned long kaslr_get_random_boot_long(void)

Sorry again for the refactoring in this area: -tip (and soon -next)
will make yet another change to this function to carry a const char *
for the debug_putstr() calls.

> +{
> +#ifdef CONFIG_X86_64
> +       const unsigned long mix_const = 0x5d6008cbf3848dd3UL;
> +#else
> +       const unsigned long mix_const = 0x3f39e593UL;
> +#endif
> +       unsigned long raw, random = get_boot_seed();
> +       bool use_i8254 = true;
> +
> +       debug_putstr("KASLR using");
> +
> +       if (has_cpuflag(X86_FEATURE_RDRAND)) {
> +               debug_putstr(" RDRAND");
> +               if (rdrand_long(&raw)) {
> +                       random ^= raw;
> +                       use_i8254 = false;
> +               }
> +       }
> +
> +       if (has_cpuflag(X86_FEATURE_TSC)) {
> +               debug_putstr(" RDTSC");
> +               raw = rdtsc();
> +
> +               random ^= raw;
> +               use_i8254 = false;
> +       }
> +
> +       if (use_i8254) {
> +               debug_putstr(" i8254");
> +               random ^= i8254();
> +       }
> +
> +       /* Circular multiply for better bit diffusion */
> +       asm("mul %3"
> +           : "=a" (random), "=d" (raw)
> +           : "a" (random), "rm" (mix_const));
> +       random += raw;
> +
> +       debug_putstr("...\n");
> +
> +       return random;
> +}
> --
> 2.8.0.rc3.226.g39d4020
>

-Kees

-- 
Kees Cook
Chrome OS & Brillo Security

[toc] | [prev] | [next] | [standalone]


#1398476

FromThomas Garnier <thgarnie@google.com>
Date2016-05-10 22:20 +0200
Message-ID<rxmin-1nf-45@gated-at.bofh.it>
In reply to#1398423
On Tue, May 10, 2016 at 12:05 PM, Kees Cook <keescook@chromium.org> wrote:
> On Tue, May 3, 2016 at 12:31 PM, Thomas Garnier <thgarnie@google.com> wrote:
>> Move the KASLR entropy functions in x86/libray to be used in early
>> kernel boot for KASLR memory randomization.
>>
>> Signed-off-by: Thomas Garnier <thgarnie@google.com>
>> ---
>> Based on next-20160502
>> ---
>>  arch/x86/boot/compressed/kaslr.c | 76 +++-----------------------------------
>>  arch/x86/include/asm/kaslr.h     |  6 +++
>>  arch/x86/lib/Makefile            |  1 +
>>  arch/x86/lib/kaslr.c             | 79 ++++++++++++++++++++++++++++++++++++++++
>>  4 files changed, 91 insertions(+), 71 deletions(-)
>>  create mode 100644 arch/x86/include/asm/kaslr.h
>>  create mode 100644 arch/x86/lib/kaslr.c
>>
>> diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
>> index 8741a6d..0bdee23 100644
>> --- a/arch/x86/boot/compressed/kaslr.c
>> +++ b/arch/x86/boot/compressed/kaslr.c
>> @@ -11,10 +11,6 @@
>>   */
>>  #include "misc.h"
>>
>> -#include <asm/msr.h>
>> -#include <asm/archrandom.h>
>> -#include <asm/e820.h>
>> -
>>  #include <generated/compile.h>
>>  #include <linux/module.h>
>>  #include <linux/uts.h>
>> @@ -25,26 +21,6 @@
>>  static const char build_str[] = UTS_RELEASE " (" LINUX_COMPILE_BY "@"
>>                 LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION;
>>
>> -#define I8254_PORT_CONTROL     0x43
>> -#define I8254_PORT_COUNTER0    0x40
>> -#define I8254_CMD_READBACK     0xC0
>> -#define I8254_SELECT_COUNTER0  0x02
>> -#define I8254_STATUS_NOTREADY  0x40
>> -static inline u16 i8254(void)
>> -{
>> -       u16 status, timer;
>> -
>> -       do {
>> -               outb(I8254_PORT_CONTROL,
>> -                    I8254_CMD_READBACK | I8254_SELECT_COUNTER0);
>> -               status = inb(I8254_PORT_COUNTER0);
>> -               timer  = inb(I8254_PORT_COUNTER0);
>> -               timer |= inb(I8254_PORT_COUNTER0) << 8;
>> -       } while (status & I8254_STATUS_NOTREADY);
>> -
>> -       return timer;
>> -}
>> -
>>  static unsigned long rotate_xor(unsigned long hash, const void *area,
>>                                 size_t size)
>>  {
>> @@ -61,7 +37,7 @@ static unsigned long rotate_xor(unsigned long hash, const void *area,
>>  }
>>
>>  /* Attempt to create a simple but unpredictable starting entropy. */
>> -static unsigned long get_random_boot(void)
>> +static unsigned long get_boot_seed(void)
>>  {
>>         unsigned long hash = 0;
>>
>> @@ -71,50 +47,6 @@ static unsigned long get_random_boot(void)
>>         return hash;
>>  }
>>
>> -static unsigned long get_random_long(void)
>> -{
>> -#ifdef CONFIG_X86_64
>> -       const unsigned long mix_const = 0x5d6008cbf3848dd3UL;
>> -#else
>> -       const unsigned long mix_const = 0x3f39e593UL;
>> -#endif
>> -       unsigned long raw, random = get_random_boot();
>> -       bool use_i8254 = true;
>> -
>> -       debug_putstr("KASLR using");
>> -
>> -       if (has_cpuflag(X86_FEATURE_RDRAND)) {
>> -               debug_putstr(" RDRAND");
>> -               if (rdrand_long(&raw)) {
>> -                       random ^= raw;
>> -                       use_i8254 = false;
>> -               }
>> -       }
>> -
>> -       if (has_cpuflag(X86_FEATURE_TSC)) {
>> -               debug_putstr(" RDTSC");
>> -               raw = rdtsc();
>> -
>> -               random ^= raw;
>> -               use_i8254 = false;
>> -       }
>> -
>> -       if (use_i8254) {
>> -               debug_putstr(" i8254");
>> -               random ^= i8254();
>> -       }
>> -
>> -       /* Circular multiply for better bit diffusion */
>> -       asm("mul %3"
>> -           : "=a" (random), "=d" (raw)
>> -           : "a" (random), "rm" (mix_const));
>> -       random += raw;
>> -
>> -       debug_putstr("...\n");
>> -
>> -       return random;
>> -}
>> -
>>  struct mem_vector {
>>         unsigned long start;
>>         unsigned long size;
>> @@ -122,7 +54,6 @@ struct mem_vector {
>>
>>  #define MEM_AVOID_MAX 5
>>  static struct mem_vector mem_avoid[MEM_AVOID_MAX];
>> -
>>  static bool mem_contains(struct mem_vector *region, struct mem_vector *item)
>>  {
>>         /* Item at least partially before region. */
>> @@ -229,13 +160,16 @@ static void slots_append(unsigned long addr)
>>         slots[slot_max++] = addr;
>>  }
>>
>> +#define KASLR_COMPRESSED_BOOT
>> +#include "../../lib/kaslr.c"
>> +
>>  static unsigned long slots_fetch_random(void)
>>  {
>>         /* Handle case of no slots stored. */
>>         if (slot_max == 0)
>>                 return 0;
>>
>> -       return slots[get_random_long() % slot_max];
>> +       return slots[kaslr_get_random_boot_long() % slot_max];
>>  }
>>
>>  static void process_e820_entry(struct e820entry *entry,
>> diff --git a/arch/x86/include/asm/kaslr.h b/arch/x86/include/asm/kaslr.h
>> new file mode 100644
>> index 0000000..2ae1429
>> --- /dev/null
>> +++ b/arch/x86/include/asm/kaslr.h
>> @@ -0,0 +1,6 @@
>> +#ifndef _ASM_KASLR_H_
>> +#define _ASM_KASLR_H_
>> +
>> +unsigned long kaslr_get_random_boot_long(void);
>> +
>> +#endif
>> diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
>> index 72a5767..cfa6d07 100644
>> --- a/arch/x86/lib/Makefile
>> +++ b/arch/x86/lib/Makefile
>> @@ -24,6 +24,7 @@ lib-y += usercopy_$(BITS).o usercopy.o getuser.o putuser.o
>>  lib-y += memcpy_$(BITS).o
>>  lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
>>  lib-$(CONFIG_INSTRUCTION_DECODER) += insn.o inat.o
>> +lib-$(CONFIG_RANDOMIZE_BASE) += kaslr.o
>>
>>  obj-y += msr.o msr-reg.o msr-reg-export.o
>>
>> diff --git a/arch/x86/lib/kaslr.c b/arch/x86/lib/kaslr.c
>> new file mode 100644
>> index 0000000..ffb22ba
>> --- /dev/null
>> +++ b/arch/x86/lib/kaslr.c
>> @@ -0,0 +1,79 @@
>
> Please add a file header comment here to describe what's contained and
> that it is used in both regular and compressed kernels.
>

Will do.

>> +#include <asm/kaslr.h>
>> +#include <asm/msr.h>
>> +#include <asm/archrandom.h>
>> +#include <asm/e820.h>
>> +#include <asm/io.h>
>> +
>> +/* Replace boot functions on library build */
>
> I'd expand this comment a bit, something like:
>
> /*
>  * When built for the regular kernel, several functions need to be stubbed out
>  * or changed to their regular kernel equivalent.
>  */
>

Will do.

>> +#ifndef KASLR_COMPRESSED_BOOT
>> +#include <asm/cpufeature.h>
>> +#include <asm/setup.h>
>> +
>> +#define debug_putstr(v)
>
> Hmmm, I don't think this should be removed. Using these routines
> should be uncommon, and it'd be nice to retain the debugging output
> from them. Can this be refactored into an early printk, or is that
> stuff not available yet? If it's not available, I can live with this
> going silent, but it'd be nice to not lose it for the memory
> randomization.
>
>> +#define has_cpuflag(f) boot_cpu_has(f)
>> +#define get_boot_seed() kaslr_offset()
>
> Hmmm... this replacement seed feels like it has much less entropy.
> Also, if RANDOMIZE_MEMORY is decoupled from RANDOMIZE_BASE, this will
> not be cool. :) But I don't feel to strongly about the config coupling
> -- I just wanted to see RANDOMIZE_MEMORY on by default if
> RANDOMIZE_BASE is too.
>

Currently, RANDOMIZE_MEMORY is coupled with RANDOMIZE_BASE. I think it
makes sense that they remain together. Also there is not much additional entropy
available as a base here. The table used on KASLR compressed boot is gone.

>> +#endif
>> +
>> +#define I8254_PORT_CONTROL     0x43
>> +#define I8254_PORT_COUNTER0    0x40
>> +#define I8254_CMD_READBACK     0xC0
>> +#define I8254_SELECT_COUNTER0  0x02
>> +#define I8254_STATUS_NOTREADY  0x40
>> +static inline u16 i8254(void)
>> +{
>> +       u16 status, timer;
>> +
>> +       do {
>> +               outb(I8254_PORT_CONTROL,
>> +                    I8254_CMD_READBACK | I8254_SELECT_COUNTER0);
>> +               status = inb(I8254_PORT_COUNTER0);
>> +               timer  = inb(I8254_PORT_COUNTER0);
>> +               timer |= inb(I8254_PORT_COUNTER0) << 8;
>> +       } while (status & I8254_STATUS_NOTREADY);
>> +
>> +       return timer;
>> +}
>> +
>> +unsigned long kaslr_get_random_boot_long(void)
>
> Sorry again for the refactoring in this area: -tip (and soon -next)
> will make yet another change to this function to carry a const char *
> for the debug_putstr() calls.
>

I will keep an eye on it and send the next iteration when the change arrive
on next.

Thanks for the comments,
Thomas

>> +{
>> +#ifdef CONFIG_X86_64
>> +       const unsigned long mix_const = 0x5d6008cbf3848dd3UL;
>> +#else
>> +       const unsigned long mix_const = 0x3f39e593UL;
>> +#endif
>> +       unsigned long raw, random = get_boot_seed();
>> +       bool use_i8254 = true;
>> +
>> +       debug_putstr("KASLR using");
>> +
>> +       if (has_cpuflag(X86_FEATURE_RDRAND)) {
>> +               debug_putstr(" RDRAND");
>> +               if (rdrand_long(&raw)) {
>> +                       random ^= raw;
>> +                       use_i8254 = false;
>> +               }
>> +       }
>> +
>> +       if (has_cpuflag(X86_FEATURE_TSC)) {
>> +               debug_putstr(" RDTSC");
>> +               raw = rdtsc();
>> +
>> +               random ^= raw;
>> +               use_i8254 = false;
>> +       }
>> +
>> +       if (use_i8254) {
>> +               debug_putstr(" i8254");
>> +               random ^= i8254();
>> +       }
>> +
>> +       /* Circular multiply for better bit diffusion */
>> +       asm("mul %3"
>> +           : "=a" (random), "=d" (raw)
>> +           : "a" (random), "rm" (mix_const));
>> +       random += raw;
>> +
>> +       debug_putstr("...\n");
>> +
>> +       return random;
>> +}
>> --
>> 2.8.0.rc3.226.g39d4020
>>
>
> -Kees
>
> --
> Kees Cook
> Chrome OS & Brillo Security

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web