Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAJcbSZEHV7ZdDsN=VdKNe0X73Z6kEv-U+TKJG296AwLevwPdVg@mail.gmail.com>
Date: Tue, 10 May 2016 13:10:19 -0700
From: Thomas Garnier <thgarnie@...gle.com>
To: Kees Cook <keescook@...omium.org>
Cc: "H . Peter Anvin" <hpa@...or.com>, Thomas Gleixner <tglx@...utronix.de>, Ingo Molnar <mingo@...hat.com>, 
	Borislav Petkov <bp@...e.de>, Andy Lutomirski <luto@...nel.org>, Dmitry Vyukov <dvyukov@...gle.com>, 
	Paolo Bonzini <pbonzini@...hat.com>, Dan Williams <dan.j.williams@...el.com>, 
	Stephen Smalley <sds@...ho.nsa.gov>, Kefeng Wang <wangkefeng.wang@...wei.com>, 
	Jonathan Corbet <corbet@....net>, Matt Fleming <matt@...eblueprint.co.uk>, 
	Toshi Kani <toshi.kani@....com>, Alexander Kuleshov <kuleshovmail@...il.com>, 
	Alexander Popov <alpopov@...ecurity.com>, Joerg Roedel <jroedel@...e.de>, Dave Young <dyoung@...hat.com>, 
	Baoquan He <bhe@...hat.com>, Dave Hansen <dave.hansen@...ux.intel.com>, 
	Mark Salter <msalter@...hat.com>, Boris Ostrovsky <boris.ostrovsky@...cle.com>, 
	"x86@...nel.org" <x86@...nel.org>, LKML <linux-kernel@...r.kernel.org>, 
	"linux-doc@...r.kernel.org" <linux-doc@...r.kernel.org>, Greg Thelen <gthelen@...gle.com>, 
	"kernel-hardening@...ts.openwall.com" <kernel-hardening@...ts.openwall.com>
Subject: Re: [PATCH v3 1/4] x86, boot: Refactor KASLR entropy functions

On Tue, May 10, 2016 at 12:05 PM, Kees Cook <keescook@...omium.org> wrote:
> On Tue, May 3, 2016 at 12:31 PM, Thomas Garnier <thgarnie@...gle.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@...gle.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

Powered by blists - more mailing lists

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