Re: [PATCH v3 2/7] x86, boot: Move ZO to end of buffer

2015-03-10 Thread Kees Cook
On Tue, Mar 10, 2015 at 1:00 AM, Borislav Petkov  wrote:
> Final patch:
>
> ---
> From: Yinghai Lu 
> Date: Sat, 7 Mar 2015 14:07:16 -0800
> Subject: [PATCH] x86/setup: Move compressed kernel to the end of the buffer
>
> Boris found that passing KASLR status through setup_data from the boot
> stage cannot be used later in the kernel stage, see commit
>
>   f47233c2d34f ("x86/mm/ASLR: Propagate base load address calculation")
>
> Here's some background:
>
> The boot loader allocates a buffer of size init_size in concordance with
> the value passed in the setup header and it loads the compressed, i.e.
> first kernel (arch/x86/boot/compressed/vmlinux) in it.
>
> First kernel then moves itself somewhere around the middle of the
> buffer at z_extract_offset to make sure that the decompressor does not
> overwrite input data.
>
> After the decompressor is finished, kernel proper (vmlinux) uses the
> whole buffer from the beginning and the compressed kernel's code and
> data section is overlapped with the kernel proper's bss section.
>
> Later on, clear_bss() in kernel proper clears .bss before code in
> arch/x86/kernel/setup.c can access setup_data passed in the first,
> compressed kernel.
>
> To make sure that data survives, we should avoid the overlapping.
>
> As a first step, move the first kernel closer to the end of the buffer
> instead of the middle. As a result, this will place first kernel's data
> area out of kernel proper's .bss area.
>
> This way we can find out where the data section of the copied first
> kernel is instead of guessing. In addition, it will make the KASLR
> mem_avoid array preparation for the search of a fitting buffer much
> simpler.
>
> While at it, rename z_extract_offset to z_min_extract_offset as it is
> actually the minimum extract offset now.
>
> In order to keep the final extract offset page-aligned we need to
> make both kernels' _end markers page-aligned too so that init_size is
> page-aligned as a result.
>
> Signed-off-by: Yinghai Lu 
> Cc: "H. Peter Anvin" 
> Cc: Matt Fleming 
> Cc: Kees Cook 
> Cc: Thomas Gleixner 
> Cc: Jiri Kosina 
> Cc: linux-...@vger.kernel.org
> Cc: Ingo Molnar 
> Cc: Baoquan He 
> Fixes: f47233c2d34f ("x86/mm/ASLR: Propagate base load address calculation")
> Link: 
> http://lkml.kernel.org/r/1425766041-6551-3-git-send-email-ying...@kernel.org
> [ Commit message massively rewritten ]

Acked-by: Kees Cook 

Thanks!

-Kees

> Signed-off-by:
> ---
>  arch/x86/boot/compressed/head_32.S | 11 +--
>  arch/x86/boot/compressed/head_64.S |  8 ++--
>  arch/x86/boot/compressed/mkpiggy.c |  7 ++-
>  arch/x86/boot/compressed/vmlinux.lds.S |  1 +
>  arch/x86/boot/header.S |  2 +-
>  arch/x86/kernel/asm-offsets.c  |  1 +
>  arch/x86/kernel/vmlinux.lds.S  |  1 +
>  7 files changed, 21 insertions(+), 10 deletions(-)
>
> diff --git a/arch/x86/boot/compressed/head_32.S 
> b/arch/x86/boot/compressed/head_32.S
> index cbed1407a5cd..a9b56f1d8e75 100644
> --- a/arch/x86/boot/compressed/head_32.S
> +++ b/arch/x86/boot/compressed/head_32.S
> @@ -147,7 +147,9 @@ preferred_addr:
>  1:
>
> /* Target address to relocate to for decompression */
> -   addl$z_extract_offset, %ebx
> +   movlBP_init_size(%esi), %eax
> +   subl$_end, %eax
> +   addl%eax, %ebx
>
> /* Set up the stack */
> lealboot_stack_end(%ebx), %esp
> @@ -208,8 +210,13 @@ relocated:
>   */
> /* push arguments for decompress_kernel: */
> pushl   $z_output_len   /* decompressed length */
> -   lealz_extract_offset_negative(%ebx), %ebp
> +
> +   movlBP_init_size(%esi), %eax
> +   subl$_end, %eax
> +   movl%ebx, %ebp
> +   subl%eax, %ebp
> pushl   %ebp/* output address */
> +
> pushl   $z_input_len/* input_len */
> lealinput_data(%ebx), %eax
> pushl   %eax/* input_data */
> diff --git a/arch/x86/boot/compressed/head_64.S 
> b/arch/x86/boot/compressed/head_64.S
> index 2884e0c3e8a5..69015b576cf6 100644
> --- a/arch/x86/boot/compressed/head_64.S
> +++ b/arch/x86/boot/compressed/head_64.S
> @@ -101,7 +101,9 @@ ENTRY(startup_32)
>  1:
>
> /* Target address to relocate to for decompression */
> -   addl$z_extract_offset, %ebx
> +   movlBP_init_size(%esi), %eax
> +   subl$_end, %eax
> +   addl%eax, %ebx
>
>  /*
>   * Prepare for entering 64 bit mode
> @@ -329,7 +331,9 @@ preferred_addr:
>  1:
>
> /* Target address to relocate to for decompression */
> -   leaqz_extract_offset(%rbp), %rbx
> +   movlBP_init_size(%rsi), %ebx
> +   subl$_end, %ebx
> +   addq%rbp, %rbx
>
> /* Set up the stack */
> leaqboot_stack_end(%rbx), %rsp
> diff --git a/arch/x86/boot/compressed/mkpiggy.c 
> b/arch/x86/boot/compressed/mkpiggy.c
> index b669ab65bf6c..c03b0097ce58 100644
> --- 

Re: [PATCH v3 2/7] x86, boot: Move ZO to end of buffer

2015-03-10 Thread Borislav Petkov
On Tue, Mar 10, 2015 at 08:11:03AM -0700, Yinghai Lu wrote:
> Also stop using "compressed kernel" please, that is confusing.

Why?

> Just use
> 
> ZO: arch/x86/boot/compressed/vmlinux
> VO: vmlinux

and this is not confusing?

Yeah, right.

-- 
Regards/Gruss,
Boris.

ECO tip #101: Trim your mails when you reply.
--
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v3 2/7] x86, boot: Move ZO to end of buffer

2015-03-10 Thread Yinghai Lu
On Tue, Mar 10, 2015 at 1:00 AM, Borislav Petkov  wrote:
> Final patch:
>
> ---
> From: Yinghai Lu 
> Date: Sat, 7 Mar 2015 14:07:16 -0800
> Subject: [PATCH] x86/setup: Move compressed kernel to the end of the buffer

setup should only about arch/x86/boot/setup.ld related.

So please keep x86, boot.

Also stop using "compressed kernel" please, that is confusing.

Just use

ZO: arch/x86/boot/compressed/vmlinux
VO: vmlinux

Thanks

Yinghai
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v3 2/7] x86, boot: Move ZO to end of buffer

2015-03-10 Thread Borislav Petkov
On Tue, Mar 10, 2015 at 10:34:31AM +0100, Jiri Kosina wrote:
> Thanks a lot for fixing my oversight.

Bah, it was my suggestion to use setup_data in the first place, sorry
about that.

-- 
Regards/Gruss,
Boris.

ECO tip #101: Trim your mails when you reply.
--
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v3 2/7] x86, boot: Move ZO to end of buffer

2015-03-10 Thread Jiri Kosina
On Tue, 10 Mar 2015, Borislav Petkov wrote:

> Final patch:
> 
> ---
> From: Yinghai Lu 
> Date: Sat, 7 Mar 2015 14:07:16 -0800
> Subject: [PATCH] x86/setup: Move compressed kernel to the end of the buffer
[ ... ]
> Signed-off-by: Yinghai Lu 
> Cc: "H. Peter Anvin" 
> Cc: Matt Fleming 
> Cc: Kees Cook 
> Cc: Thomas Gleixner 
> Cc: Jiri Kosina 
> Cc: linux-...@vger.kernel.org
> Cc: Ingo Molnar 
> Cc: Baoquan He 
> Fixes: f47233c2d34f ("x86/mm/ASLR: Propagate base load address calculation")

Thanks a lot for fixing my oversight.

Acked-by: Jiri Kosina 

