x86, boot: skip relocs when load address unchanged
PATCH 1/1 x86, boot: skip relocs when load address unchanged
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.
---
This is a reimplementation of Baoquan's "kaslr: check if kernel location is changed", which performs the check without needing to change the function declaration. This should have exactly the same effect, but I dropped Vivek's Ack and Thomas's Test, since it's technically a different patch.
--- arch/x86/boot/compressed/misc.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
arch/x86/boot/compressed/misc.c +8 -1
@@ -373,6 +373,8 @@ asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap, unsigned long output_len, unsigned long run_size) { +unsigned char *output_orig = output; + real_mode = rmode;sanitize_boot_params (real_mode);
@@ -421,7 +423,12 @@ asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap,debug_putstr ("\nDecompressing Linux... " );decompress (input_data, input_len,NULL ,NULL , output,NULL , error);parse_elf (output); -handle_relocations (output, output_len); +/* +* 32-bit always performs relocations. 64-bit relocations are only +* needed if kASLR has chosen a different load address. +*/ +if (!IS_ENABLED (CONFIG_X86_64 ) || output != output_orig) +handle_relocations (output, output_len);debug_putstr ("done.\nBooting the kernel.\n" );return output; }
Signature · 6 lines
1.9.1 -- Kees Cook Chrome OS Security
Hi,
Quoted 4 lines · Kees Cook
This is a reimplementation of Baoquan's "kaslr: check if kernel location is changed", which performs the check without needing to change the function declaration. This should have exactly the same effect, but I dropped Vivek's Ack and Thomas's Test, since it's technically a different patch.
Your patch works for me, too.
Tested with linux-3.19-rc4 on a 64-bit system.
Thanks!
-Thomas
tip-bot for Kees Cook
merge bot[tip:x86/urgent] x86, boot: Skip relocs when load address unchanged
In reply to Kees Cookx86, boot: Skip relocs when load address unchanged
Commit-ID: f285f4a21c3253887caceed493089ece17579d59 Gitweb: http://git.kernel.org/tip/f285f4a21c3253887caceed493089ece17579d59 Author: Kees Cook <[email protected]> AuthorDate: Thu, 15 Jan 2015 16:51:46 -0800 Committer: Thomas Gleixner <[email protected]> CommitDate: Tue, 20 Jan 2015 12:37:23 +0100
x86, boot: Skip relocs when load address unchanged
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.
--- arch/x86/boot/compressed/misc.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
arch/x86/boot/compressed/misc.c +8 -1
@@ -373,6 +373,8 @@ asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap, unsigned long output_len, unsigned long run_size) { +unsigned char *output_orig = output; + real_mode = rmode;sanitize_boot_params (real_mode);
@@ -421,7 +423,12 @@ asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap,debug_putstr ("\nDecompressing Linux... " );decompress (input_data, input_len,NULL ,NULL , output,NULL , error);parse_elf (output); -handle_relocations (output, output_len); +/* +* 32-bit always performs relocations. 64-bit relocations are only +* needed if kASLR has chosen a different load address. +*/ +if (!IS_ENABLED (CONFIG_X86_64 ) || output != output_orig) +handle_relocations (output, output_len);debug_putstr ("done.\nBooting the kernel.\n" );return output; }
Quoted 3 lines · Kees Cook
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.
This patch works for me. And good to see it's being merged. About the patch log, I would say relocations do unexpected things when the kernel is above 1G since randomization is done from 16M to 1G, namely CONFIG_RANDOMIZE_BASE_MAX_OFFSET. So above 1G kernel text mapping will step into kernel module mapping region.
BTW, I am working on separate randomization of kernel physical and virtual address , will post it. But it won't conflict with this because I don't think it can be accepted in a short time. Before that this patch truly fix the kexec/kdump bug when kaslr is compiled in.
Thanks
Baoquan
Quoted 47 lines
Reported-by Baoquan He <[email protected]>Signed-off-by Kees Cook <[email protected]>---
This is a reimplementation of Baoquan's "kaslr: check if kernel location is changed", which performs the check without needing to change the function declaration. This should have exactly the same effect, but I dropped Vivek's Ack and Thomas's Test, since it's technically a different patch.--- arch/x86/boot/compressed/misc.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)arch/x86/boot/compressed/misc.c +8
-1@@ -373,6 +373,8 @@ asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap, unsigned long output_len, unsigned long run_size) { +unsigned char *output_orig = output; + real_mode = rmode;sanitize_boot_params (real_mode);@@ -421,7 +423,12 @@ asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap,debug_putstr ("\nDecompressing Linux... " );decompress (input_data, input_len,NULL ,NULL , output,NULL , error);parse_elf (output); -handle_relocations (output, output_len); +/* +* 32-bit always performs relocations. 64-bit relocations are only +* needed if kASLR has chosen a different load address. +*/ +if (!IS_ENABLED (CONFIG_X86_64 ) || output != output_orig) +handle_relocations (output, output_len);debug_putstr ("done.\nBooting the kernel.\n" );return output; }Signature · 6 lines
1.9.1 -- Kees Cook Chrome OS Security
Thanks for this patch, and good to see it in mainline!
This actually fixes the problem I reported here:
https://lkml.org/lkml/2014/12/1/15
I wish it to be backported into the Ubuntu Utopic kernel asap.
Quoted 5 lines
This patch works for me. And good to see it's being merged. About the patch log, I would say relocations do unexpected things when the kernel is above 1G since randomization is done from 16M to 1G, namely
CONFIG_RANDOMIZE_BASE_MAX_OFFSET. So above 1G kernel text mapping will step into kernel module mapping region.
I'm just speculating, but is it the reason why I only get problems when I boot with kexec? Maybe it's only then when the kernel gets above 1G. Otherwise, the kernels boot properly when they are booted from GRUB.
2015-01-20 14:04 GMT+01:00 Baoquan He <[email protected]>:
Quoted 72 lines · Kees Cook
Quoted 3 lines
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.
This patch works for me. And good to see it's being merged. About the patch log, I would say relocations do unexpected things when the kernel is above 1G since randomization is done from 16M to 1G, namely
CONFIG_RANDOMIZE_BASE_MAX_OFFSET. So above 1G kernel text mapping will step into kernel module mapping region.BTW, I am working on separate randomization of kernel physical and virtual address , will post it. But it won't conflict with this because I don't think it can be accepted in a short time. Before that this patch truly fix the kexec/kdump bug when kaslr is compiled in.
Thanks
BaoquanQuoted 44 lines
Reported-by Baoquan He <[email protected]>Signed-off-by Kees Cook <[email protected]>---
This is a reimplementation of Baoquan's "kaslr: check if kernel location is changed", which performs the check without needing to change the function declaration. This should have exactly the same effect, but I dropped Vivek's Ack and Thomas's Test, since it's technically a different patch.--- arch/x86/boot/compressed/misc.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)arch/x86/boot/compressed/misc.c +8
-2@@ -373,6 +373,8 @@ asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap, unsigned long output_len, unsigned long run_size) { +unsigned char *output_orig = output; + real_mode = rmode;sanitize_boot_params (real_mode);@@ -421,7 +423,12 @@ asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap,debug_putstr ("\nDecompressing Linux... " );decompress (input_data, input_len,NULL ,NULL , output,NULL , error);parse_elf (output); -handle_relocations (output, output_len); +/* +* 32-bit always performs relocations. 64-bit relocations are only +* needed if kASLR has chosen a different load address. +*/ +if (!IS_ENABLED (CONFIG_X86_64 ) || output != output_orig) +handle_relocations (output, output_len);debug_putstr ("done.\nBooting the kernel.\n" );return output; } --1.9.1
Quoted 3 lines
--
Kees Cook
Chrome OS Security--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Quoted 13 lines · MegaBrutal
Thanks for this patch, and good to see it in mainline!
This actually fixes the problem I reported here:
https://lkml.org/lkml/2014/12/1/15I wish it to be backported into the Ubuntu Utopic kernel asap.
Quoted 5 lines
This patch works for me. And good to see it's being merged. About the patch log, I would say relocations do unexpected things when the kernel is above 1G since randomization is done from 16M to 1G, namely
CONFIG_RANDOMIZE_BASE_MAX_OFFSET. So above 1G kernel text mapping will step into kernel module mapping region.
Quoted 4 lines
I'm just speculating, but is it the reason why I only get problems when I boot with kexec? Maybe it's only then when the kernel gets above 1G. Otherwise, the kernels boot properly when they are booted from GRUB.
Yeah, kexec loads kernel at the top of physical memory. And above 1G kernel mapping will step into module mapping area and collapse system. Grub doesn't incur this problem.
A message that is not in the archive (sent off-list or not yet received): CAE8gLh=9S-FMcekB43nM6RaAxEHsPkU0PK_=wNNbMT9YzkZiXw@mail.gmail.com
Quoted 6 lines · MegaBrutal
Thanks for this patch, and good to see it in mainline!
This actually fixes the problem I reported here:
https://lkml.org/lkml/2014/12/1/15I wish it to be backported into the Ubuntu Utopic kernel asap.
We marked the commit Cc: stable, so it ought to be picked up by the stable kernel and then it should show up in Ubuntu if they refresh their kernel package to the latest stable kernel.
Thanks,
Ingo