On Fri, May 06, 2016 at 12:46:05AM -0700, tip-bot for Yinghai Lu wrote:
> Commit-ID:  9dc1969c24eff8b7d7a9a565d1047b624921ba06
> Gitweb:     http://git.kernel.org/tip/9dc1969c24eff8b7d7a9a565d1047b624921ba06
> Author:     Yinghai Lu <ying...@kernel.org>
> AuthorDate: Thu, 5 May 2016 15:13:47 -0700
> Committer:  Ingo Molnar <mi...@kernel.org>
> CommitDate: Fri, 6 May 2016 09:00:59 +0200
> 
> x86/KASLR: Consolidate mem_avoid[] entries
> 
> The mem_avoid[] array is used to track positions that should be avoided (like
> the compressed kernel, decompression code, etc) when selecting a memory
> position for the randomly relocated kernel. Since ZO is now at the end of

Can we stop with those ZO(MG) obfuscated abbreviations and call it
simply the "compressed kernel image"?

> the decompression buffer and the decompression code (and its heap and
> stack) are at the front, we can safely consolidate the decompression entry,
> the heap entry, and the stack entry. The boot_params memory, however, could
> be elsewhere, so it should be explicitly included.
> 
> Signed-off-by: Yinghai Lu <ying...@kernel.org>
> Signed-off-by: Baoquan He <b...@redhat.com>
> [ Rwrote changelog, cleaned up code comments. ]
> Signed-off-by: Kees Cook <keesc...@chromium.org>
> Cc: Andrew Morton <a...@linux-foundation.org>
> Cc: Andy Lutomirski <l...@amacapital.net>
> Cc: Andy Lutomirski <l...@kernel.org>
> Cc: Borislav Petkov <b...@alien8.de>
> Cc: Brian Gerst <brge...@gmail.com>
> Cc: Dave Young <dyo...@redhat.com>
> Cc: Denys Vlasenko <dvlas...@redhat.com>
> Cc: H. Peter Anvin <h...@zytor.com>
> Cc: Linus Torvalds <torva...@linux-foundation.org>
> Cc: Peter Zijlstra <pet...@infradead.org>
> Cc: Thomas Gleixner <t...@linutronix.de>
> Cc: Vivek Goyal <vgo...@redhat.com>
> Cc: kernel-harden...@lists.openwall.com
> Cc: lasse.col...@tukaani.org
> Link: 
> http://lkml.kernel.org/r/1462486436-3707-3-git-send-email-keesc...@chromium.org
> Signed-off-by: Ingo Molnar <mi...@kernel.org>
> ---
>  arch/x86/boot/compressed/kaslr.c | 77 
> +++++++++++++++++++++++++++++++---------
>  1 file changed, 61 insertions(+), 16 deletions(-)
> 
> diff --git a/arch/x86/boot/compressed/kaslr.c 
> b/arch/x86/boot/compressed/kaslr.c
> index 2072d82..6392f00 100644
> --- a/arch/x86/boot/compressed/kaslr.c
> +++ b/arch/x86/boot/compressed/kaslr.c
> @@ -121,7 +121,7 @@ struct mem_vector {
>       unsigned long size;
>  };
>  
> -#define MEM_AVOID_MAX 5
> +#define MEM_AVOID_MAX 4
>  static struct mem_vector mem_avoid[MEM_AVOID_MAX];
>  
>  static bool mem_contains(struct mem_vector *region, struct mem_vector *item)
> @@ -146,22 +146,71 @@ static bool mem_overlaps(struct mem_vector *one, struct 
> mem_vector *two)
>       return true;
>  }
>  
> +/*
> + * In theroy, KASLR can put the kernel anywhere in area of [16M, 64T). The
         ^^^^^^
Spellchecker please.

                                                   in the range of [...

> + * mem_avoid array is used to store the ranges that need to be avoided when
> + * KASLR searches for a an appropriate random address. We must avoid any

                        s/a //

> + * regions that are unsafe to overlap with during decompression, and other
> + * things like the initrd, cmdline and boot_params.
> + *
> + * How to calculate the unsafe areas is detailed here, and is informed by
> + * the decompression calculations in header.S, and the diagram in misc.c.
> + *
> + * The compressed vmlinux (ZO) plus relocs and the run space of ZO can't be
> + * overwritten by decompression output.
> + *
> + * ZO sits against the end of the decompression buffer, so we can calculate
> + * where text, data, bss, etc of ZO are positioned.
> + *
> + * The follow are already enforced by the code:

        " ... following conditions are ..."

> + *  - init_size >= kernel_total_size
> + *  - input + input_len >= output + output_len
> + *  - kernel_total_size could be >= or < output_len
> + *
> + * From this, we can make several observations, illustrated by a diagram:
> + *  - init_size >= kernel_total_size

You just said this above?!

> + *  - input + input_len > output + output_len
> + *  - kernel_total_size >= output_len

Ok, what is the point of the observations? To show that we're making the
conditions enforced by the code more concrete, stricter, ...?

> + *
> + * 0   output            input            input+input_len    output+init_size
> + * |     |                 |                       |                       |
> + * |     |                 |                       |                       |
> + * |-----|--------|--------|------------------|----|------------|----------|
> + *                |                           |                 |
> + *                |                           |                 |
> + * output+init_size-ZO_INIT_SIZE   output+output_len  
> output+kernel_total_size
> + *
> + * [output, output+init_size) is for the buffer for decompressing the
> + * compressed kernel (ZO).
> + *
> + * [output, output+kernel_total_size) is for the uncompressed kernel (VO)
> + * and its bss, brk, etc.
> + * [output, output+output_len) is VO plus relocs
> + *
> + * [output+init_size-ZO_INIT_SIZE, output+init_size) is the copied ZO.

..., i.e., ZO_INIT_SIZE.

> + * [input, input+input_len) is the copied compressed (VO (vmlinux after
> + * objcopy) plus relocs), not the ZO.
> + *
> + * [input+input_len, output+init_size) is [_text, _end) for ZO. That was the
> + * first range in mem_avoid, which included ZO's heap and stack. Also
> + * [input, input+input_size) need be put in mem_avoid array, but since it

                        " ... needs to be in the mem_avoid ..."

> + * is adjacent to the first entry, they can be merged. This is how we get
> + * the first entry in mem_avoid[].
> + */

<--- my head smokes right about here. :-)

>  static void mem_avoid_init(unsigned long input, unsigned long input_size,
> -                        unsigned long output, unsigned long output_size)
> +                        unsigned long output)
>  {
> +     unsigned long init_size = boot_params->hdr.init_size;
>       u64 initrd_start, initrd_size;
>       u64 cmd_line, cmd_line_size;
> -     unsigned long unsafe, unsafe_len;
>       char *ptr;
>  
>       /*
>        * Avoid the region that is unsafe to overlap during
> -      * decompression (see calculations in ../header.S).
> +      * decompression.
>        */
> -     unsafe_len = (output_size >> 12) + 32768 + 18;
> -     unsafe = (unsigned long)input + input_size - unsafe_len;
> -     mem_avoid[0].start = unsafe;
> -     mem_avoid[0].size = unsafe_len;
> +     mem_avoid[0].start = input;
> +     mem_avoid[0].size = (output + init_size) - input;

There's a define above called MEM_AVOID_MAX but the array elements are
adressed with naked numbers here. Perhaps if we had defines for them
too, it'll make the code a bit more understandable:

        mem_avoid[MEM_AVOID_ZO_RANGE] ...
        mem_avoid[MEM_AVOID_INITRD] ...

and so on.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

Reply via email to