> Link: 
> http://lkml.kernel.org/r/1425766041-6551-3-git-send-email-ying...@kernel.org
> [ Commit message massively rewritten ]
> Signed-off-by: 
> ---
>  arch/x86/boot/compressed/head_32.S | 11 +--
>  arch/x86/boot/compressed/head_64.S |  8 ++--
>  arch/x86/boot/compressed/mkpiggy.c |  7 ++-
>  arch/x86/boot/compressed/vmlinux.lds.S |  1 +
>  arch/x86/boot/header.S |  2 +-
>  arch/x86/kernel/asm-offsets.c  |  1 +
>  arch/x86/kernel/vmlinux.lds.S  |  1 +
>  7 files changed, 21 insertions(+), 10 deletions(-)
> 
> diff --git a/arch/x86/boot/compressed/head_32.S 
> b/arch/x86/boot/compressed/head_32.S
> index cbed1407a5cd..a9b56f1d8e75 100644
> --- a/arch/x86/boot/compressed/head_32.S
> +++ b/arch/x86/boot/compressed/head_32.S
> @@ -147,7 +147,9 @@ preferred_addr:
>  1:
>  
>   /* Target address to relocate to for decompression */
> - addl$z_extract_offset, %ebx
> + movlBP_init_size(%esi), %eax
> + subl$_end, %eax
> + addl%eax, %ebx
>  
>   /* Set up the stack */
>   lealboot_stack_end(%ebx), %esp
> @@ -208,8 +210,13 @@ relocated:
>   */
>   /* push arguments for decompress_kernel: */
>   pushl   $z_output_len   /* decompressed length */
> - lealz_extract_offset_negative(%ebx), %ebp
> +
> + movlBP_init_size(%esi), %eax
> + subl$_end, %eax
> + movl%ebx, %ebp
> + subl%eax, %ebp
>   pushl   %ebp/* output address */
> +
>   pushl   $z_input_len/* input_len */
>   lealinput_data(%ebx), %eax
>   pushl   %eax/* input_data */
> diff --git a/arch/x86/boot/compressed/head_64.S 
> b/arch/x86/boot/compressed/head_64.S
> index 2884e0c3e8a5..69015b576cf6 100644
> --- a/arch/x86/boot/compressed/head_64.S
> +++ b/arch/x86/boot/compressed/head_64.S
> @@ -101,7 +101,9 @@ ENTRY(startup_32)
>  1:
>  
>   /* Target address to relocate to for decompression */
> - addl$z_extract_offset, %ebx
> + movlBP_init_size(%esi), %eax
> + subl$_end, %eax
> + addl%eax, %ebx
>  
>  /*
>   * Prepare for entering 64 bit mode
> @@ -329,7 +331,9 @@ preferred_addr:
>  1:
>  
>   /* Target address to relocate to for decompression */
> - leaqz_extract_offset(%rbp), %rbx
> + movlBP_init_size(%rsi), %ebx
> + subl$_end, %ebx
> + addq%rbp, %rbx
>  
>   /* Set up the stack */
>   leaqboot_stack_end(%rbx), %rsp
> diff --git a/arch/x86/boot/compressed/mkpiggy.c 
> b/arch/x86/boot/compressed/mkpiggy.c
> index b669ab65bf6c..c03b0097ce58 100644
> --- a/arch/x86/boot/compressed/mkpiggy.c
> +++ b/arch/x86/boot/compressed/mkpiggy.c
> @@ -80,11 +80,8 @@ int main(int argc, char *argv[])
>   printf("z_input_len = %lu\n", ilen);
>   printf(".globl z_output_len\n");
>   printf("z_output_len = %lu\n", (unsigned long)olen);
> - printf(".globl z_extract_offset\n");
> - printf("z_extract_offset = 0x%lx\n", offs);
> - /* z_extract_offset_negative allows simplification of head_32.S */
> - printf(".globl z_extract_offset_negative\n");
> - printf("z_extract_offset_negative = -0x%lx\n", offs);
> + printf(".globl z_min_extract_offset\n");
> + printf("z_min_extract_offset = 0x%lx\n", offs);
>  
>   printf(".globl input_data, input_data_end\n");
>   printf("input_data:\n");
> diff --git a/arch/x86/boot/compressed/vmlinux.lds.S 
> b/arch/x86/boot/compressed/vmlinux.lds.S
> index 34d047c98284..a80acabb80ec 100644
> --- a/arch/x86/boot/compressed/vmlinux.lds.S
> +++ b/arch/x86/boot/compressed/vmlinux.lds.S
> @@ -70,5 +70,6 @@ SECTIONS
>   _epgtable = . ;
>   }
>  #endif
> + . = ALIGN(PAGE_SIZE);   /* keep size page-aligned */
>   _end = .;
>  }
> diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
> index 16ef02596db2..9bfab22efdf7 100644
> --- a/arch/x86/boot/header.S
> +++ b/arch/x86/boot/header.S
> @@ -440,7 +440,7 @@ setup_data:   .quad 0 # 
> 64-bit physical pointer to
>  
>  pref_address:.quad LOAD_PHYSICAL_ADDR# preferred 
> load addr
>  
> -#define ZO_INIT_SIZE (ZO__end - ZO_startup_32 + ZO_z_extract_offset)
> +#define ZO_INIT_SIZE (ZO__end - ZO_startup_32 + ZO_z_min_extract_offset)
>  #define VO_INIT_SIZE (VO__end - VO__text)
>  #if ZO_INIT_SIZE > VO_INIT_SIZE
>  #define INIT_SIZE 

Re: [PATCH v3 2/7] x86, boot: Move ZO to end of buffer

2015-03-10 Thread Borislav Petkov
Final patch:

---
From: Yinghai Lu 
Date: Sat, 7 Mar 2015 14:07:16 -0800
Subject: [PATCH] x86/setup: Move compressed kernel to the end of the buffer

Boris found that passing KASLR status through setup_data from the boot
stage cannot be used later in the kernel stage, see commit

  f47233c2d34f ("x86/mm/ASLR: Propagate base load address calculation")

Here's some background:

The boot loader allocates a buffer of size init_size in concordance with
the value passed in the setup header and it loads the compressed, i.e.
first kernel (arch/x86/boot/compressed/vmlinux) in it.

First kernel then moves itself somewhere around the middle of the
buffer at z_extract_offset to make sure that the decompressor does not
overwrite input data.

After the decompressor is finished, kernel proper (vmlinux) uses the
whole buffer from the beginning and the compressed kernel's code and
data section is overlapped with the kernel proper's bss section.

Later on, clear_bss() in kernel proper clears .bss before code in
arch/x86/kernel/setup.c can access setup_data passed in the first,
compressed kernel.

To make sure that data survives, we should avoid the overlapping.

As a first step, move the first kernel closer to the end of the buffer
instead of the middle. As a result, this will place first kernel's data
area out of kernel proper's .bss area.

This way we can find out where the data section of the copied first
kernel is instead of guessing. In addition, it will make the KASLR
mem_avoid array preparation for the search of a fitting buffer much
simpler.

While at it, rename z_extract_offset to z_min_extract_offset as it is
actually the minimum extract offset now.

In order to keep the final extract offset page-aligned we need to
make both kernels' _end markers page-aligned too so that init_size is
page-aligned as a result.

Signed-off-by: Yinghai Lu 
Cc: "H. Peter Anvin" 
Cc: Matt Fleming 
Cc: Kees Cook 
Cc: Thomas Gleixner 
Cc: Jiri Kosina 
Cc: linux-...@vger.kernel.org
Cc: Ingo Molnar 
Cc: Baoquan He 
Fixes: f47233c2d34f ("x86/mm/ASLR: Propagate base load address calculation")
Link: 
http://lkml.kernel.org/r/1425766041-6551-3-git-send-email-ying...@kernel.org
[ Commit message massively rewritten ]
Signed-off-by: 
---
 arch/x86/boot/compressed/head_32.S | 11 +--
 arch/x86/boot/compressed/head_64.S |  8 ++--
 arch/x86/boot/compressed/mkpiggy.c |  7 ++-
 arch/x86/boot/compressed/vmlinux.lds.S |  1 +
 arch/x86/boot/header.S |  2 +-
 arch/x86/kernel/asm-offsets.c  |  1 +
 arch/x86/kernel/vmlinux.lds.S  |  1 +
 7 files changed, 21 insertions(+), 10 deletions(-)

