aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/boot/compressed
diff options
context:
space:
mode:
authorKees Cook <keescook@chromium.org>2013-10-10 20:18:14 -0400
committerH. Peter Anvin <hpa@linux.intel.com>2013-10-13 06:12:07 -0400
commit8ab3820fd5b2896d66da7bb2a906bc382e63e7bc (patch)
tree50f6f4458f86eb66552c13bef81169e44d27dc28 /arch/x86/boot/compressed
parentdd78b97367bd575918204cc89107c1479d3fc1a7 (diff)
x86, kaslr: Return location from decompress_kernel
This allows decompress_kernel to return a new location for the kernel to be relocated to. Additionally, enforces CONFIG_PHYSICAL_START as the minimum relocation position when building with CONFIG_RELOCATABLE. With CONFIG_RANDOMIZE_BASE set, the choose_kernel_location routine will select a new location to decompress the kernel, though here it is presently a no-op. The kernel command line option "nokaslr" is introduced to bypass these routines. Signed-off-by: Kees Cook <keescook@chromium.org> Link: http://lkml.kernel.org/r/1381450698-28710-3-git-send-email-keescook@chromium.org Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'arch/x86/boot/compressed')
-rw-r--r--arch/x86/boot/compressed/Makefile2
-rw-r--r--arch/x86/boot/compressed/aslr.c23
-rw-r--r--arch/x86/boot/compressed/cmdline.c2
-rw-r--r--arch/x86/boot/compressed/head_32.S10
-rw-r--r--arch/x86/boot/compressed/head_64.S16
-rw-r--r--arch/x86/boot/compressed/misc.c8
-rw-r--r--arch/x86/boot/compressed/misc.h27
7 files changed, 68 insertions, 20 deletions
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index 3312f1be9fd9..ae8b5dbbd8c5 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -27,7 +27,7 @@ HOST_EXTRACFLAGS += -I$(srctree)/tools/include
27 27
28VMLINUX_OBJS = $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \ 28VMLINUX_OBJS = $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \
29 $(obj)/string.o $(obj)/cmdline.o $(obj)/early_serial_console.o \ 29 $(obj)/string.o $(obj)/cmdline.o $(obj)/early_serial_console.o \
30 $(obj)/piggy.o $(obj)/cpuflags.o 30 $(obj)/piggy.o $(obj)/cpuflags.o $(obj)/aslr.o
31 31
32$(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone 32$(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone
33 33
diff --git a/arch/x86/boot/compressed/aslr.c b/arch/x86/boot/compressed/aslr.c
new file mode 100644
index 000000000000..b73cc66d201e
--- /dev/null
+++ b/arch/x86/boot/compressed/aslr.c
@@ -0,0 +1,23 @@
1#include "misc.h"
2
3#ifdef CONFIG_RANDOMIZE_BASE
4
5unsigned char *choose_kernel_location(unsigned char *input,
6 unsigned long input_size,
7 unsigned char *output,
8 unsigned long output_size)
9{
10 unsigned long choice = (unsigned long)output;
11
12 if (cmdline_find_option_bool("nokaslr")) {
13 debug_putstr("KASLR disabled...\n");
14 goto out;
15 }
16
17 /* XXX: choose random location. */
18
19out:
20 return (unsigned char *)choice;
21}
22
23#endif /* CONFIG_RANDOMIZE_BASE */
diff --git a/arch/x86/boot/compressed/cmdline.c b/arch/x86/boot/compressed/cmdline.c
index bffd73b45b1f..b68e3033e6b9 100644
--- a/arch/x86/boot/compressed/cmdline.c
+++ b/arch/x86/boot/compressed/cmdline.c
@@ -1,6 +1,6 @@
1#include "misc.h" 1#include "misc.h"
2 2
3#ifdef CONFIG_EARLY_PRINTK 3#if CONFIG_EARLY_PRINTK || CONFIG_RANDOMIZE_BASE
4 4
5static unsigned long fs; 5static unsigned long fs;
6static inline void set_fs(unsigned long seg) 6static inline void set_fs(unsigned long seg)
diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
index 5d6f6891b188..9116aac232c7 100644
--- a/arch/x86/boot/compressed/head_32.S
+++ b/arch/x86/boot/compressed/head_32.S
@@ -117,9 +117,11 @@ preferred_addr:
117 addl %eax, %ebx 117 addl %eax, %ebx
118 notl %eax 118 notl %eax
119 andl %eax, %ebx 119 andl %eax, %ebx
120#else 120 cmpl $LOAD_PHYSICAL_ADDR, %ebx
121 movl $LOAD_PHYSICAL_ADDR, %ebx 121 jge 1f
122#endif 122#endif
123 movl $LOAD_PHYSICAL_ADDR, %ebx
1241:
123 125
124 /* Target address to relocate to for decompression */ 126 /* Target address to relocate to for decompression */
125 addl $z_extract_offset, %ebx 127 addl $z_extract_offset, %ebx
@@ -191,14 +193,14 @@ relocated:
191 leal boot_heap(%ebx), %eax 193 leal boot_heap(%ebx), %eax
192 pushl %eax /* heap area */ 194 pushl %eax /* heap area */
193 pushl %esi /* real mode pointer */ 195 pushl %esi /* real mode pointer */
194 call decompress_kernel 196 call decompress_kernel /* returns kernel location in %eax */
195 addl $24, %esp 197 addl $24, %esp
196 198
197/* 199/*
198 * Jump to the decompressed kernel. 200 * Jump to the decompressed kernel.
199 */ 201 */
200 xorl %ebx, %ebx 202 xorl %ebx, %ebx
201 jmp *%ebp 203 jmp *%eax
202 204
203/* 205/*
204 * Stack and heap for uncompression 206 * Stack and heap for uncompression
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index c337422b575d..c5c1ae0997e7 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -94,9 +94,11 @@ ENTRY(startup_32)
94 addl %eax, %ebx 94 addl %eax, %ebx
95 notl %eax 95 notl %eax
96 andl %eax, %ebx 96 andl %eax, %ebx
97#else 97 cmpl $LOAD_PHYSICAL_ADDR, %ebx
98 movl $LOAD_PHYSICAL_ADDR, %ebx 98 jge 1f
99#endif 99#endif
100 movl $LOAD_PHYSICAL_ADDR, %ebx
1011:
100 102
101 /* Target address to relocate to for decompression */ 103 /* Target address to relocate to for decompression */
102 addl $z_extract_offset, %ebx 104 addl $z_extract_offset, %ebx
@@ -269,9 +271,11 @@ preferred_addr:
269 addq %rax, %rbp 271 addq %rax, %rbp
270 notq %rax 272 notq %rax
271 andq %rax, %rbp 273 andq %rax, %rbp
272#else 274 cmpq $LOAD_PHYSICAL_ADDR, %rbp
273 movq $LOAD_PHYSICAL_ADDR, %rbp 275 jge 1f
274#endif 276#endif
277 movq $LOAD_PHYSICAL_ADDR, %rbp
2781:
275 279
276 /* Target address to relocate to for decompression */ 280 /* Target address to relocate to for decompression */
277 leaq z_extract_offset(%rbp), %rbx 281 leaq z_extract_offset(%rbp), %rbx
@@ -339,13 +343,13 @@ relocated:
339 movl $z_input_len, %ecx /* input_len */ 343 movl $z_input_len, %ecx /* input_len */
340 movq %rbp, %r8 /* output target address */ 344 movq %rbp, %r8 /* output target address */
341 movq $z_output_len, %r9 /* decompressed length */ 345 movq $z_output_len, %r9 /* decompressed length */
342 call decompress_kernel 346 call decompress_kernel /* returns kernel location in %rax */
343 popq %rsi 347 popq %rsi
344 348
345/* 349/*
346 * Jump to the decompressed kernel. 350 * Jump to the decompressed kernel.
347 */ 351 */
348 jmp *%rbp 352 jmp *%rax
349 353
350 .code32 354 .code32
351no_longmode: 355no_longmode:
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index 434f077d2c4d..71387685dc16 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -395,7 +395,7 @@ static void parse_elf(void *output)
395 free(phdrs); 395 free(phdrs);
396} 396}
397 397
398asmlinkage void decompress_kernel(void *rmode, memptr heap, 398asmlinkage void *decompress_kernel(void *rmode, memptr heap,
399 unsigned char *input_data, 399 unsigned char *input_data,
400 unsigned long input_len, 400 unsigned long input_len,
401 unsigned char *output, 401 unsigned char *output,
@@ -422,6 +422,10 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap,
422 free_mem_ptr = heap; /* Heap */ 422 free_mem_ptr = heap; /* Heap */
423 free_mem_end_ptr = heap + BOOT_HEAP_SIZE; 423 free_mem_end_ptr = heap + BOOT_HEAP_SIZE;
424 424
425 output = choose_kernel_location(input_data, input_len,
426 output, output_len);
427
428 /* Validate memory location choices. */
425 if ((unsigned long)output & (MIN_KERNEL_ALIGN - 1)) 429 if ((unsigned long)output & (MIN_KERNEL_ALIGN - 1))
426 error("Destination address inappropriately aligned"); 430 error("Destination address inappropriately aligned");
427#ifdef CONFIG_X86_64 431#ifdef CONFIG_X86_64
@@ -441,5 +445,5 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap,
441 parse_elf(output); 445 parse_elf(output);
442 handle_relocations(output, output_len); 446 handle_relocations(output, output_len);
443 debug_putstr("done.\nBooting the kernel.\n"); 447 debug_putstr("done.\nBooting the kernel.\n");
444 return; 448 return output;
445} 449}
diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h
index 674019d8e235..9077af7fd0b8 100644
--- a/arch/x86/boot/compressed/misc.h
+++ b/arch/x86/boot/compressed/misc.h
@@ -39,23 +39,38 @@ static inline void debug_putstr(const char *s)
39 39
40#endif 40#endif
41 41
42#ifdef CONFIG_EARLY_PRINTK 42#if CONFIG_EARLY_PRINTK || CONFIG_RANDOMIZE_BASE
43
44/* cmdline.c */ 43/* cmdline.c */
45int cmdline_find_option(const char *option, char *buffer, int bufsize); 44int cmdline_find_option(const char *option, char *buffer, int bufsize);
46int cmdline_find_option_bool(const char *option); 45int cmdline_find_option_bool(const char *option);
46#endif
47 47
48/* early_serial_console.c */
49extern int early_serial_base;
50void console_init(void);
51 48
49#if CONFIG_RANDOMIZE_BASE
50/* aslr.c */
51unsigned char *choose_kernel_location(unsigned char *input,
52 unsigned long input_size,
53 unsigned char *output,
54 unsigned long output_size);
52#else 55#else
56static inline
57unsigned char *choose_kernel_location(unsigned char *input,
58 unsigned long input_size,
59 unsigned char *output,
60 unsigned long output_size)
61{
62 return output;
63}
64#endif
53 65
66#ifdef CONFIG_EARLY_PRINTK
54/* early_serial_console.c */ 67/* early_serial_console.c */
68extern int early_serial_base;
69void console_init(void);
70#else
55static const int early_serial_base; 71static const int early_serial_base;
56static inline void console_init(void) 72static inline void console_init(void)
57{ } 73{ }
58
59#endif 74#endif
60 75
61#endif 76#endif