Re: kaslr relocation incompitable with kernel loaded high

2014-04-22 Thread Kees Cook
On Mon, Apr 21, 2014 at 10:28 PM, WANG Chao  wrote:
> On 04/21/14 at 09:58pm, Yinghai Lu wrote:
>> On Mon, Apr 21, 2014 at 8:16 PM, WANG Chao  wrote:
>> > On 04/21/14 at 11:01am, Kees Cook wrote:
>> >> On Mon, Apr 21, 2014 at 10:56 AM, Yinghai Lu  wrote:
>> >> > On Mon, Apr 21, 2014 at 3:52 AM, WANG Chao  wrote:
>> >> >> Hi, Kees
>> >> >>
>> >> >> When I'm testing kaslr with kdump, I find that when 2nd kernel is 
>> >> >> loaded
>> >> >> high, it doesn't boot.
>> >> >>
>> >> >> I reserved 128M memory at high with kernel cmdline
>> >> >> "crashkernel=128M,high crashkernel=0,low", and for which I got:
>> >> >>
>> >> >> [0.00] Reserving 128MB of memory at 6896MB for crashkernel 
>> >> >> (System RAM: 6013MB)
>> >> >>
>> >> >> Then I load kdump kernel into the reserved memory region, using a local
>> >> >> modified kexec-tools which is passing e820 in boot_params.
>> >> >>
>> >> >> The e820 map of system RAM passed to 2nd kernel:
>> >> >>
>> >> >> E820 memmap (of RAM):
>> >> >> 1000-0009e3ff (1)
>> >> >> 0001af00-0001b6f5dfff (1)
>> >> >> 0001b6fff400-0001b6ff (1)
>> >> >>
>> >> >> In which, 2nd kernel is loaded at 0x1b500.
>> >> >>
>> >> >> After triggerred a system crash, 2nd kernel doesn't boot even with
>> >> >> "nokaslr" cmdline:
>> >> >>
>> >> >> # echo c > /proc/sysrq-trigger
>> >> >> [..]
>> >> >>
>> >> >> I'm in purgatory
>> >> >> early console in decompress_kernel
>> >> >> KASLR disabled...
>> >> >>
>> >> >> Decompressing Linux... Parsing ELF... Performing relocations...
>> >> >>
>> >> >> 32-bit relocation outside of kernel!
>> >> >
>> >> > Interesting, when kernel get at "early console in decompress_kernel"
>> >> > kernel already in 64 bit...
>> >> >
>> >> > what does it mean "32-bit relocation outside of kernel" ?
>> >> >
>> >> > why 32-bit is involved ?
>> >>
>> >> The 64-bit kernel has both 64 and 32 bit relocations (there are two
>> >> tables at the end of the kernel image). The error means that the
>> >> resulting relocation is believed to be outside the kernel image:
>> >>
>> >> http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/x86/boot/compressed/misc.c#n283
>> >>
>> >> Which means there is likely something wrong with this calculation in
>> >> your situation:
>> >>
>> >> /*
>> >>  * Calculate the delta between where vmlinux was linked to load
>> >>  * and where it was actually loaded.
>> >>  */
>> >> delta = min_addr - LOAD_PHYSICAL_ADDR;
>> >>
>> >
>> > Probably.
>>
>> Please check attached that patch that will solve nokaslr.
>>
>> Somehow I got "KASLR could not find suitable E820 region..."
>> so i only have "No relocation needed"
>
> I think it makes sense. If output from choose_kernel_location() doesn't
> change (output == output_orig), we shouldn't call relocation code.
>
> There are two situations that makes output == output_orig:
> - "nokaslr" case
> - "KASLR could not find suitable E820 region" case.
>
>>
>> will check that later.
>
>> ---
>>  arch/x86/boot/compressed/misc.c |   14 +-
>>  1 file changed, 9 insertions(+), 5 deletions(-)
>>
>> Index: linux-2.6/arch/x86/boot/compressed/misc.c
>> ===
>> --- linux-2.6.orig/arch/x86/boot/compressed/misc.c
>> +++ linux-2.6/arch/x86/boot/compressed/misc.c
>> @@ -235,8 +235,9 @@ static void error(char *x)
>>   asm("hlt");
>>  }
>>
>> -#if CONFIG_X86_NEED_RELOCS
>> -static void handle_relocations(void *output, unsigned long output_len)
>> +#ifdef CONFIG_X86_NEED_RELOCS
>> +static void handle_relocations(void *output_orig, void *output,
>> +unsigned long output_len)
>>  {
>>   int *reloc;
>>   unsigned long delta, map, ptr;
>> @@ -247,7 +248,7 @@ static void handle_relocations(void *out
>>* Calculate the delta between where vmlinux was linked to load
>>* and where it was actually loaded.
>>*/
>> - delta = min_addr - LOAD_PHYSICAL_ADDR;
>> + delta = min_addr - (unsigned long)output_orig;
>>   if (!delta) {
>>   debug_putstr("No relocation needed... ");
>>   return;
>> @@ -304,7 +305,8 @@ static void handle_relocations(void *out
>>  #endif
>>  }
>>  #else
>> -static inline void handle_relocations(void *output, unsigned long 
>> output_len)
>> +static inline void handle_relocations(void *output_orig, void *output,
>> +   unsigned long output_len)
>>  { }
>>  #endif
>>
>> @@ -365,6 +367,8 @@ asmlinkage void *decompress_kernel(void
>> unsigned char *output,
>> unsigned long output_len)
>>  {
>> + unsigned char *output_orig = output;
>> +
>>   real_mode = rmode;
>>
>>   sanitize_boot_params(real_mode);
>> @@ -417,7 +421,7 @@ asmlinkage void *decompress_kernel(void
>>   debug_putstr("... ");
>>   decompress(input_data, input_len, NULL, NULL, output, NULL, error);
>>   

Re: kaslr relocation incompitable with kernel loaded high

2014-04-22 Thread Kees Cook
On Mon, Apr 21, 2014 at 10:28 PM, WANG Chao chaow...@redhat.com wrote:
 On 04/21/14 at 09:58pm, Yinghai Lu wrote:
 On Mon, Apr 21, 2014 at 8:16 PM, WANG Chao chaow...@redhat.com wrote:
  On 04/21/14 at 11:01am, Kees Cook wrote:
  On Mon, Apr 21, 2014 at 10:56 AM, Yinghai Lu ying...@kernel.org wrote:
   On Mon, Apr 21, 2014 at 3:52 AM, WANG Chao chaow...@redhat.com wrote:
   Hi, Kees
  
   When I'm testing kaslr with kdump, I find that when 2nd kernel is 
   loaded
   high, it doesn't boot.
  
   I reserved 128M memory at high with kernel cmdline
   crashkernel=128M,high crashkernel=0,low, and for which I got:
  
   [0.00] Reserving 128MB of memory at 6896MB for crashkernel 
   (System RAM: 6013MB)
  
   Then I load kdump kernel into the reserved memory region, using a local
   modified kexec-tools which is passing e820 in boot_params.
  
   The e820 map of system RAM passed to 2nd kernel:
  
   E820 memmap (of RAM):
   1000-0009e3ff (1)
   0001af00-0001b6f5dfff (1)
   0001b6fff400-0001b6ff (1)
  
   In which, 2nd kernel is loaded at 0x1b500.
  
   After triggerred a system crash, 2nd kernel doesn't boot even with
   nokaslr cmdline:
  
   # echo c  /proc/sysrq-trigger
   [..]
  
   I'm in purgatory
   early console in decompress_kernel
   KASLR disabled...
  
   Decompressing Linux... Parsing ELF... Performing relocations...
  
   32-bit relocation outside of kernel!
  
   Interesting, when kernel get at early console in decompress_kernel
   kernel already in 64 bit...
  
   what does it mean 32-bit relocation outside of kernel ?
  
   why 32-bit is involved ?
 
  The 64-bit kernel has both 64 and 32 bit relocations (there are two
  tables at the end of the kernel image). The error means that the
  resulting relocation is believed to be outside the kernel image:
 
  http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/x86/boot/compressed/misc.c#n283
 
  Which means there is likely something wrong with this calculation in
  your situation:
 
  /*
   * Calculate the delta between where vmlinux was linked to load
   * and where it was actually loaded.
   */
  delta = min_addr - LOAD_PHYSICAL_ADDR;
 
 
  Probably.

 Please check attached that patch that will solve nokaslr.

 Somehow I got KASLR could not find suitable E820 region...
 so i only have No relocation needed

 I think it makes sense. If output from choose_kernel_location() doesn't
 change (output == output_orig), we shouldn't call relocation code.

 There are two situations that makes output == output_orig:
 - nokaslr case
 - KASLR could not find suitable E820 region case.


 will check that later.

 ---
  arch/x86/boot/compressed/misc.c |   14 +-
  1 file changed, 9 insertions(+), 5 deletions(-)

 Index: linux-2.6/arch/x86/boot/compressed/misc.c
 ===
 --- linux-2.6.orig/arch/x86/boot/compressed/misc.c
 +++ linux-2.6/arch/x86/boot/compressed/misc.c
 @@ -235,8 +235,9 @@ static void error(char *x)
   asm(hlt);
  }

 -#if CONFIG_X86_NEED_RELOCS
 -static void handle_relocations(void *output, unsigned long output_len)
 +#ifdef CONFIG_X86_NEED_RELOCS
 +static void handle_relocations(void *output_orig, void *output,
 +unsigned long output_len)
  {
   int *reloc;
   unsigned long delta, map, ptr;
 @@ -247,7 +248,7 @@ static void handle_relocations(void *out
* Calculate the delta between where vmlinux was linked to load
* and where it was actually loaded.
*/
 - delta = min_addr - LOAD_PHYSICAL_ADDR;
 + delta = min_addr - (unsigned long)output_orig;
   if (!delta) {
   debug_putstr(No relocation needed... );
   return;
 @@ -304,7 +305,8 @@ static void handle_relocations(void *out
  #endif
  }
  #else
 -static inline void handle_relocations(void *output, unsigned long 
 output_len)
 +static inline void handle_relocations(void *output_orig, void *output,
 +   unsigned long output_len)
  { }
  #endif

 @@ -365,6 +367,8 @@ asmlinkage void *decompress_kernel(void
 unsigned char *output,
 unsigned long output_len)
  {
 + unsigned char *output_orig = output;
 +
   real_mode = rmode;

   sanitize_boot_params(real_mode);
 @@ -417,7 +421,7 @@ asmlinkage void *decompress_kernel(void
   debug_putstr(... );
   decompress(input_data, input_len, NULL, NULL, output, NULL, error);
   parse_elf(output);
 - handle_relocations(output, output_len);
 + handle_relocations(output_orig, output, output_len);
   debug_putstr(done.\nBooting the kernel.\n);
   return output;
  }

 Thanks for the patch, it works for me :)

 I also have a draft patch with the same idea as Yinghai. But I take a
 slightly different approach:

 diff --git a/arch/x86/boot/compressed/misc.c 

Re: kaslr relocation incompitable with kernel loaded high

2014-04-21 Thread WANG Chao
On 04/21/14 at 09:58pm, Yinghai Lu wrote:
> On Mon, Apr 21, 2014 at 8:16 PM, WANG Chao  wrote:
> > On 04/21/14 at 11:01am, Kees Cook wrote:
> >> On Mon, Apr 21, 2014 at 10:56 AM, Yinghai Lu  wrote:
> >> > On Mon, Apr 21, 2014 at 3:52 AM, WANG Chao  wrote:
> >> >> Hi, Kees
> >> >>
> >> >> When I'm testing kaslr with kdump, I find that when 2nd kernel is loaded
> >> >> high, it doesn't boot.
> >> >>
> >> >> I reserved 128M memory at high with kernel cmdline
> >> >> "crashkernel=128M,high crashkernel=0,low", and for which I got:
> >> >>
> >> >> [0.00] Reserving 128MB of memory at 6896MB for crashkernel 
> >> >> (System RAM: 6013MB)
> >> >>
> >> >> Then I load kdump kernel into the reserved memory region, using a local
> >> >> modified kexec-tools which is passing e820 in boot_params.
> >> >>
> >> >> The e820 map of system RAM passed to 2nd kernel:
> >> >>
> >> >> E820 memmap (of RAM):
> >> >> 1000-0009e3ff (1)
> >> >> 0001af00-0001b6f5dfff (1)
> >> >> 0001b6fff400-0001b6ff (1)
> >> >>
> >> >> In which, 2nd kernel is loaded at 0x1b500.
> >> >>
> >> >> After triggerred a system crash, 2nd kernel doesn't boot even with
> >> >> "nokaslr" cmdline:
> >> >>
> >> >> # echo c > /proc/sysrq-trigger
> >> >> [..]
> >> >>
> >> >> I'm in purgatory
> >> >> early console in decompress_kernel
> >> >> KASLR disabled...
> >> >>
> >> >> Decompressing Linux... Parsing ELF... Performing relocations...
> >> >>
> >> >> 32-bit relocation outside of kernel!
> >> >
> >> > Interesting, when kernel get at "early console in decompress_kernel"
> >> > kernel already in 64 bit...
> >> >
> >> > what does it mean "32-bit relocation outside of kernel" ?
> >> >
> >> > why 32-bit is involved ?
> >>
> >> The 64-bit kernel has both 64 and 32 bit relocations (there are two
> >> tables at the end of the kernel image). The error means that the
> >> resulting relocation is believed to be outside the kernel image:
> >>
> >> http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/x86/boot/compressed/misc.c#n283
> >>
> >> Which means there is likely something wrong with this calculation in
> >> your situation:
> >>
> >> /*
> >>  * Calculate the delta between where vmlinux was linked to load
> >>  * and where it was actually loaded.
> >>  */
> >> delta = min_addr - LOAD_PHYSICAL_ADDR;
> >>
> >
> > Probably.
> 
> Please check attached that patch that will solve nokaslr.
> 
> Somehow I got "KASLR could not find suitable E820 region..."
> so i only have "No relocation needed"

I think it makes sense. If output from choose_kernel_location() doesn't
change (output == output_orig), we shouldn't call relocation code.

There are two situations that makes output == output_orig:
- "nokaslr" case
- "KASLR could not find suitable E820 region" case.

> 
> will check that later.

> ---
>  arch/x86/boot/compressed/misc.c |   14 +-
>  1 file changed, 9 insertions(+), 5 deletions(-)
> 
> Index: linux-2.6/arch/x86/boot/compressed/misc.c
> ===
> --- linux-2.6.orig/arch/x86/boot/compressed/misc.c
> +++ linux-2.6/arch/x86/boot/compressed/misc.c
> @@ -235,8 +235,9 @@ static void error(char *x)
>   asm("hlt");
>  }
>  
> -#if CONFIG_X86_NEED_RELOCS
> -static void handle_relocations(void *output, unsigned long output_len)
> +#ifdef CONFIG_X86_NEED_RELOCS
> +static void handle_relocations(void *output_orig, void *output,
> +unsigned long output_len)
>  {
>   int *reloc;
>   unsigned long delta, map, ptr;
> @@ -247,7 +248,7 @@ static void handle_relocations(void *out
>* Calculate the delta between where vmlinux was linked to load
>* and where it was actually loaded.
>*/
> - delta = min_addr - LOAD_PHYSICAL_ADDR;
> + delta = min_addr - (unsigned long)output_orig;
>   if (!delta) {
>   debug_putstr("No relocation needed... ");
>   return;
> @@ -304,7 +305,8 @@ static void handle_relocations(void *out
>  #endif
>  }
>  #else
> -static inline void handle_relocations(void *output, unsigned long output_len)
> +static inline void handle_relocations(void *output_orig, void *output,
> +   unsigned long output_len)
>  { }
>  #endif
>  
> @@ -365,6 +367,8 @@ asmlinkage void *decompress_kernel(void
> unsigned char *output,
> unsigned long output_len)
>  {
> + unsigned char *output_orig = output;
> +
>   real_mode = rmode;
>  
>   sanitize_boot_params(real_mode);
> @@ -417,7 +421,7 @@ asmlinkage void *decompress_kernel(void
>   debug_putstr("... ");
>   decompress(input_data, input_len, NULL, NULL, output, NULL, error);
>   parse_elf(output);
> - handle_relocations(output, output_len);
> + handle_relocations(output_orig, output, output_len);
>   debug_putstr("done.\nBooting the kernel.\n");
>   return 

Re: kaslr relocation incompitable with kernel loaded high

2014-04-21 Thread Yinghai Lu
On Mon, Apr 21, 2014 at 8:16 PM, WANG Chao  wrote:
> On 04/21/14 at 11:01am, Kees Cook wrote:
>> On Mon, Apr 21, 2014 at 10:56 AM, Yinghai Lu  wrote:
>> > On Mon, Apr 21, 2014 at 3:52 AM, WANG Chao  wrote:
>> >> Hi, Kees
>> >>
>> >> When I'm testing kaslr with kdump, I find that when 2nd kernel is loaded
>> >> high, it doesn't boot.
>> >>
>> >> I reserved 128M memory at high with kernel cmdline
>> >> "crashkernel=128M,high crashkernel=0,low", and for which I got:
>> >>
>> >> [0.00] Reserving 128MB of memory at 6896MB for crashkernel 
>> >> (System RAM: 6013MB)
>> >>
>> >> Then I load kdump kernel into the reserved memory region, using a local
>> >> modified kexec-tools which is passing e820 in boot_params.
>> >>
>> >> The e820 map of system RAM passed to 2nd kernel:
>> >>
>> >> E820 memmap (of RAM):
>> >> 1000-0009e3ff (1)
>> >> 0001af00-0001b6f5dfff (1)
>> >> 0001b6fff400-0001b6ff (1)
>> >>
>> >> In which, 2nd kernel is loaded at 0x1b500.
>> >>
>> >> After triggerred a system crash, 2nd kernel doesn't boot even with
>> >> "nokaslr" cmdline:
>> >>
>> >> # echo c > /proc/sysrq-trigger
>> >> [..]
>> >>
>> >> I'm in purgatory
>> >> early console in decompress_kernel
>> >> KASLR disabled...
>> >>
>> >> Decompressing Linux... Parsing ELF... Performing relocations...
>> >>
>> >> 32-bit relocation outside of kernel!
>> >
>> > Interesting, when kernel get at "early console in decompress_kernel"
>> > kernel already in 64 bit...
>> >
>> > what does it mean "32-bit relocation outside of kernel" ?
>> >
>> > why 32-bit is involved ?
>>
>> The 64-bit kernel has both 64 and 32 bit relocations (there are two
>> tables at the end of the kernel image). The error means that the
>> resulting relocation is believed to be outside the kernel image:
>>
>> http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/x86/boot/compressed/misc.c#n283
>>
>> Which means there is likely something wrong with this calculation in
>> your situation:
>>
>> /*
>>  * Calculate the delta between where vmlinux was linked to load
>>  * and where it was actually loaded.
>>  */
>> delta = min_addr - LOAD_PHYSICAL_ADDR;
>>
>
> Probably.

Please check attached that patch that will solve nokaslr.

Somehow I got "KASLR could not find suitable E820 region..."
so i only have "No relocation needed"

will check that later.
---
 arch/x86/boot/compressed/misc.c |   14 +-
 1 file changed, 9 insertions(+), 5 deletions(-)

Index: linux-2.6/arch/x86/boot/compressed/misc.c
===
--- linux-2.6.orig/arch/x86/boot/compressed/misc.c
+++ linux-2.6/arch/x86/boot/compressed/misc.c
@@ -235,8 +235,9 @@ static void error(char *x)
 		asm("hlt");
 }
 
-#if CONFIG_X86_NEED_RELOCS
-static void handle_relocations(void *output, unsigned long output_len)
+#ifdef CONFIG_X86_NEED_RELOCS
+static void handle_relocations(void *output_orig, void *output,
+			   unsigned long output_len)
 {
 	int *reloc;
 	unsigned long delta, map, ptr;
@@ -247,7 +248,7 @@ static void handle_relocations(void *out
 	 * Calculate the delta between where vmlinux was linked to load
 	 * and where it was actually loaded.
 	 */
-	delta = min_addr - LOAD_PHYSICAL_ADDR;
+	delta = min_addr - (unsigned long)output_orig;
 	if (!delta) {
 		debug_putstr("No relocation needed... ");
 		return;
@@ -304,7 +305,8 @@ static void handle_relocations(void *out
 #endif
 }
 #else
-static inline void handle_relocations(void *output, unsigned long output_len)
+static inline void handle_relocations(void *output_orig, void *output,
+  unsigned long output_len)
 { }
 #endif
 
@@ -365,6 +367,8 @@ asmlinkage void *decompress_kernel(void
   unsigned char *output,
   unsigned long output_len)
 {
+	unsigned char *output_orig = output;
+
 	real_mode = rmode;
 
 	sanitize_boot_params(real_mode);
@@ -417,7 +421,7 @@ asmlinkage void *decompress_kernel(void
 	debug_putstr("... ");
 	decompress(input_data, input_len, NULL, NULL, output, NULL, error);
 	parse_elf(output);
-	handle_relocations(output, output_len);
+	handle_relocations(output_orig, output, output_len);
 	debug_putstr("done.\nBooting the kernel.\n");
 	return output;
 }


Re: kaslr relocation incompitable with kernel loaded high

2014-04-21 Thread WANG Chao
On 04/21/14 at 11:01am, Kees Cook wrote:
> On Mon, Apr 21, 2014 at 10:56 AM, Yinghai Lu  wrote:
> > On Mon, Apr 21, 2014 at 3:52 AM, WANG Chao  wrote:
> >> Hi, Kees
> >>
> >> When I'm testing kaslr with kdump, I find that when 2nd kernel is loaded
> >> high, it doesn't boot.
> >>
> >> I reserved 128M memory at high with kernel cmdline
> >> "crashkernel=128M,high crashkernel=0,low", and for which I got:
> >>
> >> [0.00] Reserving 128MB of memory at 6896MB for crashkernel (System 
> >> RAM: 6013MB)
> >>
> >> Then I load kdump kernel into the reserved memory region, using a local
> >> modified kexec-tools which is passing e820 in boot_params.
> >>
> >> The e820 map of system RAM passed to 2nd kernel:
> >>
> >> E820 memmap (of RAM):
> >> 1000-0009e3ff (1)
> >> 0001af00-0001b6f5dfff (1)
> >> 0001b6fff400-0001b6ff (1)
> >>
> >> In which, 2nd kernel is loaded at 0x1b500.
> >>
> >> After triggerred a system crash, 2nd kernel doesn't boot even with
> >> "nokaslr" cmdline:
> >>
> >> # echo c > /proc/sysrq-trigger
> >> [..]
> >>
> >> I'm in purgatory
> >> early console in decompress_kernel
> >> KASLR disabled...
> >>
> >> Decompressing Linux... Parsing ELF... Performing relocations...
> >>
> >> 32-bit relocation outside of kernel!
> >
> > Interesting, when kernel get at "early console in decompress_kernel"
> > kernel already in 64 bit...
> >
> > what does it mean "32-bit relocation outside of kernel" ?
> >
> > why 32-bit is involved ?
> 
> The 64-bit kernel has both 64 and 32 bit relocations (there are two
> tables at the end of the kernel image). The error means that the
> resulting relocation is believed to be outside the kernel image:
> 
> http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/x86/boot/compressed/misc.c#n283
> 
> Which means there is likely something wrong with this calculation in
> your situation:
> 
> /*
>  * Calculate the delta between where vmlinux was linked to load
>  * and where it was actually loaded.
>  */
> delta = min_addr - LOAD_PHYSICAL_ADDR;
> 

Probably.

I'm wondering why such relocation is still needed when kaslr
is disabled in 64bit path. I think the relocation work is already
handled in head_64.S.

FWIW, I got these following relocation info:

# arch/x86/tools/relocs --text vmlinux
.section ".data.reloc","a"
.balign 4
.long 0x
.long 0x81004687
[..]
.long 0x81e6b018
.long 0x
.long 0x810a
[..]
.long 0x81e6c9fc


Thanks
WANG Chao
--
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: kaslr relocation incompitable with kernel loaded high

2014-04-21 Thread Kees Cook
On Mon, Apr 21, 2014 at 10:56 AM, Yinghai Lu  wrote:
> On Mon, Apr 21, 2014 at 3:52 AM, WANG Chao  wrote:
>> Hi, Kees
>>
>> When I'm testing kaslr with kdump, I find that when 2nd kernel is loaded
>> high, it doesn't boot.
>>
>> I reserved 128M memory at high with kernel cmdline
>> "crashkernel=128M,high crashkernel=0,low", and for which I got:
>>
>> [0.00] Reserving 128MB of memory at 6896MB for crashkernel (System 
>> RAM: 6013MB)
>>
>> Then I load kdump kernel into the reserved memory region, using a local
>> modified kexec-tools which is passing e820 in boot_params.
>>
>> The e820 map of system RAM passed to 2nd kernel:
>>
>> E820 memmap (of RAM):
>> 1000-0009e3ff (1)
>> 0001af00-0001b6f5dfff (1)
>> 0001b6fff400-0001b6ff (1)
>>
>> In which, 2nd kernel is loaded at 0x1b500.
>>
>> After triggerred a system crash, 2nd kernel doesn't boot even with
>> "nokaslr" cmdline:
>>
>> # echo c > /proc/sysrq-trigger
>> [..]
>>
>> I'm in purgatory
>> early console in decompress_kernel
>> KASLR disabled...
>>
>> Decompressing Linux... Parsing ELF... Performing relocations...
>>
>> 32-bit relocation outside of kernel!
>
> Interesting, when kernel get at "early console in decompress_kernel"
> kernel already in 64 bit...
>
> what does it mean "32-bit relocation outside of kernel" ?
>
> why 32-bit is involved ?

The 64-bit kernel has both 64 and 32 bit relocations (there are two
tables at the end of the kernel image). The error means that the
resulting relocation is believed to be outside the kernel image:

http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/x86/boot/compressed/misc.c#n283

Which means there is likely something wrong with this calculation in
your situation:

/*
 * Calculate the delta between where vmlinux was linked to load
 * and where it was actually loaded.
 */
delta = min_addr - LOAD_PHYSICAL_ADDR;


-Kees

-- 
Kees Cook
Chrome OS Security
--
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: kaslr relocation incompitable with kernel loaded high

2014-04-21 Thread H. Peter Anvin
On 04/21/2014 10:56 AM, Yinghai Lu wrote:
>>
>> 32-bit relocation outside of kernel!
> 
> Interesting, when kernel get at "early console in decompress_kernel"
> kernel already in 64 bit...
> 
> what does it mean "32-bit relocation outside of kernel" ?
> 
> why 32-bit is involved ?
> 

Most addresses and immediates on 64 bits are 32 bits wide, which is why
we have the high kernel mapping in the first place.

-hpa


--
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: kaslr relocation incompitable with kernel loaded high

2014-04-21 Thread Yinghai Lu
On Mon, Apr 21, 2014 at 3:52 AM, WANG Chao  wrote:
> Hi, Kees
>
> When I'm testing kaslr with kdump, I find that when 2nd kernel is loaded
> high, it doesn't boot.
>
> I reserved 128M memory at high with kernel cmdline
> "crashkernel=128M,high crashkernel=0,low", and for which I got:
>
> [0.00] Reserving 128MB of memory at 6896MB for crashkernel (System 
> RAM: 6013MB)
>
> Then I load kdump kernel into the reserved memory region, using a local
> modified kexec-tools which is passing e820 in boot_params.
>
> The e820 map of system RAM passed to 2nd kernel:
>
> E820 memmap (of RAM):
> 1000-0009e3ff (1)
> 0001af00-0001b6f5dfff (1)
> 0001b6fff400-0001b6ff (1)
>
> In which, 2nd kernel is loaded at 0x1b500.
>
> After triggerred a system crash, 2nd kernel doesn't boot even with
> "nokaslr" cmdline:
>
> # echo c > /proc/sysrq-trigger
> [..]
>
> I'm in purgatory
> early console in decompress_kernel
> KASLR disabled...
>
> Decompressing Linux... Parsing ELF... Performing relocations...
>
> 32-bit relocation outside of kernel!

Interesting, when kernel get at "early console in decompress_kernel"
kernel already in 64 bit...

what does it mean "32-bit relocation outside of kernel" ?

why 32-bit is involved ?

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: kaslr relocation incompitable with kernel loaded high

2014-04-21 Thread Yinghai Lu
On Mon, Apr 21, 2014 at 3:52 AM, WANG Chao chaow...@redhat.com wrote:
 Hi, Kees

 When I'm testing kaslr with kdump, I find that when 2nd kernel is loaded
 high, it doesn't boot.

 I reserved 128M memory at high with kernel cmdline
 crashkernel=128M,high crashkernel=0,low, and for which I got:

 [0.00] Reserving 128MB of memory at 6896MB for crashkernel (System 
 RAM: 6013MB)

 Then I load kdump kernel into the reserved memory region, using a local
 modified kexec-tools which is passing e820 in boot_params.

 The e820 map of system RAM passed to 2nd kernel:

 E820 memmap (of RAM):
 1000-0009e3ff (1)
 0001af00-0001b6f5dfff (1)
 0001b6fff400-0001b6ff (1)

 In which, 2nd kernel is loaded at 0x1b500.

 After triggerred a system crash, 2nd kernel doesn't boot even with
 nokaslr cmdline:

 # echo c  /proc/sysrq-trigger
 [..]

 I'm in purgatory
 early console in decompress_kernel
 KASLR disabled...

 Decompressing Linux... Parsing ELF... Performing relocations...

 32-bit relocation outside of kernel!

Interesting, when kernel get at early console in decompress_kernel
kernel already in 64 bit...

what does it mean 32-bit relocation outside of kernel ?

why 32-bit is involved ?

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: kaslr relocation incompitable with kernel loaded high

2014-04-21 Thread H. Peter Anvin
On 04/21/2014 10:56 AM, Yinghai Lu wrote:

 32-bit relocation outside of kernel!
 
 Interesting, when kernel get at early console in decompress_kernel
 kernel already in 64 bit...
 
 what does it mean 32-bit relocation outside of kernel ?
 
 why 32-bit is involved ?
 

Most addresses and immediates on 64 bits are 32 bits wide, which is why
we have the high kernel mapping in the first place.

-hpa


--
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: kaslr relocation incompitable with kernel loaded high

2014-04-21 Thread Kees Cook
On Mon, Apr 21, 2014 at 10:56 AM, Yinghai Lu ying...@kernel.org wrote:
 On Mon, Apr 21, 2014 at 3:52 AM, WANG Chao chaow...@redhat.com wrote:
 Hi, Kees

 When I'm testing kaslr with kdump, I find that when 2nd kernel is loaded
 high, it doesn't boot.

 I reserved 128M memory at high with kernel cmdline
 crashkernel=128M,high crashkernel=0,low, and for which I got:

 [0.00] Reserving 128MB of memory at 6896MB for crashkernel (System 
 RAM: 6013MB)

 Then I load kdump kernel into the reserved memory region, using a local
 modified kexec-tools which is passing e820 in boot_params.

 The e820 map of system RAM passed to 2nd kernel:

 E820 memmap (of RAM):
 1000-0009e3ff (1)
 0001af00-0001b6f5dfff (1)
 0001b6fff400-0001b6ff (1)

 In which, 2nd kernel is loaded at 0x1b500.

 After triggerred a system crash, 2nd kernel doesn't boot even with
 nokaslr cmdline:

 # echo c  /proc/sysrq-trigger
 [..]

 I'm in purgatory
 early console in decompress_kernel
 KASLR disabled...

 Decompressing Linux... Parsing ELF... Performing relocations...

 32-bit relocation outside of kernel!

 Interesting, when kernel get at early console in decompress_kernel
 kernel already in 64 bit...

 what does it mean 32-bit relocation outside of kernel ?

 why 32-bit is involved ?

The 64-bit kernel has both 64 and 32 bit relocations (there are two
tables at the end of the kernel image). The error means that the
resulting relocation is believed to be outside the kernel image:

http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/x86/boot/compressed/misc.c#n283

Which means there is likely something wrong with this calculation in
your situation:

/*
 * Calculate the delta between where vmlinux was linked to load
 * and where it was actually loaded.
 */
delta = min_addr - LOAD_PHYSICAL_ADDR;


-Kees

-- 
Kees Cook
Chrome OS Security
--
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: kaslr relocation incompitable with kernel loaded high

2014-04-21 Thread WANG Chao
On 04/21/14 at 11:01am, Kees Cook wrote:
 On Mon, Apr 21, 2014 at 10:56 AM, Yinghai Lu ying...@kernel.org wrote:
  On Mon, Apr 21, 2014 at 3:52 AM, WANG Chao chaow...@redhat.com wrote:
  Hi, Kees
 
  When I'm testing kaslr with kdump, I find that when 2nd kernel is loaded
  high, it doesn't boot.
 
  I reserved 128M memory at high with kernel cmdline
  crashkernel=128M,high crashkernel=0,low, and for which I got:
 
  [0.00] Reserving 128MB of memory at 6896MB for crashkernel (System 
  RAM: 6013MB)
 
  Then I load kdump kernel into the reserved memory region, using a local
  modified kexec-tools which is passing e820 in boot_params.
 
  The e820 map of system RAM passed to 2nd kernel:
 
  E820 memmap (of RAM):
  1000-0009e3ff (1)
  0001af00-0001b6f5dfff (1)
  0001b6fff400-0001b6ff (1)
 
  In which, 2nd kernel is loaded at 0x1b500.
 
  After triggerred a system crash, 2nd kernel doesn't boot even with
  nokaslr cmdline:
 
  # echo c  /proc/sysrq-trigger
  [..]
 
  I'm in purgatory
  early console in decompress_kernel
  KASLR disabled...
 
  Decompressing Linux... Parsing ELF... Performing relocations...
 
  32-bit relocation outside of kernel!
 
  Interesting, when kernel get at early console in decompress_kernel
  kernel already in 64 bit...
 
  what does it mean 32-bit relocation outside of kernel ?
 
  why 32-bit is involved ?
 
 The 64-bit kernel has both 64 and 32 bit relocations (there are two
 tables at the end of the kernel image). The error means that the
 resulting relocation is believed to be outside the kernel image:
 
 http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/x86/boot/compressed/misc.c#n283
 
 Which means there is likely something wrong with this calculation in
 your situation:
 
 /*
  * Calculate the delta between where vmlinux was linked to load
  * and where it was actually loaded.
  */
 delta = min_addr - LOAD_PHYSICAL_ADDR;
 

Probably.

I'm wondering why such relocation is still needed when kaslr
is disabled in 64bit path. I think the relocation work is already
handled in head_64.S.

FWIW, I got these following relocation info:

# arch/x86/tools/relocs --text vmlinux
.section .data.reloc,a
.balign 4
.long 0x
.long 0x81004687
[..]
.long 0x81e6b018
.long 0x
.long 0x810a
[..]
.long 0x81e6c9fc


Thanks
WANG Chao
--
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: kaslr relocation incompitable with kernel loaded high

2014-04-21 Thread Yinghai Lu
On Mon, Apr 21, 2014 at 8:16 PM, WANG Chao chaow...@redhat.com wrote:
 On 04/21/14 at 11:01am, Kees Cook wrote:
 On Mon, Apr 21, 2014 at 10:56 AM, Yinghai Lu ying...@kernel.org wrote:
  On Mon, Apr 21, 2014 at 3:52 AM, WANG Chao chaow...@redhat.com wrote:
  Hi, Kees
 
  When I'm testing kaslr with kdump, I find that when 2nd kernel is loaded
  high, it doesn't boot.
 
  I reserved 128M memory at high with kernel cmdline
  crashkernel=128M,high crashkernel=0,low, and for which I got:
 
  [0.00] Reserving 128MB of memory at 6896MB for crashkernel 
  (System RAM: 6013MB)
 
  Then I load kdump kernel into the reserved memory region, using a local
  modified kexec-tools which is passing e820 in boot_params.
 
  The e820 map of system RAM passed to 2nd kernel:
 
  E820 memmap (of RAM):
  1000-0009e3ff (1)
  0001af00-0001b6f5dfff (1)
  0001b6fff400-0001b6ff (1)
 
  In which, 2nd kernel is loaded at 0x1b500.
 
  After triggerred a system crash, 2nd kernel doesn't boot even with
  nokaslr cmdline:
 
  # echo c  /proc/sysrq-trigger
  [..]
 
  I'm in purgatory
  early console in decompress_kernel
  KASLR disabled...
 
  Decompressing Linux... Parsing ELF... Performing relocations...
 
  32-bit relocation outside of kernel!
 
  Interesting, when kernel get at early console in decompress_kernel
  kernel already in 64 bit...
 
  what does it mean 32-bit relocation outside of kernel ?
 
  why 32-bit is involved ?

 The 64-bit kernel has both 64 and 32 bit relocations (there are two
 tables at the end of the kernel image). The error means that the
 resulting relocation is believed to be outside the kernel image:

 http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/x86/boot/compressed/misc.c#n283

 Which means there is likely something wrong with this calculation in
 your situation:

 /*
  * Calculate the delta between where vmlinux was linked to load
  * and where it was actually loaded.
  */
 delta = min_addr - LOAD_PHYSICAL_ADDR;


 Probably.

Please check attached that patch that will solve nokaslr.

Somehow I got KASLR could not find suitable E820 region...
so i only have No relocation needed

will check that later.
---
 arch/x86/boot/compressed/misc.c |   14 +-
 1 file changed, 9 insertions(+), 5 deletions(-)

Index: linux-2.6/arch/x86/boot/compressed/misc.c
===
--- linux-2.6.orig/arch/x86/boot/compressed/misc.c
+++ linux-2.6/arch/x86/boot/compressed/misc.c
@@ -235,8 +235,9 @@ static void error(char *x)
 		asm(hlt);
 }
 
-#if CONFIG_X86_NEED_RELOCS
-static void handle_relocations(void *output, unsigned long output_len)
+#ifdef CONFIG_X86_NEED_RELOCS
+static void handle_relocations(void *output_orig, void *output,
+			   unsigned long output_len)
 {
 	int *reloc;
 	unsigned long delta, map, ptr;
@@ -247,7 +248,7 @@ static void handle_relocations(void *out
 	 * Calculate the delta between where vmlinux was linked to load
 	 * and where it was actually loaded.
 	 */
-	delta = min_addr - LOAD_PHYSICAL_ADDR;
+	delta = min_addr - (unsigned long)output_orig;
 	if (!delta) {
 		debug_putstr(No relocation needed... );
 		return;
@@ -304,7 +305,8 @@ static void handle_relocations(void *out
 #endif
 }
 #else
-static inline void handle_relocations(void *output, unsigned long output_len)
+static inline void handle_relocations(void *output_orig, void *output,
+  unsigned long output_len)
 { }
 #endif
 
@@ -365,6 +367,8 @@ asmlinkage void *decompress_kernel(void
   unsigned char *output,
   unsigned long output_len)
 {
+	unsigned char *output_orig = output;
+
 	real_mode = rmode;
 
 	sanitize_boot_params(real_mode);
@@ -417,7 +421,7 @@ asmlinkage void *decompress_kernel(void
 	debug_putstr(... );
 	decompress(input_data, input_len, NULL, NULL, output, NULL, error);
 	parse_elf(output);
-	handle_relocations(output, output_len);
+	handle_relocations(output_orig, output, output_len);
 	debug_putstr(done.\nBooting the kernel.\n);
 	return output;
 }


Re: kaslr relocation incompitable with kernel loaded high

2014-04-21 Thread WANG Chao
On 04/21/14 at 09:58pm, Yinghai Lu wrote:
 On Mon, Apr 21, 2014 at 8:16 PM, WANG Chao chaow...@redhat.com wrote:
  On 04/21/14 at 11:01am, Kees Cook wrote:
  On Mon, Apr 21, 2014 at 10:56 AM, Yinghai Lu ying...@kernel.org wrote:
   On Mon, Apr 21, 2014 at 3:52 AM, WANG Chao chaow...@redhat.com wrote:
   Hi, Kees
  
   When I'm testing kaslr with kdump, I find that when 2nd kernel is loaded
   high, it doesn't boot.
  
   I reserved 128M memory at high with kernel cmdline
   crashkernel=128M,high crashkernel=0,low, and for which I got:
  
   [0.00] Reserving 128MB of memory at 6896MB for crashkernel 
   (System RAM: 6013MB)
  
   Then I load kdump kernel into the reserved memory region, using a local
   modified kexec-tools which is passing e820 in boot_params.
  
   The e820 map of system RAM passed to 2nd kernel:
  
   E820 memmap (of RAM):
   1000-0009e3ff (1)
   0001af00-0001b6f5dfff (1)
   0001b6fff400-0001b6ff (1)
  
   In which, 2nd kernel is loaded at 0x1b500.
  
   After triggerred a system crash, 2nd kernel doesn't boot even with
   nokaslr cmdline:
  
   # echo c  /proc/sysrq-trigger
   [..]
  
   I'm in purgatory
   early console in decompress_kernel
   KASLR disabled...
  
   Decompressing Linux... Parsing ELF... Performing relocations...
  
   32-bit relocation outside of kernel!
  
   Interesting, when kernel get at early console in decompress_kernel
   kernel already in 64 bit...
  
   what does it mean 32-bit relocation outside of kernel ?
  
   why 32-bit is involved ?
 
  The 64-bit kernel has both 64 and 32 bit relocations (there are two
  tables at the end of the kernel image). The error means that the
  resulting relocation is believed to be outside the kernel image:
 
  http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/x86/boot/compressed/misc.c#n283
 
  Which means there is likely something wrong with this calculation in
  your situation:
 
  /*
   * Calculate the delta between where vmlinux was linked to load
   * and where it was actually loaded.
   */
  delta = min_addr - LOAD_PHYSICAL_ADDR;
 
 
  Probably.
 
 Please check attached that patch that will solve nokaslr.
 
 Somehow I got KASLR could not find suitable E820 region...
 so i only have No relocation needed

I think it makes sense. If output from choose_kernel_location() doesn't
change (output == output_orig), we shouldn't call relocation code.

There are two situations that makes output == output_orig:
- nokaslr case
- KASLR could not find suitable E820 region case.

 
 will check that later.

 ---
  arch/x86/boot/compressed/misc.c |   14 +-
  1 file changed, 9 insertions(+), 5 deletions(-)
 
 Index: linux-2.6/arch/x86/boot/compressed/misc.c
 ===
 --- linux-2.6.orig/arch/x86/boot/compressed/misc.c
 +++ linux-2.6/arch/x86/boot/compressed/misc.c
 @@ -235,8 +235,9 @@ static void error(char *x)
   asm(hlt);
  }
  
 -#if CONFIG_X86_NEED_RELOCS
 -static void handle_relocations(void *output, unsigned long output_len)
 +#ifdef CONFIG_X86_NEED_RELOCS
 +static void handle_relocations(void *output_orig, void *output,
 +unsigned long output_len)
  {
   int *reloc;
   unsigned long delta, map, ptr;
 @@ -247,7 +248,7 @@ static void handle_relocations(void *out
* Calculate the delta between where vmlinux was linked to load
* and where it was actually loaded.
*/
 - delta = min_addr - LOAD_PHYSICAL_ADDR;
 + delta = min_addr - (unsigned long)output_orig;
   if (!delta) {
   debug_putstr(No relocation needed... );
   return;
 @@ -304,7 +305,8 @@ static void handle_relocations(void *out
  #endif
  }
  #else
 -static inline void handle_relocations(void *output, unsigned long output_len)
 +static inline void handle_relocations(void *output_orig, void *output,
 +   unsigned long output_len)
  { }
  #endif
  
 @@ -365,6 +367,8 @@ asmlinkage void *decompress_kernel(void
 unsigned char *output,
 unsigned long output_len)
  {
 + unsigned char *output_orig = output;
 +
   real_mode = rmode;
  
   sanitize_boot_params(real_mode);
 @@ -417,7 +421,7 @@ asmlinkage void *decompress_kernel(void
   debug_putstr(... );
   decompress(input_data, input_len, NULL, NULL, output, NULL, error);
   parse_elf(output);
 - handle_relocations(output, output_len);
 + handle_relocations(output_orig, output, output_len);
   debug_putstr(done.\nBooting the kernel.\n);
   return output;
  }

Thanks for the patch, it works for me :)

I also have a draft patch with the same idea as Yinghai. But I take a
slightly different approach:

diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index 1768461..7f392a8 100644
--- a/arch/x86/boot/compressed/misc.c
+++