diff --git a/arch/x86/boot/compressed/head_32.S 
b/arch/x86/boot/compressed/head_32.S
index cbed1407a5cd..a9b56f1d8e75 100644
--- a/arch/x86/boot/compressed/head_32.S
+++ b/arch/x86/boot/compressed/head_32.S
@@ -147,7 +147,9 @@ preferred_addr:
 1:
 
/* Target address to relocate to for decompression */
-   addl$z_extract_offset, %ebx
+   movlBP_init_size(%esi), %eax
+   subl$_end, %eax
+   addl%eax, %ebx
 
/* Set up the stack */
lealboot_stack_end(%ebx), %esp
@@ -208,8 +210,13 @@ relocated:
  */
/* push arguments for decompress_kernel: */
pushl   $z_output_len   /* decompressed length */
-   lealz_extract_offset_negative(%ebx), %ebp
+
+   movlBP_init_size(%esi), %eax
+   subl$_end, %eax
+   movl%ebx, %ebp
+   subl%eax, %ebp
pushl   %ebp/* output address */
+
pushl   $z_input_len/* input_len */
lealinput_data(%ebx), %eax
pushl   %eax/* input_data */
diff --git a/arch/x86/boot/compressed/head_64.S 
b/arch/x86/boot/compressed/head_64.S
index 2884e0c3e8a5..69015b576cf6 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -101,7 +101,9 @@ ENTRY(startup_32)
 1:
 
/* Target address to relocate to for decompression */
-   addl$z_extract_offset, %ebx
+   movlBP_init_size(%esi), %eax
+   subl$_end, %eax
+   addl%eax, %ebx
 
 /*
  * Prepare for entering 64 bit mode
@@ -329,7 +331,9 @@ preferred_addr:
 1:
 
/* Target address to relocate to for decompression */
-   leaqz_extract_offset(%rbp), %rbx
+   movlBP_init_size(%rsi), %ebx
+   subl$_end, %ebx
+   addq%rbp, %rbx
 
/* Set up the stack */
leaqboot_stack_end(%rbx), %rsp
diff --git a/arch/x86/boot/compressed/mkpiggy.c 
b/arch/x86/boot/compressed/mkpiggy.c
index b669ab65bf6c..c03b0097ce58 100644
--- a/arch/x86/boot/compressed/mkpiggy.c
+++ b/arch/x86/boot/compressed/mkpiggy.c
@@ -80,11 +80,8 @@ int main(int argc, char *argv[])
printf("z_input_len = %lu\n", ilen);
printf(".globl z_output_len\n");
printf("z_output_len = %lu\n", (unsigned long)olen);
-   printf(".globl z_extract_offset\n");
-   

Re: [PATCH v3 2/7] x86, boot: Move ZO to end of buffer

2015-03-10 Thread Borislav Petkov
On Mon, Mar 09, 2015 at 05:54:01PM -0700, Kees Cook wrote:
> On Sat, Mar 7, 2015 at 2:07 PM, Yinghai Lu  wrote:
> > Boris found data from boot stage can not be used kernel stage.
> 
> "... be used during kernel stage."
> 
> Also, can you give a specific example of this problem? (Which data, used how?)

Yeah, I'm filling stuff in, no worries. It just takes twice as long as
I'm decyphering early boot code *and* Yinghai. :-)

-- 
Regards/Gruss,
Boris.

ECO tip #101: Trim your mails when you reply.
--
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v3 2/7] x86, boot: Move ZO to end of buffer

2015-03-10 Thread Borislav Petkov
On Mon, Mar 09, 2015 at 05:54:01PM -0700, Kees Cook wrote:
 On Sat, Mar 7, 2015 at 2:07 PM, Yinghai Lu ying...@kernel.org wrote:
  Boris found data from boot stage can not be used kernel stage.
 
 ... be used during kernel stage.
 
 Also, can you give a specific example of this problem? (Which data, used how?)

Yeah, I'm filling stuff in, no worries. It just takes twice as long as
I'm decyphering early boot code *and* Yinghai. :-)

-- 
Regards/Gruss,
Boris.

ECO tip #101: Trim your mails when you reply.
--
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v3 2/7] x86, boot: Move ZO to end of buffer

2015-03-10 Thread Jiri Kosina
On Tue, 10 Mar 2015, Borislav Petkov wrote:

 Final patch:
 
 ---
 From: Yinghai Lu ying...@kernel.org
 Date: Sat, 7 Mar 2015 14:07:16 -0800
 Subject: [PATCH] x86/setup: Move compressed kernel to the end of the buffer
[ ... ]
 Signed-off-by: Yinghai Lu ying...@kernel.org
 Cc: H. Peter Anvin h...@zytor.com
 Cc: Matt Fleming matt.flem...@intel.com
 Cc: Kees Cook keesc...@chromium.org
 Cc: Thomas Gleixner t...@linutronix.de
 Cc: Jiri Kosina jkos...@suse.cz
 Cc: linux-...@vger.kernel.org
 Cc: Ingo Molnar mi...@redhat.com
 Cc: Baoquan He b...@redhat.com
 Fixes: f47233c2d34f (x86/mm/ASLR: Propagate base load address calculation)

Thanks a lot for fixing my oversight.

Acked-by: Jiri Kosina jkos...@suse.cz

 Link: 
 http://lkml.kernel.org/r/1425766041-6551-3-git-send-email-ying...@kernel.org
 [ Commit message massively rewritten ]
 Signed-off-by: 
 ---
  arch/x86/boot/compressed/head_32.S | 11 +--
  arch/x86/boot/compressed/head_64.S |  8 ++--
  arch/x86/boot/compressed/mkpiggy.c |  7 ++-
  arch/x86/boot/compressed/vmlinux.lds.S |  1 +
  arch/x86/boot/header.S |  2 +-
  arch/x86/kernel/asm-offsets.c  |  1 +
  arch/x86/kernel/vmlinux.lds.S  |  1 +
  7 files changed, 21 insertions(+), 10 deletions(-)
 
 diff --git a/arch/x86/boot/compressed/head_32.S 
 b/arch/x86/boot/compressed/head_32.S
 index cbed1407a5cd..a9b56f1d8e75 100644
 --- a/arch/x86/boot/compressed/head_32.S
 +++ b/arch/x86/boot/compressed/head_32.S
 @@ -147,7 +147,9 @@ preferred_addr:
  1:
  
   /* Target address to relocate to for decompression */
 - addl$z_extract_offset, %ebx
 + movlBP_init_size(%esi), %eax
 + subl$_end, %eax
 + addl%eax, %ebx
  
   /* Set up the stack */
   lealboot_stack_end(%ebx), %esp
 @@ -208,8 +210,13 @@ relocated:
   */
   /* push arguments for decompress_kernel: */
   pushl   $z_output_len   /* decompressed length */
 - lealz_extract_offset_negative(%ebx), %ebp
 +
 + movlBP_init_size(%esi), %eax
 + subl$_end, %eax
 + movl%ebx, %ebp
 + subl%eax, %ebp
   pushl   %ebp/* output address */
 +
   pushl   $z_input_len/* input_len */
   lealinput_data(%ebx), %eax
   pushl   %eax/* input_data */
 diff --git a/arch/x86/boot/compressed/head_64.S 
 b/arch/x86/boot/compressed/head_64.S
 index 2884e0c3e8a5..69015b576cf6 100644
 --- a/arch/x86/boot/compressed/head_64.S
 +++ b/arch/x86/boot/compressed/head_64.S
 @@ -101,7 +101,9 @@ ENTRY(startup_32)
  1:
  
   /* Target address to relocate to for decompression */
 - addl$z_extract_offset, %ebx
 + movlBP_init_size(%esi), %eax
 + subl$_end, %eax
 + addl%eax, %ebx
  
  /*
   * Prepare for entering 64 bit mode
 @@ -329,7 +331,9 @@ preferred_addr:
  1:
  
   /* Target address to relocate to for decompression */
 - leaqz_extract_offset(%rbp), %rbx
 + movlBP_init_size(%rsi), %ebx
 + subl$_end, %ebx
 + addq%rbp, %rbx
  
   /* Set up the stack */
   leaqboot_stack_end(%rbx), %rsp
 diff --git a/arch/x86/boot/compressed/mkpiggy.c 
 b/arch/x86/boot/compressed/mkpiggy.c
 index b669ab65bf6c..c03b0097ce58 100644
 --- a/arch/x86/boot/compressed/mkpiggy.c
 +++ b/arch/x86/boot/compressed/mkpiggy.c
 @@ -80,11 +80,8 @@ int main(int argc, char *argv[])
   printf(z_input_len = %lu\n, ilen);
   printf(.globl z_output_len\n);
   printf(z_output_len = %lu\n, (unsigned long)olen);
 - printf(.globl z_extract_offset\n);
 - printf(z_extract_offset = 0x%lx\n, offs);
 - /* z_extract_offset_negative allows simplification of head_32.S */
 - printf(.globl z_extract_offset_negative\n);
 - printf(z_extract_offset_negative = -0x%lx\n, offs);
 + printf(.globl z_min_extract_offset\n);
 + printf(z_min_extract_offset = 0x%lx\n, offs);
  
   printf(.globl input_data, input_data_end\n);
   printf(input_data:\n);
 diff --git a/arch/x86/boot/compressed/vmlinux.lds.S 
 b/arch/x86/boot/compressed/vmlinux.lds.S
 index 34d047c98284..a80acabb80ec 100644
 --- a/arch/x86/boot/compressed/vmlinux.lds.S
 +++ b/arch/x86/boot/compressed/vmlinux.lds.S
 @@ -70,5 +70,6 @@ SECTIONS
   _epgtable = . ;
   }
  #endif
 + . = ALIGN(PAGE_SIZE);   /* keep size page-aligned */
   _end = .;
  }
 diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
 index 16ef02596db2..9bfab22efdf7 100644
 --- a/arch/x86/boot/header.S
 +++ b/arch/x86/boot/header.S
 @@ -440,7 +440,7 @@ setup_data:   .quad 0 # 
 64-bit physical pointer to
  
  pref_address:.quad LOAD_PHYSICAL_ADDR# preferred 
 load addr
  
 -#define ZO_INIT_SIZE (ZO__end - ZO_startup_32 + ZO_z_extract_offset)
 +#define ZO_INIT_SIZE (ZO__end - ZO_startup_32 + ZO_z_min_extract_offset)
  #define VO_INIT_SIZE (VO__end - VO__text)
  #if ZO_INIT_SIZE  VO_INIT_SIZE
  #define 

