|
Message-Id: <1380833605-26313-4-git-send-email-keescook@chromium.org> Date: Thu, 3 Oct 2013 13:53:21 -0700 From: Kees Cook <keescook@...omium.org> To: linux-kernel@...r.kernel.org Cc: x86@...nel.org, kernel-hardening@...ts.openwall.com, adurbin@...gle.com, Eric Northup <digitaleric@...gle.com>, jln@...gle.com, wad@...gle.com, Mathias Krause <minipli@...glemail.com>, Zhang Yanfei <zhangyanfei@...fujitsu.com>, "H. Peter Anvin" <hpa@...or.com>, keescook@...omium.org Subject: [PATCH 3/7] x86, kaslr: find minimum safe relocation position Examine all the known unsafe areas and avoid them by just raising the minimum relocation position to be past them. Signed-off-by: Kees Cook <keescook@...omium.org> --- arch/x86/boot/compressed/aslr.c | 50 +++++++++++++++++++++++++++++++++++++++ arch/x86/boot/compressed/misc.c | 10 ++------ arch/x86/boot/compressed/misc.h | 8 +++++++ 3 files changed, 60 insertions(+), 8 deletions(-) diff --git a/arch/x86/boot/compressed/aslr.c b/arch/x86/boot/compressed/aslr.c index b73cc66..ed7e9f0 100644 --- a/arch/x86/boot/compressed/aslr.c +++ b/arch/x86/boot/compressed/aslr.c @@ -2,6 +2,53 @@ #ifdef CONFIG_RANDOMIZE_BASE +static unsigned long find_minimum_location(unsigned long input, + unsigned long input_size, + unsigned long output, + unsigned long output_size) +{ + u64 initrd_start, initrd_size; + u64 cmd_line, cmd_line_size; + unsigned long unsafe, unsafe_len; + char *ptr; + + /* + * Mark off the region that is unsafe to overlap during + * decompression (see calculations at top of misc.c). + */ + unsafe_len = (output_size >> 12) + 32768 + 18; + unsafe = (unsigned long)input + input_size - unsafe_len; + + /* + * Locate other regions that cannot be over-written during + * decompression: initrd, cmd_line. + */ + initrd_start = (u64)real_mode->ext_ramdisk_image << 32; + initrd_start |= real_mode->hdr.ramdisk_image; + initrd_size = (u64)real_mode->ext_ramdisk_size << 32; + initrd_size |= real_mode->hdr.ramdisk_size; + cmd_line = (u64)real_mode->ext_cmd_line_ptr << 32; + cmd_line |= real_mode->hdr.cmd_line_ptr; + /* Calculate size of cmd_line. */ + ptr = (char *)(unsigned long)cmd_line; + for (cmd_line_size = 0; ptr[cmd_line_size++]; ) + ; + + /* Minimum location must be above all these regions: */ + output = max(output, unsafe + unsafe_len); + output = max(output, (unsigned long)free_mem_ptr + BOOT_HEAP_SIZE); + output = max(output, (unsigned long)free_mem_end_ptr + BOOT_STACK_SIZE); + output = max(output, (unsigned long)initrd_start + + (unsigned long)initrd_size); + output = max(output, (unsigned long)cmd_line + + (unsigned long)cmd_line_size); + + /* Make sure the location is still aligned. */ + output = ALIGN(output, CONFIG_PHYSICAL_ALIGN); + + return output; +} + unsigned char *choose_kernel_location(unsigned char *input, unsigned long input_size, unsigned char *output, @@ -14,6 +61,9 @@ unsigned char *choose_kernel_location(unsigned char *input, goto out; } + choice = find_minimum_location((unsigned long)input, input_size, + (unsigned long)output, output_size); + /* XXX: choose random location. */ out: diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index 7138768..196eaf3 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -112,14 +112,8 @@ struct boot_params *real_mode; /* Pointer to real-mode data */ void *memset(void *s, int c, size_t n); void *memcpy(void *dest, const void *src, size_t n); -#ifdef CONFIG_X86_64 -#define memptr long -#else -#define memptr unsigned -#endif - -static memptr free_mem_ptr; -static memptr free_mem_end_ptr; +memptr free_mem_ptr; +memptr free_mem_end_ptr; static char *vidmem; static int vidport; diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h index 9077af7..42f71bb 100644 --- a/arch/x86/boot/compressed/misc.h +++ b/arch/x86/boot/compressed/misc.h @@ -23,7 +23,15 @@ #define BOOT_BOOT_H #include "../ctype.h" +#ifdef CONFIG_X86_64 +#define memptr long +#else +#define memptr unsigned +#endif + /* misc.c */ +extern memptr free_mem_ptr; +extern memptr free_mem_end_ptr; extern struct boot_params *real_mode; /* Pointer to real-mode data */ void __putstr(const char *s); #define error_putstr(__x) __putstr(__x) -- 1.7.9.5
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.