Re: [PATCH v1.1] x86/mm/ASLR: Propagate ASLR status to kernel proper

Yinghai Lu
2015-04-13T23:18:38Z

On Thu, Apr 2, 2015 at 4:50 AM, Borislav Petkov <bp@alien8.de> wrote:
> On Thu, Apr 02, 2015 at 01:29:30PM +0200, Ingo Molnar wrote:
>> So was this duplication dead code in essence?
>
> See e2b32e678513.
>
> Looks like it was parsing the cmdline option for a second time in the
> kernel proper (vs first one which we still parse in the compressed
> kernel).
>
> hpa said that we probably could solve it this way here too but using a
> bit in loadflags is cleaner and nicer. IMO :)
>
>> > I guess by multi-line you mean multiple source lines...
>>
>> Yeah.
>
> Here you go:
>
> ---
> From: Borislav Petkov <bp@suse.de>
> Subject: [PATCH v1.2] x86/mm/ASLR: Propagate ASLR status to kernel proper
>
> Commit
>
> e2b32e678513 ("x86, kaslr: randomize module base load address")
>
> made module base address randomization unconditional and didn't regard
> disabled KASLR due to CONFIG_HIBERNATION and command line option
> "nokaslr". For more info see (now reverted) commit:
>
> f47233c2d34f ("x86/mm/ASLR: Propagate base load address calculation")
>
> In order to propagate ASLR status to kernel proper, we need a single bit
> in boot_params.hdr.loadflags and we've chosen bit 1 thus leaving the
> top-down allocated bits for bits supposed to be used by the bootloader.
>
> diff --git a/arch/x86/boot/compressed/aslr.c b/arch/x86/boot/compressed/aslr.c
> index bb1376381985..370e47d763b0 100644
> --- a/arch/x86/boot/compressed/aslr.c
> +++ b/arch/x86/boot/compressed/aslr.c
> @@ -295,7 +295,8 @@ static unsigned long find_random_addr(unsigned long minimum,
> return slots_fetch_random();
> }
>
> -unsigned char *choose_kernel_location(unsigned char *input,
> +unsigned char *choose_kernel_location(struct boot_params *boot_params,
> + unsigned char *input,
> unsigned long input_size,
> unsigned char *output,
> unsigned long output_size)
> @@ -315,6 +316,8 @@ unsigned char *choose_kernel_location(unsigned char *input,
> }
> #endif
>
> + boot_params->hdr.loadflags |= ASLR_FLAG;
> +
> /* Record the various known unsafe memory ranges. */
> mem_avoid_init((unsigned long)input, input_size,
> (unsigned long)output, output_size);
> diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
> index a950864a64da..ca83518e405e 100644
> --- a/arch/x86/boot/compressed/misc.c
> +++ b/arch/x86/boot/compressed/misc.c
> @@ -377,6 +377,9 @@ asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap,
>
> real_mode = rmode;
>
> + /* Clear it for solely in-kernel use */
> + real_mode->hdr.loadflags &= ~ASLR_FLAG;
> +
> sanitize_boot_params(real_mode);
>
> if (real_mode->screen_info.orig_video_mode == 7) {
> @@ -401,7 +404,7 @@ asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap,
> * the entire decompressed kernel plus relocation table, or the
> * entire decompressed kernel plus .bss and .brk sections.
> */
> - output = choose_kernel_location(input_data, input_len, output,
> + output = choose_kernel_location(real_mode, input_data, input_len, output,
> output_len > run_size ? output_len
> : run_size);
>
> diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h
> index 04477d68403f..89dd0d78013a 100644
> --- a/arch/x86/boot/compressed/misc.h
> +++ b/arch/x86/boot/compressed/misc.h
> @@ -57,7 +57,8 @@ int cmdline_find_option_bool(const char *option);
>
> #if CONFIG_RANDOMIZE_BASE
> /* aslr.c */
> -unsigned char *choose_kernel_location(unsigned char *input,
> +unsigned char *choose_kernel_location(struct boot_params *boot_params,
> + unsigned char *input,
> unsigned long input_size,
> unsigned char *output,
> unsigned long output_size);
> @@ -65,7 +66,8 @@ unsigned char *choose_kernel_location(unsigned char *input,
> bool has_cpuflag(int flag);
> #else
> static inline
> -unsigned char *choose_kernel_location(unsigned char *input,
> +unsigned char *choose_kernel_location(struct boot_params *boot_params,
> + unsigned char *input,
> unsigned long input_size,
> unsigned char *output,
> unsigned long output_size)

Why do you need to pass around pointer to boot_params around?

The real_mode is global variable.

Yinghai