Re: [PATCH v3 2/7] x86, boot: Move ZO to end of buffer

2015-03-10 Thread Borislav Petkov
On Tue, Mar 10, 2015 at 10:34:31AM +0100, Jiri Kosina wrote:
 Thanks a lot for fixing my oversight.

Bah, it was my suggestion to use setup_data in the first place, sorry
about that.

-- 
Regards/Gruss,
Boris.

ECO tip #101: Trim your mails when you reply.
--
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v3 2/7] x86, boot: Move ZO to end of buffer

2015-03-10 Thread Kees Cook
On Tue, Mar 10, 2015 at 1:00 AM, Borislav Petkov b...@suse.de wrote:
 Final patch:

 ---
 From: Yinghai Lu ying...@kernel.org
 Date: Sat, 7 Mar 2015 14:07:16 -0800
 Subject: [PATCH] x86/setup: Move compressed kernel to the end of the buffer

 Boris found that passing KASLR status through setup_data from the boot
 stage cannot be used later in the kernel stage, see commit

   f47233c2d34f (x86/mm/ASLR: Propagate base load address calculation)

 Here's some background:

 The boot loader allocates a buffer of size init_size in concordance with
 the value passed in the setup header and it loads the compressed, i.e.
 first kernel (arch/x86/boot/compressed/vmlinux) in it.

 First kernel then moves itself somewhere around the middle of the
 buffer at z_extract_offset to make sure that the decompressor does not
 overwrite input data.

 After the decompressor is finished, kernel proper (vmlinux) uses the
 whole buffer from the beginning and the compressed kernel's code and
 data section is overlapped with the kernel proper's bss section.

 Later on, clear_bss() in kernel proper clears .bss before code in
 arch/x86/kernel/setup.c can access setup_data passed in the first,
 compressed kernel.

 To make sure that data survives, we should avoid the overlapping.

 As a first step, move the first kernel closer to the end of the buffer
 instead of the middle. As a result, this will place first kernel's data
 area out of kernel proper's .bss area.

 This way we can find out where the data section of the copied first
 kernel is instead of guessing. In addition, it will make the KASLR
 mem_avoid array preparation for the search of a fitting buffer much
 simpler.

 While at it, rename z_extract_offset to z_min_extract_offset as it is
 actually the minimum extract offset now.

 In order to keep the final extract offset page-aligned we need to
 make both kernels' _end markers page-aligned too so that init_size is
 page-aligned as a result.

 Signed-off-by: Yinghai Lu ying...@kernel.org
 Cc: H. Peter Anvin h...@zytor.com
 Cc: Matt Fleming matt.flem...@intel.com
 Cc: Kees Cook keesc...@chromium.org
 Cc: Thomas Gleixner t...@linutronix.de
 Cc: Jiri Kosina jkos...@suse.cz
 Cc: linux-...@vger.kernel.org
 Cc: Ingo Molnar mi...@redhat.com
 Cc: Baoquan He b...@redhat.com
 Fixes: f47233c2d34f (x86/mm/ASLR: Propagate base load address calculation)
 Link: 
 http://lkml.kernel.org/r/1425766041-6551-3-git-send-email-ying...@kernel.org
 [ Commit message massively rewritten ]

Acked-by: Kees Cook keesc...@chromium.org

Thanks!

-Kees

 Signed-off-by:
 ---
  arch/x86/boot/compressed/head_32.S | 11 +--
  arch/x86/boot/compressed/head_64.S |  8 ++--
  arch/x86/boot/compressed/mkpiggy.c |  7 ++-
  arch/x86/boot/compressed/vmlinux.lds.S |  1 +
  arch/x86/boot/header.S |  2 +-
  arch/x86/kernel/asm-offsets.c  |  1 +
  arch/x86/kernel/vmlinux.lds.S  |  1 +
  7 files changed, 21 insertions(+), 10 deletions(-)

 diff --git a/arch/x86/boot/compressed/head_32.S 
 b/arch/x86/boot/compressed/head_32.S
 index cbed1407a5cd..a9b56f1d8e75 100644
 --- a/arch/x86/boot/compressed/head_32.S
 +++ b/arch/x86/boot/compressed/head_32.S
 @@ -147,7 +147,9 @@ preferred_addr:
  1:

 /* Target address to relocate to for decompression */
 -   addl$z_extract_offset, %ebx
 +   movlBP_init_size(%esi), %eax
 +   subl$_end, %eax
 +   addl%eax, %ebx

 /* Set up the stack */
 lealboot_stack_end(%ebx), %esp
 @@ -208,8 +210,13 @@ relocated:
   */
 /* push arguments for decompress_kernel: */
 pushl   $z_output_len   /* decompressed length */
 -   lealz_extract_offset_negative(%ebx), %ebp
 +
 +   movlBP_init_size(%esi), %eax
 +   subl$_end, %eax
 +   movl%ebx, %ebp
 +   subl%eax, %ebp
 pushl   %ebp/* output address */
 +
 pushl   $z_input_len/* input_len */
 lealinput_data(%ebx), %eax
 pushl   %eax/* input_data */
 diff --git a/arch/x86/boot/compressed/head_64.S 
 b/arch/x86/boot/compressed/head_64.S
 index 2884e0c3e8a5..69015b576cf6 100644
 --- a/arch/x86/boot/compressed/head_64.S
 +++ b/arch/x86/boot/compressed/head_64.S
 @@ -101,7 +101,9 @@ ENTRY(startup_32)
  1:

 /* Target address to relocate to for decompression */
 -   addl$z_extract_offset, %ebx
 +   movlBP_init_size(%esi), %eax
 +   subl$_end, %eax
 +   addl%eax, %ebx

  /*
   * Prepare for entering 64 bit mode
 @@ -329,7 +331,9 @@ preferred_addr:
  1:

 /* Target address to relocate to for decompression */
 -   leaqz_extract_offset(%rbp), %rbx
 +   movlBP_init_size(%rsi), %ebx
 +   subl$_end, %ebx
 +   addq%rbp, %rbx

 /* Set up the stack */
 leaqboot_stack_end(%rbx), %rsp
 diff --git a/arch/x86/boot/compressed/mkpiggy.c 
 b/arch/x86/boot/compressed/mkpiggy.c
 index 

Re: [PATCH v3 2/7] x86, boot: Move ZO to end of buffer

