aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2015-02-19 06:06:04 -0500
committerIngo Molnar <mingo@kernel.org>2015-02-19 06:31:34 -0500
commita267b0a349bb021c010e36a2a13e1e16657b1b0f (patch)
tree4438a10ecc864f15ce6f37c1764fffa995a9a175
parentee408b4207c8281a91f039e89d06de264d319466 (diff)
parent4e7c22d447bb6d7e37bfe39ff658486ae78e8d77 (diff)
Merge branch 'tip-x86-kaslr' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp into x86/urgent
Pull ASLR and kASLR fixes from Borislav Petkov: - Add a global flag announcing KASLR state so that relevant code can do informed decisions based on its setting. (Jiri Kosina) - Fix a stack randomization entropy decrease bug. (Hector Marco-Gisbert) Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/x86/boot/compressed/aslr.c34
-rw-r--r--arch/x86/boot/compressed/misc.c3
-rw-r--r--arch/x86/boot/compressed/misc.h6
-rw-r--r--arch/x86/include/asm/page_types.h3
-rw-r--r--arch/x86/include/uapi/asm/bootparam.h1
-rw-r--r--arch/x86/kernel/module.c11
-rw-r--r--arch/x86/kernel/setup.c22
-rw-r--r--arch/x86/mm/mmap.c6
-rw-r--r--fs/binfmt_elf.c5
9 files changed, 69 insertions, 22 deletions
diff --git a/arch/x86/boot/compressed/aslr.c b/arch/x86/boot/compressed/aslr.c
index bb1376381985..7083c16cccba 100644
--- a/arch/x86/boot/compressed/aslr.c
+++ b/arch/x86/boot/compressed/aslr.c
@@ -14,6 +14,13 @@
14static const char build_str[] = UTS_RELEASE " (" LINUX_COMPILE_BY "@" 14static const char build_str[] = UTS_RELEASE " (" LINUX_COMPILE_BY "@"
15 LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION; 15 LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION;
16 16
17struct kaslr_setup_data {
18 __u64 next;
19 __u32 type;
20 __u32 len;
21 __u8 data[1];
22} kaslr_setup_data;
23
17#define I8254_PORT_CONTROL 0x43 24#define I8254_PORT_CONTROL 0x43
18#define I8254_PORT_COUNTER0 0x40 25#define I8254_PORT_COUNTER0 0x40
19#define I8254_CMD_READBACK 0xC0 26#define I8254_CMD_READBACK 0xC0
@@ -295,7 +302,29 @@ static unsigned long find_random_addr(unsigned long minimum,
295 return slots_fetch_random(); 302 return slots_fetch_random();
296} 303}
297 304
298unsigned char *choose_kernel_location(unsigned char *input, 305static void add_kaslr_setup_data(struct boot_params *params, __u8 enabled)
306{
307 struct setup_data *data;
308
309 kaslr_setup_data.type = SETUP_KASLR;
310 kaslr_setup_data.len = 1;
311 kaslr_setup_data.next = 0;
312 kaslr_setup_data.data[0] = enabled;
313
314 data = (struct setup_data *)(unsigned long)params->hdr.setup_data;
315
316 while (data && data->next)
317 data = (struct setup_data *)(unsigned long)data->next;
318
319 if (data)
320 data->next = (unsigned long)&kaslr_setup_data;
321 else
322 params->hdr.setup_data = (unsigned long)&kaslr_setup_data;
323
324}
325
326unsigned char *choose_kernel_location(struct boot_params *params,
327 unsigned char *input,
299 unsigned long input_size, 328 unsigned long input_size,
300 unsigned char *output, 329 unsigned char *output,
301 unsigned long output_size) 330 unsigned long output_size)
@@ -306,14 +335,17 @@ unsigned char *choose_kernel_location(unsigned char *input,
306#ifdef CONFIG_HIBERNATION 335#ifdef CONFIG_HIBERNATION
307 if (!cmdline_find_option_bool("kaslr")) { 336 if (!cmdline_find_option_bool("kaslr")) {
308 debug_putstr("KASLR disabled by default...\n"); 337 debug_putstr("KASLR disabled by default...\n");
338 add_kaslr_setup_data(params, 0);
309 goto out; 339 goto out;
310 } 340 }
311#else 341#else
312 if (cmdline_find_option_bool("nokaslr")) { 342 if (cmdline_find_option_bool("nokaslr")) {
313 debug_putstr("KASLR disabled by cmdline...\n"); 343 debug_putstr("KASLR disabled by cmdline...\n");
344 add_kaslr_setup_data(params, 0);
314 goto out; 345 goto out;
315 } 346 }
316#endif 347#endif
348 add_kaslr_setup_data(params, 1);
317 349
318 /* Record the various known unsafe memory ranges. */ 350 /* Record the various known unsafe memory ranges. */
319 mem_avoid_init((unsigned long)input, input_size, 351 mem_avoid_init((unsigned long)input, input_size,
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index a950864a64da..5903089c818f 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -401,7 +401,8 @@ asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap,
401 * the entire decompressed kernel plus relocation table, or the 401 * the entire decompressed kernel plus relocation table, or the
402 * entire decompressed kernel plus .bss and .brk sections. 402 * entire decompressed kernel plus .bss and .brk sections.
403 */ 403 */
404 output = choose_kernel_location(input_data, input_len, output, 404 output = choose_kernel_location(real_mode, input_data, input_len,
405 output,
405 output_len > run_size ? output_len 406 output_len > run_size ? output_len
406 : run_size); 407 : run_size);
407 408
diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h
index 24e3e569a13c..6d6730743024 100644
--- a/arch/x86/boot/compressed/misc.h
+++ b/arch/x86/boot/compressed/misc.h
@@ -56,7 +56,8 @@ int cmdline_find_option_bool(const char *option);
56 56
57#if CONFIG_RANDOMIZE_BASE 57#if CONFIG_RANDOMIZE_BASE
58/* aslr.c */ 58/* aslr.c */
59unsigned char *choose_kernel_location(unsigned char *input, 59unsigned char *choose_kernel_location(struct boot_params *params,
60 unsigned char *input,
60 unsigned long input_size, 61 unsigned long input_size,
61 unsigned char *output, 62 unsigned char *output,
62 unsigned long output_size); 63 unsigned long output_size);
@@ -64,7 +65,8 @@ unsigned char *choose_kernel_location(unsigned char *input,
64bool has_cpuflag(int flag); 65bool has_cpuflag(int flag);
65#else 66#else
66static inline 67static inline
67unsigned char *choose_kernel_location(unsigned char *input, 68unsigned char *choose_kernel_location(struct boot_params *params,
69 unsigned char *input,
68 unsigned long input_size, 70 unsigned long input_size,
69 unsigned char *output, 71 unsigned char *output,
70 unsigned long output_size) 72 unsigned long output_size)
diff --git a/arch/x86/include/asm/page_types.h b/arch/x86/include/asm/page_types.h
index f97fbe3abb67..3d43ce36eaba 100644
--- a/arch/x86/include/asm/page_types.h
+++ b/arch/x86/include/asm/page_types.h
@@ -3,6 +3,7 @@
3 3
4#include <linux/const.h> 4#include <linux/const.h>
5#include <linux/types.h> 5#include <linux/types.h>
6#include <asm/bootparam.h>
6 7
7/* PAGE_SHIFT determines the page size */ 8/* PAGE_SHIFT determines the page size */
8#define PAGE_SHIFT 12 9#define PAGE_SHIFT 12
@@ -51,6 +52,8 @@ extern int devmem_is_allowed(unsigned long pagenr);
51extern unsigned long max_low_pfn_mapped; 52extern unsigned long max_low_pfn_mapped;
52extern unsigned long max_pfn_mapped; 53extern unsigned long max_pfn_mapped;
53 54
55extern bool kaslr_enabled;
56
54static inline phys_addr_t get_max_mapped(void) 57static inline phys_addr_t get_max_mapped(void)
55{ 58{
56 return (phys_addr_t)max_pfn_mapped << PAGE_SHIFT; 59 return (phys_addr_t)max_pfn_mapped << PAGE_SHIFT;
diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
index 225b0988043a..44e6dd7e36a2 100644
--- a/arch/x86/include/uapi/asm/bootparam.h
+++ b/arch/x86/include/uapi/asm/bootparam.h
@@ -7,6 +7,7 @@
7#define SETUP_DTB 2 7#define SETUP_DTB 2
8#define SETUP_PCI 3 8#define SETUP_PCI 3
9#define SETUP_EFI 4 9#define SETUP_EFI 4
10#define SETUP_KASLR 5
10 11
11/* ram_size flags */ 12/* ram_size flags */
12#define RAMDISK_IMAGE_START_MASK 0x07FF 13#define RAMDISK_IMAGE_START_MASK 0x07FF
diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c
index e69f9882bf95..c3c59a3a14ad 100644
--- a/arch/x86/kernel/module.c
+++ b/arch/x86/kernel/module.c
@@ -32,6 +32,7 @@
32 32
33#include <asm/page.h> 33#include <asm/page.h>
34#include <asm/pgtable.h> 34#include <asm/pgtable.h>
35#include <asm/page_types.h>
35 36
36#if 0 37#if 0
37#define DEBUGP(fmt, ...) \ 38#define DEBUGP(fmt, ...) \
@@ -46,21 +47,13 @@ do { \
46 47
47#ifdef CONFIG_RANDOMIZE_BASE 48#ifdef CONFIG_RANDOMIZE_BASE
48static unsigned long module_load_offset; 49static unsigned long module_load_offset;
49static int randomize_modules = 1;
50 50
51/* Mutex protects the module_load_offset. */ 51/* Mutex protects the module_load_offset. */
52static DEFINE_MUTEX(module_kaslr_mutex); 52static DEFINE_MUTEX(module_kaslr_mutex);
53 53
54static int __init parse_nokaslr(char *p)
55{
56 randomize_modules = 0;
57 return 0;
58}
59early_param("nokaslr", parse_nokaslr);
60
61static unsigned long int get_module_load_offset(void) 54static unsigned long int get_module_load_offset(void)
62{ 55{
63 if (randomize_modules) { 56 if (kaslr_enabled) {
64 mutex_lock(&module_kaslr_mutex); 57 mutex_lock(&module_kaslr_mutex);
65 /* 58 /*
66 * Calculate the module_load_offset the first time this 59 * Calculate the module_load_offset the first time this
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index c4648adadd7d..0d8071d7addb 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -121,6 +121,8 @@
121unsigned long max_low_pfn_mapped; 121unsigned long max_low_pfn_mapped;
122unsigned long max_pfn_mapped; 122unsigned long max_pfn_mapped;
123 123
124bool __read_mostly kaslr_enabled = false;
125
124#ifdef CONFIG_DMI 126#ifdef CONFIG_DMI
125RESERVE_BRK(dmi_alloc, 65536); 127RESERVE_BRK(dmi_alloc, 65536);
126#endif 128#endif
@@ -424,6 +426,11 @@ static void __init reserve_initrd(void)
424} 426}
425#endif /* CONFIG_BLK_DEV_INITRD */ 427#endif /* CONFIG_BLK_DEV_INITRD */
426 428
429static void __init parse_kaslr_setup(u64 pa_data, u32 data_len)
430{
431 kaslr_enabled = (bool)(pa_data + sizeof(struct setup_data));
432}
433
427static void __init parse_setup_data(void) 434static void __init parse_setup_data(void)
428{ 435{
429 struct setup_data *data; 436 struct setup_data *data;
@@ -449,6 +456,9 @@ static void __init parse_setup_data(void)
449 case SETUP_EFI: 456 case SETUP_EFI:
450 parse_efi_setup(pa_data, data_len); 457 parse_efi_setup(pa_data, data_len);
451 break; 458 break;
459 case SETUP_KASLR:
460 parse_kaslr_setup(pa_data, data_len);
461 break;
452 default: 462 default:
453 break; 463 break;
454 } 464 }
@@ -831,10 +841,14 @@ static void __init trim_low_memory_range(void)
831static int 841static int
832dump_kernel_offset(struct notifier_block *self, unsigned long v, void *p) 842dump_kernel_offset(struct notifier_block *self, unsigned long v, void *p)
833{ 843{
834 pr_emerg("Kernel Offset: 0x%lx from 0x%lx " 844 if (kaslr_enabled)
835 "(relocation range: 0x%lx-0x%lx)\n", 845 pr_emerg("Kernel Offset: 0x%lx from 0x%lx (relocation range: 0x%lx-0x%lx)\n",
836 (unsigned long)&_text - __START_KERNEL, __START_KERNEL, 846 (unsigned long)&_text - __START_KERNEL,
837 __START_KERNEL_map, MODULES_VADDR-1); 847 __START_KERNEL,
848 __START_KERNEL_map,
849 MODULES_VADDR-1);
850 else
851 pr_emerg("Kernel Offset: disabled\n");
838 852
839 return 0; 853 return 0;
840} 854}
diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c
index 919b91205cd4..df4552bd239e 100644
--- a/arch/x86/mm/mmap.c
+++ b/arch/x86/mm/mmap.c
@@ -35,12 +35,12 @@ struct va_alignment __read_mostly va_align = {
35 .flags = -1, 35 .flags = -1,
36}; 36};
37 37
38static unsigned int stack_maxrandom_size(void) 38static unsigned long stack_maxrandom_size(void)
39{ 39{
40 unsigned int max = 0; 40 unsigned long max = 0;
41 if ((current->flags & PF_RANDOMIZE) && 41 if ((current->flags & PF_RANDOMIZE) &&
42 !(current->personality & ADDR_NO_RANDOMIZE)) { 42 !(current->personality & ADDR_NO_RANDOMIZE)) {
43 max = ((-1U) & STACK_RND_MASK) << PAGE_SHIFT; 43 max = ((-1UL) & STACK_RND_MASK) << PAGE_SHIFT;
44 } 44 }
45 45
46 return max; 46 return max;
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 02b16910f4c9..995986b8e36b 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -645,11 +645,12 @@ out:
645 645
646static unsigned long randomize_stack_top(unsigned long stack_top) 646static unsigned long randomize_stack_top(unsigned long stack_top)
647{ 647{
648 unsigned int random_variable = 0; 648 unsigned long random_variable = 0;
649 649
650 if ((current->flags & PF_RANDOMIZE) && 650 if ((current->flags & PF_RANDOMIZE) &&
651 !(current->personality & ADDR_NO_RANDOMIZE)) { 651 !(current->personality & ADDR_NO_RANDOMIZE)) {
652 random_variable = get_random_int() & STACK_RND_MASK; 652 random_variable = (unsigned long) get_random_int();
653 random_variable &= STACK_RND_MASK;
653 random_variable <<= PAGE_SHIFT; 654 random_variable <<= PAGE_SHIFT;
654 } 655 }
655#ifdef CONFIG_STACK_GROWSUP 656#ifdef CONFIG_STACK_GROWSUP