Re: [PATCH 5/6] x86: kaslr: routines to choose random base offset

2013-04-13 Thread Yinghai Lu
On Fri, Apr 12, 2013 at 1:13 PM, Kees Cook  wrote:
> This provides routines for selecting a randomized kernel base offset,
> bounded by the e820 entries. It tries to use RDRAND and falls back to
> RDTSC. If "noaslr" is on the kernel command line, no offset will be used.
>
> Heavily based on work by Dan Rosenberg and Neill Clift.
>
> Signed-off-by: Kees Cook 
> Cc: Eric Northup 
> ---
>  arch/x86/boot/compressed/Makefile |2 +-
>  arch/x86/boot/compressed/aslr.S   |  228 
> +
>  2 files changed, 229 insertions(+), 1 deletion(-)
>  create mode 100644 arch/x86/boot/compressed/aslr.S
>
> diff --git a/arch/x86/boot/compressed/Makefile 
> b/arch/x86/boot/compressed/Makefile
> index 0dac175..feaf203 100644
> --- a/arch/x86/boot/compressed/Makefile
> +++ b/arch/x86/boot/compressed/Makefile
> @@ -26,7 +26,7 @@ HOST_EXTRACFLAGS += -I$(srctree)/tools/include
>
>  VMLINUX_OBJS = $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \
> $(obj)/string.o $(obj)/cmdline.o $(obj)/early_serial_console.o \
> -   $(obj)/piggy.o
> +   $(obj)/piggy.o $(obj)/aslr.o
>
>  $(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone
>
> diff --git a/arch/x86/boot/compressed/aslr.S b/arch/x86/boot/compressed/aslr.S
> new file mode 100644
> index 000..37cdef4
> --- /dev/null
> +++ b/arch/x86/boot/compressed/aslr.S
> @@ -0,0 +1,228 @@
> +/*
> + *  arch/x86/boot/compressed/aslr.S
> + *
> + * Support routine for Kernel Address Space Layout Randomization used by both
> + * the 32 and 64 bit boot code.
> + *
> + */
> +   .text
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#ifdef CONFIG_RANDOMIZE_BASE
> +
> +   .globl  select_aslr_address
> +   .code32
> +
> +/*
> + * Get the physical memory limit for the run from the physical load position 
> of
> + * the kernel. The kernel loads at LOAD_PHYSICAL_ADDR and we need to know how
> + * much physical memory is available for use after that point to make sure 
> the
> + * relocated kernel will fit. Returns the limit in eax.
> + */
> +get_physical_run_end:
> +   pushl   %edi
> +   pushl   %esi
> +   pushl   %ebx
> +   pushl   %edx
> +   pushl   %ecx
> +   movzbl  BP_e820_entries(%esi), %edi
> +   lealBP_e820_map(%esi), %esi
> +   testl   %edi, %edi
> +   jz  5f
> +1: cmpl$E820_RAM, E820_type(%esi)
> +   jnz 4f
> +   movlE820_addr(%esi), %eax
> +   movlE820_addr+4(%esi), %edx
> +   testl   %edx, %edx /* Start address is too big for 32 bit */
> +   jnz 4f
> +   cmpl$LOAD_PHYSICAL_ADDR, %eax
> +   ja  4f
> +   movlE820_size(%esi), %ecx
> +   movlE820_size+4(%esi), %ebx
> +   addl%eax, %ecx
> +   adcl%edx, %ebx
> +   jz  2f /* end address not beyond 32bit*/
> +/* For a large run set the limit as 2^32-1 */
> +   xorl%ecx, %ecx
> +   decl%ecx
> +   jmp 3f
> +2: cmpl$LOAD_PHYSICAL_ADDR, %ecx
> +   jb  4f
> +3:
> +   movl%ecx, %eax
> +   jmp 6f
> +
> +4: addl$E820_entry_size, %esi
> +   decl%edi
> +   jnz 1b
> +5: xorl%eax, %eax /* Fail */
> +6: popl%ecx
> +   popl%edx
> +   popl%ebx
> +   popl%esi
> +   popl%edi
> +   ret
> +
> +/*
> + * Get a random value to be used for the ASLR kernel offset.
> + * Returns the value in eax.
> + */
> +get_aslr_offset:
> +   pushl   %ebx
> +   pushl   %edx
> +   pushl   %ecx
> +   callfind_cmdline_option
> +   testl   %eax, %eax
> +   jne 4f
> +   /* Standard check for cpuid */
> +   pushfl  /* Push original flags */
> +   pushfl
> +   popl%eax
> +   movl%eax, %ebx
> +   xorl$X86_EFLAGS_ID, %eax
> +   pushl   %eax
> +   popfl
> +   pushfl
> +   popl%eax
> +   popfl   /* Pop original flags */
> +   cmpl%eax, %ebx
> +   /* Say zero offset if we can't change the flag */
> +   movl$0, %eax
> +   je  4f
> +
> +   /* Check for cpuid 1 */
> +   cpuid
> +   cmpl$0x1, %eax
> +   jb  4f
> +
> +   movl$0x1, %eax
> +   cpuid
> +   xor %eax, %eax
> +
> +   /* RDRAND is bit 30 */
> +   btl $(X86_FEATURE_RDRAND & 31), %ecx
> +   jc  1f
> +
> +   /* RDTSC is bit 4 */
> +   btl $(X86_FEATURE_TSC & 31), %edx
> +   jc  3f
> +
> +   /* Nothing is supported */
> +   jmp 4f
> +1:
> +   /*
> +* RDRAND sets carry bit on success, otherwise we should try
> +* again up to 16 times.
> +*/
> +   movl$0x10, %ecx
> +2:
> +   /* rdrand %eax */
> +   .byte   0x0f, 0xc7, 0xf0
> +   jc  4f
> +   loop2b
> +
> +   /* Fall through: if RDRAND is supported but fails, use RDTSC,
> +* which is guaranteed to be supported.
> +*/
> +3:
> +   rdtsc
> 

Re: [PATCH 5/6] x86: kaslr: routines to choose random base offset

2013-04-13 Thread Yinghai Lu
On Fri, Apr 12, 2013 at 1:13 PM, Kees Cook keesc...@chromium.org wrote:
 This provides routines for selecting a randomized kernel base offset,
 bounded by the e820 entries. It tries to use RDRAND and falls back to
 RDTSC. If noaslr is on the kernel command line, no offset will be used.

 Heavily based on work by Dan Rosenberg and Neill Clift.

 Signed-off-by: Kees Cook keesc...@chromium.org
 Cc: Eric Northup digitale...@google.com
 ---
  arch/x86/boot/compressed/Makefile |2 +-
  arch/x86/boot/compressed/aslr.S   |  228 
 +
  2 files changed, 229 insertions(+), 1 deletion(-)
  create mode 100644 arch/x86/boot/compressed/aslr.S

 diff --git a/arch/x86/boot/compressed/Makefile 
 b/arch/x86/boot/compressed/Makefile
 index 0dac175..feaf203 100644
 --- a/arch/x86/boot/compressed/Makefile
 +++ b/arch/x86/boot/compressed/Makefile
 @@ -26,7 +26,7 @@ HOST_EXTRACFLAGS += -I$(srctree)/tools/include

  VMLINUX_OBJS = $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \
 $(obj)/string.o $(obj)/cmdline.o $(obj)/early_serial_console.o \
 -   $(obj)/piggy.o
 +   $(obj)/piggy.o $(obj)/aslr.o

  $(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone

 diff --git a/arch/x86/boot/compressed/aslr.S b/arch/x86/boot/compressed/aslr.S
 new file mode 100644
 index 000..37cdef4
 --- /dev/null
 +++ b/arch/x86/boot/compressed/aslr.S
 @@ -0,0 +1,228 @@
 +/*
 + *  arch/x86/boot/compressed/aslr.S
 + *
 + * Support routine for Kernel Address Space Layout Randomization used by both
 + * the 32 and 64 bit boot code.
 + *
 + */
 +   .text
 +
 +#include asm/boot.h
 +#include asm/asm-offsets.h
 +#include asm/cpufeature.h
 +#include asm/processor-flags.h
 +#include asm/e820.h
 +
 +#ifdef CONFIG_RANDOMIZE_BASE
 +
 +   .globl  select_aslr_address
 +   .code32
 +
 +/*
 + * Get the physical memory limit for the run from the physical load position 
 of
 + * the kernel. The kernel loads at LOAD_PHYSICAL_ADDR and we need to know how
 + * much physical memory is available for use after that point to make sure 
 the
 + * relocated kernel will fit. Returns the limit in eax.
 + */
 +get_physical_run_end:
 +   pushl   %edi
 +   pushl   %esi
 +   pushl   %ebx
 +   pushl   %edx
 +   pushl   %ecx
 +   movzbl  BP_e820_entries(%esi), %edi
 +   lealBP_e820_map(%esi), %esi
 +   testl   %edi, %edi
 +   jz  5f
 +1: cmpl$E820_RAM, E820_type(%esi)
 +   jnz 4f
 +   movlE820_addr(%esi), %eax
 +   movlE820_addr+4(%esi), %edx
 +   testl   %edx, %edx /* Start address is too big for 32 bit */
 +   jnz 4f
 +   cmpl$LOAD_PHYSICAL_ADDR, %eax
 +   ja  4f
 +   movlE820_size(%esi), %ecx
 +   movlE820_size+4(%esi), %ebx
 +   addl%eax, %ecx
 +   adcl%edx, %ebx
 +   jz  2f /* end address not beyond 32bit*/
 +/* For a large run set the limit as 2^32-1 */
 +   xorl%ecx, %ecx
 +   decl%ecx
 +   jmp 3f
 +2: cmpl$LOAD_PHYSICAL_ADDR, %ecx
 +   jb  4f
 +3:
 +   movl%ecx, %eax
 +   jmp 6f
 +
 +4: addl$E820_entry_size, %esi
 +   decl%edi
 +   jnz 1b
 +5: xorl%eax, %eax /* Fail */
 +6: popl%ecx
 +   popl%edx
 +   popl%ebx
 +   popl%esi
 +   popl%edi
 +   ret
 +
 +/*
 + * Get a random value to be used for the ASLR kernel offset.
 + * Returns the value in eax.
 + */
 +get_aslr_offset:
 +   pushl   %ebx
 +   pushl   %edx
 +   pushl   %ecx
 +   callfind_cmdline_option
 +   testl   %eax, %eax
 +   jne 4f
 +   /* Standard check for cpuid */
 +   pushfl  /* Push original flags */
 +   pushfl
 +   popl%eax
 +   movl%eax, %ebx
 +   xorl$X86_EFLAGS_ID, %eax
 +   pushl   %eax
 +   popfl
 +   pushfl
 +   popl%eax
 +   popfl   /* Pop original flags */
 +   cmpl%eax, %ebx
 +   /* Say zero offset if we can't change the flag */
 +   movl$0, %eax
 +   je  4f
 +
 +   /* Check for cpuid 1 */
 +   cpuid
 +   cmpl$0x1, %eax
 +   jb  4f
 +
 +   movl$0x1, %eax
 +   cpuid
 +   xor %eax, %eax
 +
 +   /* RDRAND is bit 30 */
 +   btl $(X86_FEATURE_RDRAND  31), %ecx
 +   jc  1f
 +
 +   /* RDTSC is bit 4 */
 +   btl $(X86_FEATURE_TSC  31), %edx
 +   jc  3f
 +
 +   /* Nothing is supported */
 +   jmp 4f
 +1:
 +   /*
 +* RDRAND sets carry bit on success, otherwise we should try
 +* again up to 16 times.
 +*/
 +   movl$0x10, %ecx
 +2:
 +   /* rdrand %eax */
 +   .byte   0x0f, 0xc7, 0xf0
 +   jc  4f
 +   loop2b
 +
 +   /* Fall through: if RDRAND is supported but fails, use RDTSC,
 +* which is guaranteed to be supported.
 +*/
 +3:
 +   rdtsc
 +   /*
 +* Since this is 

[PATCH 5/6] x86: kaslr: routines to choose random base offset

2013-04-12 Thread Kees Cook
This provides routines for selecting a randomized kernel base offset,
bounded by the e820 entries. It tries to use RDRAND and falls back to
RDTSC. If "noaslr" is on the kernel command line, no offset will be used.

Heavily based on work by Dan Rosenberg and Neill Clift.

Signed-off-by: Kees Cook 
Cc: Eric Northup 
---
 arch/x86/boot/compressed/Makefile |2 +-
 arch/x86/boot/compressed/aslr.S   |  228 +
 2 files changed, 229 insertions(+), 1 deletion(-)
 create mode 100644 arch/x86/boot/compressed/aslr.S

diff --git a/arch/x86/boot/compressed/Makefile 
b/arch/x86/boot/compressed/Makefile
index 0dac175..feaf203 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -26,7 +26,7 @@ HOST_EXTRACFLAGS += -I$(srctree)/tools/include
 
 VMLINUX_OBJS = $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \
$(obj)/string.o $(obj)/cmdline.o $(obj)/early_serial_console.o \
-   $(obj)/piggy.o
+   $(obj)/piggy.o $(obj)/aslr.o
 
 $(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone
 
diff --git a/arch/x86/boot/compressed/aslr.S b/arch/x86/boot/compressed/aslr.S
new file mode 100644
index 000..37cdef4
--- /dev/null
+++ b/arch/x86/boot/compressed/aslr.S
@@ -0,0 +1,228 @@
+/*
+ *  arch/x86/boot/compressed/aslr.S
+ *
+ * Support routine for Kernel Address Space Layout Randomization used by both
+ * the 32 and 64 bit boot code.
+ *
+ */
+   .text
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#ifdef CONFIG_RANDOMIZE_BASE
+
+   .globl  select_aslr_address
+   .code32
+
+/*
+ * Get the physical memory limit for the run from the physical load position of
+ * the kernel. The kernel loads at LOAD_PHYSICAL_ADDR and we need to know how
+ * much physical memory is available for use after that point to make sure the
+ * relocated kernel will fit. Returns the limit in eax.
+ */
+get_physical_run_end:
+   pushl   %edi
+   pushl   %esi
+   pushl   %ebx
+   pushl   %edx
+   pushl   %ecx
+   movzbl  BP_e820_entries(%esi), %edi
+   lealBP_e820_map(%esi), %esi
+   testl   %edi, %edi
+   jz  5f
+1: cmpl$E820_RAM, E820_type(%esi)
+   jnz 4f
+   movlE820_addr(%esi), %eax
+   movlE820_addr+4(%esi), %edx
+   testl   %edx, %edx /* Start address is too big for 32 bit */
+   jnz 4f
+   cmpl$LOAD_PHYSICAL_ADDR, %eax
+   ja  4f
+   movlE820_size(%esi), %ecx
+   movlE820_size+4(%esi), %ebx
+   addl%eax, %ecx
+   adcl%edx, %ebx
+   jz  2f /* end address not beyond 32bit*/
+/* For a large run set the limit as 2^32-1 */
+   xorl%ecx, %ecx
+   decl%ecx
+   jmp 3f
+2: cmpl$LOAD_PHYSICAL_ADDR, %ecx
+   jb  4f
+3:
+   movl%ecx, %eax
+   jmp 6f
+
+4: addl$E820_entry_size, %esi
+   decl%edi
+   jnz 1b
+5: xorl%eax, %eax /* Fail */
+6: popl%ecx
+   popl%edx
+   popl%ebx
+   popl%esi
+   popl%edi
+   ret
+
+/*
+ * Get a random value to be used for the ASLR kernel offset.
+ * Returns the value in eax.
+ */
+get_aslr_offset:
+   pushl   %ebx
+   pushl   %edx
+   pushl   %ecx
+   callfind_cmdline_option
+   testl   %eax, %eax
+   jne 4f
+   /* Standard check for cpuid */
+   pushfl  /* Push original flags */
+   pushfl
+   popl%eax
+   movl%eax, %ebx
+   xorl$X86_EFLAGS_ID, %eax
+   pushl   %eax
+   popfl
+   pushfl
+   popl%eax
+   popfl   /* Pop original flags */
+   cmpl%eax, %ebx
+   /* Say zero offset if we can't change the flag */
+   movl$0, %eax
+   je  4f
+
+   /* Check for cpuid 1 */
+   cpuid
+   cmpl$0x1, %eax
+   jb  4f
+
+   movl$0x1, %eax
+   cpuid
+   xor %eax, %eax
+
+   /* RDRAND is bit 30 */
+   btl $(X86_FEATURE_RDRAND & 31), %ecx
+   jc  1f
+
+   /* RDTSC is bit 4 */
+   btl $(X86_FEATURE_TSC & 31), %edx
+   jc  3f
+
+   /* Nothing is supported */
+   jmp 4f
+1:
+   /*
+* RDRAND sets carry bit on success, otherwise we should try
+* again up to 16 times.
+*/
+   movl$0x10, %ecx
+2:
+   /* rdrand %eax */
+   .byte   0x0f, 0xc7, 0xf0
+   jc  4f
+   loop2b
+
+   /* Fall through: if RDRAND is supported but fails, use RDTSC,
+* which is guaranteed to be supported.
+*/
+3:
+   rdtsc
+   /*
+* Since this is time related get some of the least significant bits
+* past the alignment mask
+   */
+   shll$0x0c, %eax
+   /* Fix the maximal offset allowed */
+4: andl$CONFIG_RANDOMIZE_BASE_MAX_OFFSET-1, %eax
+   popl%ecx
+   popl%edx
+   popl%ebx
+   ret
+
+/*
+ * Select the ASLR address to use. We 

[PATCH 5/6] x86: kaslr: routines to choose random base offset

2013-04-12 Thread Kees Cook
This provides routines for selecting a randomized kernel base offset,
bounded by the e820 entries. It tries to use RDRAND and falls back to
RDTSC. If noaslr is on the kernel command line, no offset will be used.

Heavily based on work by Dan Rosenberg and Neill Clift.

Signed-off-by: Kees Cook keesc...@chromium.org
Cc: Eric Northup digitale...@google.com
---
 arch/x86/boot/compressed/Makefile |2 +-
 arch/x86/boot/compressed/aslr.S   |  228 +
 2 files changed, 229 insertions(+), 1 deletion(-)
 create mode 100644 arch/x86/boot/compressed/aslr.S

diff --git a/arch/x86/boot/compressed/Makefile 
b/arch/x86/boot/compressed/Makefile
index 0dac175..feaf203 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -26,7 +26,7 @@ HOST_EXTRACFLAGS += -I$(srctree)/tools/include
 
 VMLINUX_OBJS = $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \
$(obj)/string.o $(obj)/cmdline.o $(obj)/early_serial_console.o \
-   $(obj)/piggy.o
+   $(obj)/piggy.o $(obj)/aslr.o
 
 $(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone
 
diff --git a/arch/x86/boot/compressed/aslr.S b/arch/x86/boot/compressed/aslr.S
new file mode 100644
index 000..37cdef4
--- /dev/null
+++ b/arch/x86/boot/compressed/aslr.S
@@ -0,0 +1,228 @@
+/*
+ *  arch/x86/boot/compressed/aslr.S
+ *
+ * Support routine for Kernel Address Space Layout Randomization used by both
+ * the 32 and 64 bit boot code.
+ *
+ */
+   .text
+
+#include asm/boot.h
+#include asm/asm-offsets.h
+#include asm/cpufeature.h
+#include asm/processor-flags.h
+#include asm/e820.h
+
+#ifdef CONFIG_RANDOMIZE_BASE
+
+   .globl  select_aslr_address
+   .code32
+
+/*
+ * Get the physical memory limit for the run from the physical load position of
+ * the kernel. The kernel loads at LOAD_PHYSICAL_ADDR and we need to know how
+ * much physical memory is available for use after that point to make sure the
+ * relocated kernel will fit. Returns the limit in eax.
+ */
+get_physical_run_end:
+   pushl   %edi
+   pushl   %esi
+   pushl   %ebx
+   pushl   %edx
+   pushl   %ecx
+   movzbl  BP_e820_entries(%esi), %edi
+   lealBP_e820_map(%esi), %esi
+   testl   %edi, %edi
+   jz  5f
+1: cmpl$E820_RAM, E820_type(%esi)
+   jnz 4f
+   movlE820_addr(%esi), %eax
+   movlE820_addr+4(%esi), %edx
+   testl   %edx, %edx /* Start address is too big for 32 bit */
+   jnz 4f
+   cmpl$LOAD_PHYSICAL_ADDR, %eax
+   ja  4f
+   movlE820_size(%esi), %ecx
+   movlE820_size+4(%esi), %ebx
+   addl%eax, %ecx
+   adcl%edx, %ebx
+   jz  2f /* end address not beyond 32bit*/
+/* For a large run set the limit as 2^32-1 */
+   xorl%ecx, %ecx
+   decl%ecx
+   jmp 3f
+2: cmpl$LOAD_PHYSICAL_ADDR, %ecx
+   jb  4f
+3:
+   movl%ecx, %eax
+   jmp 6f
+
+4: addl$E820_entry_size, %esi
+   decl%edi
+   jnz 1b
+5: xorl%eax, %eax /* Fail */
+6: popl%ecx
+   popl%edx
+   popl%ebx
+   popl%esi
+   popl%edi
+   ret
+
+/*
+ * Get a random value to be used for the ASLR kernel offset.
+ * Returns the value in eax.
+ */
+get_aslr_offset:
+   pushl   %ebx
+   pushl   %edx
+   pushl   %ecx
+   callfind_cmdline_option
+   testl   %eax, %eax
+   jne 4f
+   /* Standard check for cpuid */
+   pushfl  /* Push original flags */
+   pushfl
+   popl%eax
+   movl%eax, %ebx
+   xorl$X86_EFLAGS_ID, %eax
+   pushl   %eax
+   popfl
+   pushfl
+   popl%eax
+   popfl   /* Pop original flags */
+   cmpl%eax, %ebx
+   /* Say zero offset if we can't change the flag */
+   movl$0, %eax
+   je  4f
+
+   /* Check for cpuid 1 */
+   cpuid
+   cmpl$0x1, %eax
+   jb  4f
+
+   movl$0x1, %eax
+   cpuid
+   xor %eax, %eax
+
+   /* RDRAND is bit 30 */
+   btl $(X86_FEATURE_RDRAND  31), %ecx
+   jc  1f
+
+   /* RDTSC is bit 4 */
+   btl $(X86_FEATURE_TSC  31), %edx
+   jc  3f
+
+   /* Nothing is supported */
+   jmp 4f
+1:
+   /*
+* RDRAND sets carry bit on success, otherwise we should try
+* again up to 16 times.
+*/
+   movl$0x10, %ecx
+2:
+   /* rdrand %eax */
+   .byte   0x0f, 0xc7, 0xf0
+   jc  4f
+   loop2b
+
+   /* Fall through: if RDRAND is supported but fails, use RDTSC,
+* which is guaranteed to be supported.
+*/
+3:
+   rdtsc
+   /*
+* Since this is time related get some of the least significant bits
+* past the alignment mask
+   */
+   shll$0x0c, %eax
+   /* Fix the maximal offset allowed */
+4: andl$CONFIG_RANDOMIZE_BASE_MAX_OFFSET-1, %eax
+