2015-03-10 Thread Yinghai Lu
On Tue, Mar 10, 2015 at 1:00 AM, Borislav Petkov b...@suse.de wrote:
 Final patch:

 ---
 From: Yinghai Lu ying...@kernel.org
 Date: Sat, 7 Mar 2015 14:07:16 -0800
 Subject: [PATCH] x86/setup: Move compressed kernel to the end of the buffer

setup should only about arch/x86/boot/setup.ld related.

So please keep x86, boot.

Also stop using compressed kernel please, that is confusing.

Just use

ZO: arch/x86/boot/compressed/vmlinux
VO: vmlinux

Thanks

Yinghai
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v3 2/7] x86, boot: Move ZO to end of buffer

2015-03-10 Thread Borislav Petkov
On Tue, Mar 10, 2015 at 08:11:03AM -0700, Yinghai Lu wrote:
 Also stop using compressed kernel please, that is confusing.

Why?

 Just use
 
 ZO: arch/x86/boot/compressed/vmlinux
 VO: vmlinux

and this is not confusing?

Yeah, right.

-- 
Regards/Gruss,
Boris.

ECO tip #101: Trim your mails when you reply.
--
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v3 2/7] x86, boot: Move ZO to end of buffer

2015-03-10 Thread Borislav Petkov
Final patch:

---
From: Yinghai Lu ying...@kernel.org
Date: Sat, 7 Mar 2015 14:07:16 -0800
Subject: [PATCH] x86/setup: Move compressed kernel to the end of the buffer

Boris found that passing KASLR status through setup_data from the boot
stage cannot be used later in the kernel stage, see commit

  f47233c2d34f (x86/mm/ASLR: Propagate base load address calculation)

Here's some background:

The boot loader allocates a buffer of size init_size in concordance with
the value passed in the setup header and it loads the compressed, i.e.
first kernel (arch/x86/boot/compressed/vmlinux) in it.

First kernel then moves itself somewhere around the middle of the
buffer at z_extract_offset to make sure that the decompressor does not
overwrite input data.

After the decompressor is finished, kernel proper (vmlinux) uses the
whole buffer from the beginning and the compressed kernel's code and
data section is overlapped with the kernel proper's bss section.

Later on, clear_bss() in kernel proper clears .bss before code in
arch/x86/kernel/setup.c can access setup_data passed in the first,
compressed kernel.

To make sure that data survives, we should avoid the overlapping.

As a first step, move the first kernel closer to the end of the buffer
instead of the middle. As a result, this will place first kernel's data
area out of kernel proper's .bss area.

This way we can find out where the data section of the copied first
kernel is instead of guessing. In addition, it will make the KASLR
mem_avoid array preparation for the search of a fitting buffer much
simpler.

While at it, rename z_extract_offset to z_min_extract_offset as it is
actually the minimum extract offset now.

In order to keep the final extract offset page-aligned we need to
make both kernels' _end markers page-aligned too so that init_size is
page-aligned as a result.

Signed-off-by: Yinghai Lu ying...@kernel.org
Cc: H. Peter Anvin h...@zytor.com
Cc: Matt Fleming matt.flem...@intel.com
Cc: Kees Cook keesc...@chromium.org
Cc: Thomas Gleixner t...@linutronix.de
Cc: Jiri Kosina jkos...@suse.cz
Cc: linux-...@vger.kernel.org
Cc: Ingo Molnar mi...@redhat.com
Cc: Baoquan He b...@redhat.com
Fixes: f47233c2d34f (x86/mm/ASLR: Propagate base load address calculation)
Link: 
http://lkml.kernel.org/r/1425766041-6551-3-git-send-email-ying...@kernel.org
[ Commit message massively rewritten ]
Signed-off-by: 
---
 arch/x86/boot/compressed/head_32.S | 11 +--
 arch/x86/boot/compressed/head_64.S |  8 ++--
 arch/x86/boot/compressed/mkpiggy.c |  7 ++-
 arch/x86/boot/compressed/vmlinux.lds.S |  1 +
 arch/x86/boot/header.S |  2 +-
 arch/x86/kernel/asm-offsets.c  |  1 +
 arch/x86/kernel/vmlinux.lds.S  |  1 +
 7 files changed, 21 insertions(+), 10 deletions(-)

diff --git a/arch/x86/boot/compressed/head_32.S 
b/arch/x86/boot/compressed/head_32.S
index cbed1407a5cd..a9b56f1d8e75 100644
--- a/arch/x86/boot/compressed/head_32.S
+++ b/arch/x86/boot/compressed/head_32.S
@@ -147,7 +147,9 @@ preferred_addr:
 1:
 
/* Target address to relocate to for decompression */
-   addl$z_extract_offset, %ebx
+   movlBP_init_size(%esi), %eax
+   subl$_end, %eax
+   addl%eax, %ebx
 
/* Set up the stack */
lealboot_stack_end(%ebx), %esp
@@ -208,8 +210,13 @@ relocated:
  */
/* push arguments for decompress_kernel: */
pushl   $z_output_len   /* decompressed length */
-   lealz_extract_offset_negative(%ebx), %ebp
+
+   movlBP_init_size(%esi), %eax
+   subl$_end, %eax
+   movl%ebx, %ebp
+   subl%eax, %ebp
pushl   %ebp/* output address */
+
pushl   $z_input_len/* input_len */
lealinput_data(%ebx), %eax
pushl   %eax/* input_data */
diff --git a/arch/x86/boot/compressed/head_64.S 
b/arch/x86/boot/compressed/head_64.S
index 2884e0c3e8a5..69015b576cf6 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -101,7 +101,9 @@ ENTRY(startup_32)
 1:
 
/* Target address to relocate to for decompression */
-   addl$z_extract_offset, %ebx
+   movlBP_init_size(%esi), %eax
+   subl$_end, %eax
+   addl%eax, %ebx
 
 /*
  * Prepare for entering 64 bit mode
@@ -329,7 +331,9 @@ preferred_addr:
 1:
 
/* Target address to relocate to for decompression */
-   leaqz_extract_offset(%rbp), %rbx
+   movlBP_init_size(%rsi), %ebx
+   subl$_end, %ebx
+   addq%rbp, %rbx
 
/* Set up the stack */
leaqboot_stack_end(%rbx), %rsp
diff --git a/arch/x86/boot/compressed/mkpiggy.c 
b/arch/x86/boot/compressed/mkpiggy.c
index b669ab65bf6c..c03b0097ce58 100644
--- a/arch/x86/boot/compressed/mkpiggy.c
+++ b/arch/x86/boot/compressed/mkpiggy.c
@@ -80,11 +80,8 @@ int main(int argc, char *argv[])
printf(z_input_len = %lu\n, ilen);
printf(.globl 

Re: [PATCH v3 2/7] x86, boot: Move ZO to end of buffer

2015-03-09 Thread Yinghai Lu
On Mon, Mar 9, 2015 at 5:54 PM, Kees Cook  wrote:
> On Sat, Mar 7, 2015 at 2:07 PM, Yinghai Lu  wrote:
>> Boris found data from boot stage can not be used kernel stage.
>
> "... be used during kernel stage."
>
> Also, can you give a specific example of this problem? (Which data, used how?)
>
>> Bootloader allocate buffer according to init_size in hdr, and load the
>> ZO (arch/x86/boot/compressed/vmlinux) from start of that buffer.
>> During running of ZO, ZO move itself to the middle of buffer at
>> z_extract_offset to make sure that decompressor would not have output
>> overwrite input data before input data get consumed.
>> After decompressor is called, VO (vmlinux) use whole buffer from start,
>> and ZO code and data section is overlapped with VO bss section.
>> And later VO/clear_bss() clear them before code in arch/x86/kernel/setup.c
>> access them.
>>
>> To make the data survive that later, we should avoid the overlapping.
>> At first move ZO close the end of buffer instead of middle of the buffer,
>> that will move out ZO data out of VO bss area.
>>
>> Also after that we can find out where is data section of copied ZO
>> instead of guessing. That will aslr mem_avoid array filling for
>
> "That will make aslr mem_avoid array ..."
>
>> new buffer seaching much simple.
>>
>> And rename z_extract_offset to z_min_extract_offset, as it is
>> actually the minimum offset for extracting now.
>>
>> To keep the final real extract_offset to be page aligned like
>> min_extract_offset, we need make VO _end and ZO _end both
>> page aligned to make sure init_size always page aligned.
>>
>> Next patch will add ZO data size to init_size, so it will make sure
>> ZO data is even out of VO brk area.
>
> This seems like a reasonable idea, but I think the changes should be
> noted/updated in misc.c since a lot of effort was made to make the
> in-memory foot print as small as possible.

Yes, that explanation in misc.c is very good about extra bytes, and it should
still stand. Also need to make mkpiggy.c to point to it.
We need to add more info about in head_32/64.c actually we need move
to end of the buffer.

> These changes do expand the
> size of the loaded kernel, IIUC. If not in this patch, maybe in 5/7?

It extend about 256k for init_size.  should be 3/7.
but that is only for decompress time. Final VO (vmlinux) run size
is not changed.

Thanks

Yinghai
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v3 2/7] x86, boot: Move ZO to end of buffer

