Commit c546e47591d7c8b4fa3dc2d9dae14c127f0c3b22

Authored by Kees Cook
Committed by Greg Kroah-Hartman
1 parent 056ad39c15

x86, boot: Skip relocs when load address unchanged

commit f285f4a21c3253887caceed493089ece17579d59 upstream.

On 64-bit, relocation is not required unless the load address gets
changed. Without this, relocations do unexpected things when the kernel
is above 4G.

Reported-by: Baoquan He <bhe@redhat.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
Tested-by: Thomas D. <whissi@whissi.de>
Cc: Vivek Goyal <vgoyal@redhat.com>
Cc: Jan Beulich <JBeulich@suse.com>
Cc: Junjie Mao <eternal.n08@gmail.com>
Cc: Andi Kleen <ak@linux.intel.com>
Link: http://lkml.kernel.org/r/20150116005146.GA4212@www.outflux.net
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Showing 1 changed file with 8 additions and 1 deletions Side-by-side Diff

arch/x86/boot/compressed/misc.c
... ... @@ -361,6 +361,8 @@
361 361 unsigned long output_len,
362 362 unsigned long run_size)
363 363 {
  364 + unsigned char *output_orig = output;
  365 +
364 366 real_mode = rmode;
365 367  
366 368 sanitize_boot_params(real_mode);
... ... @@ -409,7 +411,12 @@
409 411 debug_putstr("\nDecompressing Linux... ");
410 412 decompress(input_data, input_len, NULL, NULL, output, NULL, error);
411 413 parse_elf(output);
412   - handle_relocations(output, output_len);
  414 + /*
  415 + * 32-bit always performs relocations. 64-bit relocations are only
  416 + * needed if kASLR has chosen a different load address.
  417 + */
  418 + if (!IS_ENABLED(CONFIG_X86_64) || output != output_orig)
  419 + handle_relocations(output, output_len);
413 420 debug_putstr("done.\nBooting the kernel.\n");
414 421 return output;
415 422 }