2015-03-09 Thread Kees Cook
On Sat, Mar 7, 2015 at 2:07 PM, Yinghai Lu  wrote:
> Boris found data from boot stage can not be used kernel stage.

"... be used during kernel stage."

Also, can you give a specific example of this problem? (Which data, used how?)

> Bootloader allocate buffer according to init_size in hdr, and load the
> ZO (arch/x86/boot/compressed/vmlinux) from start of that buffer.
> During running of ZO, ZO move itself to the middle of buffer at
> z_extract_offset to make sure that decompressor would not have output
> overwrite input data before input data get consumed.
> After decompressor is called, VO (vmlinux) use whole buffer from start,
> and ZO code and data section is overlapped with VO bss section.
> And later VO/clear_bss() clear them before code in arch/x86/kernel/setup.c
> access them.
>
> To make the data survive that later, we should avoid the overlapping.
> At first move ZO close the end of buffer instead of middle of the buffer,
> that will move out ZO data out of VO bss area.
>
> Also after that we can find out where is data section of copied ZO
> instead of guessing. That will aslr mem_avoid array filling for

"That will make aslr mem_avoid array ..."

> new buffer seaching much simple.
>
> And rename z_extract_offset to z_min_extract_offset, as it is
> actually the minimum offset for extracting now.
>
> To keep the final real extract_offset to be page aligned like
> min_extract_offset, we need make VO _end and ZO _end both
> page aligned to make sure init_size always page aligned.
>
> Next patch will add ZO data size to init_size, so it will make sure
> ZO data is even out of VO brk area.

This seems like a reasonable idea, but I think the changes should be
noted/updated in misc.c since a lot of effort was made to make the
in-memory foot print as small as possible. These changes do expand the
size of the loaded kernel, IIUC. If not in this patch, maybe in 5/7?

-Kees

>
> Fixes: f47233c2d34f ("x86/mm/ASLR: Propagate base load address calculation")
> Cc: "H. Peter Anvin" 
> Cc: Matt Fleming 
> Cc: Kees Cook 
> Signed-off-by: Yinghai Lu 
> ---
>  arch/x86/boot/compressed/head_32.S | 11 +--
>  arch/x86/boot/compressed/head_64.S |  8 ++--
>  arch/x86/boot/compressed/mkpiggy.c |  7 ++-
>  arch/x86/boot/compressed/vmlinux.lds.S |  1 +
>  arch/x86/boot/header.S |  2 +-
>  arch/x86/kernel/asm-offsets.c  |  1 +
>  arch/x86/kernel/vmlinux.lds.S  |  1 +
>  7 files changed, 21 insertions(+), 10 deletions(-)
>
> diff --git a/arch/x86/boot/compressed/head_32.S 
> b/arch/x86/boot/compressed/head_32.S
> index cbed140..a9b56f1 100644
> --- a/arch/x86/boot/compressed/head_32.S
> +++ b/arch/x86/boot/compressed/head_32.S
> @@ -147,7 +147,9 @@ preferred_addr:
>  1:
>
> /* Target address to relocate to for decompression */
> -   addl$z_extract_offset, %ebx
> +   movlBP_init_size(%esi), %eax
> +   subl$_end, %eax
> +   addl%eax, %ebx
>
> /* Set up the stack */
> lealboot_stack_end(%ebx), %esp
> @@ -208,8 +210,13 @@ relocated:
>   */
> /* push arguments for decompress_kernel: */
> pushl   $z_output_len   /* decompressed length */
> -   lealz_extract_offset_negative(%ebx), %ebp
> +
> +   movlBP_init_size(%esi), %eax
> +   subl$_end, %eax
> +   movl%ebx, %ebp
> +   subl%eax, %ebp
> pushl   %ebp/* output address */
> +
> pushl   $z_input_len/* input_len */
> lealinput_data(%ebx), %eax
> pushl   %eax/* input_data */
> diff --git a/arch/x86/boot/compressed/head_64.S 
> b/arch/x86/boot/compressed/head_64.S
> index 2884e0c..69015b5 100644
> --- a/arch/x86/boot/compressed/head_64.S
> +++ b/arch/x86/boot/compressed/head_64.S
> @@ -101,7 +101,9 @@ ENTRY(startup_32)
>  1:
>
> /* Target address to relocate to for decompression */
> -   addl$z_extract_offset, %ebx
> +   movlBP_init_size(%esi), %eax
> +   subl$_end, %eax
> +   addl%eax, %ebx
>
>  /*
>   * Prepare for entering 64 bit mode
> @@ -329,7 +331,9 @@ preferred_addr:
>  1:
>
> /* Target address to relocate to for decompression */
> -   leaqz_extract_offset(%rbp), %rbx
> +   movlBP_init_size(%rsi), %ebx
> +   subl$_end, %ebx
> +   addq%rbp, %rbx
>
> /* Set up the stack */
> leaqboot_stack_end(%rbx), %rsp
> diff --git a/arch/x86/boot/compressed/mkpiggy.c 
> b/arch/x86/boot/compressed/mkpiggy.c
> index b669ab6..c03b009 100644
> --- a/arch/x86/boot/compressed/mkpiggy.c
> +++ b/arch/x86/boot/compressed/mkpiggy.c
> @@ -80,11 +80,8 @@ int main(int argc, char *argv[])
> printf("z_input_len = %lu\n", ilen);
> printf(".globl z_output_len\n");
> printf("z_output_len = %lu\n", (unsigned long)olen);
> -   printf(".globl z_extract_offset\n");
> -   printf("z_extract_offset = 0x%lx\n", offs);
> -   

Re: [PATCH v3 2/7] x86, boot: Move ZO to end of buffer

2015-03-09 Thread Yinghai Lu
On Mon, Mar 9, 2015 at 5:54 PM, Kees Cook keesc...@chromium.org wrote:
 On Sat, Mar 7, 2015 at 2:07 PM, Yinghai Lu ying...@kernel.org wrote:
 Boris found data from boot stage can not be used kernel stage.

 ... be used during kernel stage.

 Also, can you give a specific example of this problem? (Which data, used how?)

 Bootloader allocate buffer according to init_size in hdr, and load the
 ZO (arch/x86/boot/compressed/vmlinux) from start of that buffer.
 During running of ZO, ZO move itself to the middle of buffer at
 z_extract_offset to make sure that decompressor would not have output
 overwrite input data before input data get consumed.
 After decompressor is called, VO (vmlinux) use whole buffer from start,
 and ZO code and data section is overlapped with VO bss section.
 And later VO/clear_bss() clear them before code in arch/x86/kernel/setup.c
 access them.

 To make the data survive that later, we should avoid the overlapping.
 At first move ZO close the end of buffer instead of middle of the buffer,
 that will move out ZO data out of VO bss area.

 Also after that we can find out where is data section of copied ZO
 instead of guessing. That will aslr mem_avoid array filling for

 That will make aslr mem_avoid array ...

 new buffer seaching much simple.

 And rename z_extract_offset to z_min_extract_offset, as it is
 actually the minimum offset for extracting now.

 To keep the final real extract_offset to be page aligned like
 min_extract_offset, we need make VO _end and ZO _end both
 page aligned to make sure init_size always page aligned.

 Next patch will add ZO data size to init_size, so it will make sure
 ZO data is even out of VO brk area.

 This seems like a reasonable idea, but I think the changes should be
 noted/updated in misc.c since a lot of effort was made to make the
 in-memory foot print as small as possible.

Yes, that explanation in misc.c is very good about extra bytes, and it should
still stand. Also need to make mkpiggy.c to point to it.
We need to add more info about in head_32/64.c actually we need move
to end of the buffer.

 These changes do expand the
 size of the loaded kernel, IIUC. If not in this patch, maybe in 5/7?

It extend about 256k for init_size.  should be 3/7.
but that is only for decompress time. Final VO (vmlinux) run size
is not changed.

Thanks

Yinghai
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v3 2/7] x86, boot: Move ZO to end of buffer

2015-03-09 Thread Kees Cook
On Sat, Mar 7, 2015 at 2:07 PM, Yinghai Lu ying...@kernel.org wrote:
 Boris found data from boot stage can not be used kernel stage.

... be used during kernel stage.

Also, can you give a specific example of this problem? (Which data, used how?)

 Bootloader allocate buffer according to init_size in hdr, and load the
 ZO (arch/x86/boot/compressed/vmlinux) from start of that buffer.
 During running of ZO, ZO move itself to the middle of buffer at
 z_extract_offset to make sure that decompressor would not have output
 overwrite input data before input data get consumed.
 After decompressor is called, VO (vmlinux) use whole buffer from start,
 and ZO code and data section is overlapped with VO bss section.
 And later VO/clear_bss() clear them before code in arch/x86/kernel/setup.c
 access them.

 To make the data survive that later, we should avoid the overlapping.
 At first move ZO close the end of buffer instead of middle of the buffer,
 that will move out ZO data out of VO bss area.

 Also after that we can find out where is data section of copied ZO
 instead of guessing. That will aslr mem_avoid array filling for

That will make aslr mem_avoid array ...

 new buffer seaching much simple.

 And rename z_extract_offset to z_min_extract_offset, as it is
 actually the minimum offset for extracting now.

 To keep the final real extract_offset to be page aligned like
 min_extract_offset, we need make VO _end and ZO _end both
 page aligned to make sure init_size always page aligned.

 Next patch will add ZO data size to init_size, so it will make sure
 ZO data is even out of VO brk area.

This seems like a reasonable idea, but I think the changes should be
noted/updated in misc.c since a lot of effort was made to make the
in-memory foot print as small as possible. These changes do expand the
size of the loaded kernel, IIUC. If not in this patch, maybe in 5/7?

-Kees


 Fixes: f47233c2d34f (x86/mm/ASLR: Propagate base load address calculation)
 Cc: H. Peter Anvin h...@zytor.com
 Cc: Matt Fleming matt.flem...@intel.com
 Cc: Kees Cook keesc...@chromium.org
 Signed-off-by: Yinghai Lu ying...@kernel.org
 ---
  arch/x86/boot/compressed/head_32.S | 11 +--
  arch/x86/boot/compressed/head_64.S |  8 ++--
  arch/x86/boot/compressed/mkpiggy.c |  7 ++-
  arch/x86/boot/compressed/vmlinux.lds.S |  1 +
  arch/x86/boot/header.S |  2 +-
  arch/x86/kernel/asm-offsets.c  |  1 +
  arch/x86/kernel/vmlinux.lds.S  |  1 +
  7 files changed, 21 insertions(+), 10 deletions(-)

 diff --git a/arch/x86/boot/compressed/head_32.S 
 b/arch/x86/boot/compressed/head_32.S
 index cbed140..a9b56f1 100644
 --- a/arch/x86/boot/compressed/head_32.S
 +++ b/arch/x86/boot/compressed/head_32.S
 @@ -147,7 +147,9 @@ preferred_addr:
  1:

 /* Target address to relocate to for decompression */
 -   addl$z_extract_offset, %ebx
 +   movlBP_init_size(%esi), %eax
 +   subl$_end, %eax
 +   addl%eax, %ebx

 /* Set up the stack */
 lealboot_stack_end(%ebx), %esp
 @@ -208,8 +210,13 @@ relocated:
   */
 /* push arguments for decompress_kernel: */
 pushl   $z_output_len   /* decompressed length */
 -   lealz_extract_offset_negative(%ebx), %ebp
 +
 +   movlBP_init_size(%esi), %eax
 +   subl$_end, %eax
 +   movl%ebx, %ebp
 +   subl%eax, %ebp
 pushl   %ebp/* output address */
 +
 pushl   $z_input_len/* input_len */
 lealinput_data(%ebx), %eax
 pushl   %eax/* input_data */
 diff --git a/arch/x86/boot/compressed/head_64.S 
 b/arch/x86/boot/compressed/head_64.S
 index 2884e0c..69015b5 100644
 --- a/arch/x86/boot/compressed/head_64.S
 +++ b/arch/x86/boot/compressed/head_64.S
 @@ -101,7 +101,9 @@ ENTRY(startup_32)
  1:

 /* Target address to relocate to for decompression */
 -   addl$z_extract_offset, %ebx
 +   movlBP_init_size(%esi), %eax
 +   subl$_end, %eax
 +   addl%eax, %ebx

  /*
   * Prepare for entering 64 bit mode
 @@ -329,7 +331,9 @@ preferred_addr:
  1:

 /* Target address to relocate to for decompression */
 -   leaqz_extract_offset(%rbp), %rbx
 +   movlBP_init_size(%rsi), %ebx
 +   subl$_end, %ebx
 +   addq%rbp, %rbx

 /* Set up the stack */
 leaqboot_stack_end(%rbx), %rsp
 diff --git a/arch/x86/boot/compressed/mkpiggy.c 
 b/arch/x86/boot/compressed/mkpiggy.c
 index b669ab6..c03b009 100644
 --- a/arch/x86/boot/compressed/mkpiggy.c
 +++ b/arch/x86/boot/compressed/mkpiggy.c
 @@ -80,11 +80,8 @@ int main(int argc, char *argv[])
 printf(z_input_len = %lu\n, ilen);
 printf(.globl z_output_len\n);
 printf(z_output_len = %lu\n, (unsigned long)olen);
 -   printf(.globl z_extract_offset\n);
 -   printf(z_extract_offset = 0x%lx\n, offs);
 -   /* z_extract_offset_negative allows 

[PATCH v3 2/7] x86, boot: Move ZO to end of buffer

2015-03-07 Thread Yinghai Lu
Boris found data from boot stage can not be used kernel stage.

Bootloader allocate buffer according to init_size in hdr, and load the
ZO (arch/x86/boot/compressed/vmlinux) from start of that buffer.
During running of ZO, ZO move itself to the middle of buffer at
z_extract_offset to make sure that decompressor would not have output
overwrite input data before input data get consumed.
After decompressor is called, VO (vmlinux) use whole buffer from start,
and ZO code and data section is overlapped with VO bss section.
And later VO/clear_bss() clear them before code in arch/x86/kernel/setup.c
access them.

To make the data survive that later, we should avoid the overlapping.
At first move ZO close the end of buffer instead of middle of the buffer,
that will move out ZO data out of VO bss area.

Also after that we can find out where is data section of copied ZO
instead of guessing. That will aslr mem_avoid array filling for
new buffer seaching much simple.

And rename z_extract_offset to z_min_extract_offset, as it is
actually the minimum offset for extracting now.

To keep the final real extract_offset to be page aligned like
min_extract_offset, we need make VO _end and ZO _end both
page aligned to make sure init_size always page aligned.

Next patch will add ZO data size to init_size, so it will make sure
ZO data is even out of VO brk area.

Fixes: f47233c2d34f ("x86/mm/ASLR: Propagate base load address calculation")
Cc: "H. Peter Anvin" 
Cc: Matt Fleming 
Cc: Kees Cook 
Signed-off-by: Yinghai Lu 
---
 arch/x86/boot/compressed/head_32.S | 11 +--
 arch/x86/boot/compressed/head_64.S |  8 ++--
 arch/x86/boot/compressed/mkpiggy.c |  7 ++-
 arch/x86/boot/compressed/vmlinux.lds.S |  1 +
 arch/x86/boot/header.S |  2 +-
 arch/x86/kernel/asm-offsets.c  |  1 +
 arch/x86/kernel/vmlinux.lds.S  |  1 +
 7 files changed, 21 insertions(+), 10 deletions(-)

diff --git a/arch/x86/boot/compressed/head_32.S 
b/arch/x86/boot/compressed/head_32.S
index cbed140..a9b56f1 100644
--- a/arch/x86/boot/compressed/head_32.S
+++ b/arch/x86/boot/compressed/head_32.S
@@ -147,7 +147,9 @@ preferred_addr:
 1:
 
/* Target address to relocate to for decompression */
-   addl$z_extract_offset, %ebx
+   movlBP_init_size(%esi), %eax
+   subl$_end, %eax
+   addl%eax, %ebx
 
/* Set up the stack */
lealboot_stack_end(%ebx), %esp
@@ -208,8 +210,13 @@ relocated:
  */
/* push arguments for decompress_kernel: */
pushl   $z_output_len   /* decompressed length */
-   lealz_extract_offset_negative(%ebx), %ebp
+
+   movlBP_init_size(%esi), %eax
+   subl$_end, %eax
+   movl%ebx, %ebp
+   subl%eax, %ebp
pushl   %ebp/* output address */
+
pushl   $z_input_len/* input_len */
lealinput_data(%ebx), %eax
pushl   %eax/* input_data */
diff --git a/arch/x86/boot/compressed/head_64.S 
b/arch/x86/boot/compressed/head_64.S
index 2884e0c..69015b5 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -101,7 +101,9 @@ ENTRY(startup_32)
 1:
 
/* Target address to relocate to for decompression */
-   addl$z_extract_offset, %ebx
+   movlBP_init_size(%esi), %eax
+   subl$_end, %eax
+   addl%eax, %ebx
 
 /*
  * Prepare for entering 64 bit mode
@@ -329,7 +331,9 @@ preferred_addr:
 1:
 
/* Target address to relocate to for decompression */
-   leaqz_extract_offset(%rbp), %rbx
+   movlBP_init_size(%rsi), %ebx
+   subl$_end, %ebx
+   addq%rbp, %rbx
 
/* Set up the stack */
leaqboot_stack_end(%rbx), %rsp
diff --git a/arch/x86/boot/compressed/mkpiggy.c 
b/arch/x86/boot/compressed/mkpiggy.c
index b669ab6..c03b009 100644
--- a/arch/x86/boot/compressed/mkpiggy.c
+++ b/arch/x86/boot/compressed/mkpiggy.c
@@ -80,11 +80,8 @@ int main(int argc, char *argv[])
printf("z_input_len = %lu\n", ilen);
printf(".globl z_output_len\n");
printf("z_output_len = %lu\n", (unsigned long)olen);
-   printf(".globl z_extract_offset\n");
-   printf("z_extract_offset = 0x%lx\n", offs);
-   /* z_extract_offset_negative allows simplification of head_32.S */
-   printf(".globl z_extract_offset_negative\n");
-   printf("z_extract_offset_negative = -0x%lx\n", offs);
+   printf(".globl z_min_extract_offset\n");
+   printf("z_min_extract_offset = 0x%lx\n", offs);
 
printf(".globl input_data, input_data_end\n");
printf("input_data:\n");
diff --git a/arch/x86/boot/compressed/vmlinux.lds.S 
b/arch/x86/boot/compressed/vmlinux.lds.S
index 34d047c..e24e0a0 100644
--- a/arch/x86/boot/compressed/vmlinux.lds.S
+++ b/arch/x86/boot/compressed/vmlinux.lds.S
@@ -70,5 +70,6 @@ SECTIONS
_epgtable = . ;
}
 #endif
+   . = ALIGN(PAGE_SIZE);   /* 

[PATCH v3 2/7] x86, boot: Move ZO to end of buffer

2015-03-07 Thread Yinghai Lu
Boris found data from boot stage can not be used kernel stage.

Bootloader allocate buffer according to init_size in hdr, and load the
ZO (arch/x86/boot/compressed/vmlinux) from start of that buffer.
During running of ZO, ZO move itself to the middle of buffer at
z_extract_offset to make sure that decompressor would not have output
overwrite input data before input data get consumed.
After decompressor is called, VO (vmlinux) use whole buffer from start,
and ZO code and data section is overlapped with VO bss section.
And later VO/clear_bss() clear them before code in arch/x86/kernel/setup.c
access them.

To make the data survive that later, we should avoid the overlapping.
At first move ZO close the end of buffer instead of middle of the buffer,
that will move out ZO data out of VO bss area.

Also after that we can find out where is data section of copied ZO
instead of guessing. That will aslr mem_avoid array filling for
new buffer seaching much simple.

And rename z_extract_offset to z_min_extract_offset, as it is
actually the minimum offset for extracting now.

To keep the final real extract_offset to be page aligned like
min_extract_offset, we need make VO _end and ZO _end both
page aligned to make sure init_size always page aligned.

Next patch will add ZO data size to init_size, so it will make sure
ZO data is even out of VO brk area.

Fixes: f47233c2d34f (x86/mm/ASLR: Propagate base load address calculation)
Cc: H. Peter Anvin h...@zytor.com
Cc: Matt Fleming matt.flem...@intel.com
Cc: Kees Cook keesc...@chromium.org
Signed-off-by: Yinghai Lu ying...@kernel.org
---
 arch/x86/boot/compressed/head_32.S | 11 +--
 arch/x86/boot/compressed/head_64.S |  8 ++--
 arch/x86/boot/compressed/mkpiggy.c |  7 ++-
 arch/x86/boot/compressed/vmlinux.lds.S |  1 +
 arch/x86/boot/header.S |  2 +-
 arch/x86/kernel/asm-offsets.c  |  1 +
 arch/x86/kernel/vmlinux.lds.S  |  1 +
 7 files changed, 21 insertions(+), 10 deletions(-)

diff --git a/arch/x86/boot/compressed/head_32.S 
b/arch/x86/boot/compressed/head_32.S
index cbed140..a9b56f1 100644
--- a/arch/x86/boot/compressed/head_32.S
+++ b/arch/x86/boot/compressed/head_32.S
@@ -147,7 +147,9 @@ preferred_addr:
 1:
 
/* Target address to relocate to for decompression */
-   addl$z_extract_offset, %ebx
+   movlBP_init_size(%esi), %eax
+   subl$_end, %eax
+   addl%eax, %ebx
 
/* Set up the stack */
lealboot_stack_end(%ebx), %esp
@@ -208,8 +210,13 @@ relocated:
  */
/* push arguments for decompress_kernel: */
pushl   $z_output_len   /* decompressed length */
-   lealz_extract_offset_negative(%ebx), %ebp
+
+   movlBP_init_size(%esi), %eax
+   subl$_end, %eax
+   movl%ebx, %ebp
+   subl%eax, %ebp
pushl   %ebp/* output address */
+
pushl   $z_input_len/* input_len */
lealinput_data(%ebx), %eax
pushl   %eax/* input_data */
diff --git a/arch/x86/boot/compressed/head_64.S 
b/arch/x86/boot/compressed/head_64.S
index 2884e0c..69015b5 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -101,7 +101,9 @@ ENTRY(startup_32)
 1:
 
/* Target address to relocate to for decompression */
-   addl$z_extract_offset, %ebx
+   movlBP_init_size(%esi), %eax
+   subl$_end, %eax
+   addl%eax, %ebx
 
 /*
  * Prepare for entering 64 bit mode
@@ -329,7 +331,9 @@ preferred_addr:
 1:
 
/* Target address to relocate to for decompression */
-   leaqz_extract_offset(%rbp), %rbx
+   movlBP_init_size(%rsi), %ebx
+   subl$_end, %ebx
+   addq%rbp, %rbx
 
/* Set up the stack */
leaqboot_stack_end(%rbx), %rsp
diff --git a/arch/x86/boot/compressed/mkpiggy.c 
b/arch/x86/boot/compressed/mkpiggy.c
index b669ab6..c03b009 100644
--- a/arch/x86/boot/compressed/mkpiggy.c
+++ b/arch/x86/boot/compressed/mkpiggy.c
@@ -80,11 +80,8 @@ int main(int argc, char *argv[])
printf(z_input_len = %lu\n, ilen);
printf(.globl z_output_len\n);
printf(z_output_len = %lu\n, (unsigned long)olen);
-   printf(.globl z_extract_offset\n);
-   printf(z_extract_offset = 0x%lx\n, offs);
-   /* z_extract_offset_negative allows simplification of head_32.S */
-   printf(.globl z_extract_offset_negative\n);
-   printf(z_extract_offset_negative = -0x%lx\n, offs);
+   printf(.globl z_min_extract_offset\n);
+   printf(z_min_extract_offset = 0x%lx\n, offs);
 
printf(.globl input_data, input_data_end\n);
printf(input_data:\n);
diff --git a/arch/x86/boot/compressed/vmlinux.lds.S 
b/arch/x86/boot/compressed/vmlinux.lds.S
index 34d047c..e24e0a0 100644
--- a/arch/x86/boot/compressed/vmlinux.lds.S
+++ b/arch/x86/boot/compressed/vmlinux.lds.S
@@ -70,5 +70,6 @@ SECTIONS
_epgtable = . ;