aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2015-02-13 10:04:55 -0500
committerBorislav Petkov <bp@suse.de>2015-02-19 05:38:54 -0500
commitf47233c2d34f243ecdaac179c3408a39ff9216a7 (patch)
treeb42d4847dd27acbea3526134adfc3f7b5780c5cd /arch/x86
parentbfa76d49576599a4b9f9b7a71f23d73d6dcff735 (diff)
x86/mm/ASLR: Propagate base load address calculation
Commit: e2b32e678513 ("x86, kaslr: randomize module base load address") makes the base address for module to be unconditionally randomized in case when CONFIG_RANDOMIZE_BASE is defined and "nokaslr" option isn't present on the commandline. This is not consistent with how choose_kernel_location() decides whether it will randomize kernel load base. Namely, CONFIG_HIBERNATION disables kASLR (unless "kaslr" option is explicitly specified on kernel commandline), which makes the state space larger than what module loader is looking at. IOW CONFIG_HIBERNATION && CONFIG_RANDOMIZE_BASE is a valid config option, kASLR wouldn't be applied by default in that case, but module loader is not aware of that. Instead of fixing the logic in module.c, this patch takes more generic aproach. It introduces a new bootparam setup data_type SETUP_KASLR and uses that to pass the information whether kaslr has been applied during kernel decompression, and sets a global 'kaslr_enabled' variable accordingly, so that any kernel code (module loading, livepatching, ...) can make decisions based on its value. x86 module loader is converted to make use of this flag. Signed-off-by: Jiri Kosina <jkosina@suse.cz> Acked-by: Kees Cook <keescook@chromium.org> Cc: "H. Peter Anvin" <hpa@linux.intel.com> Link: https://lkml.kernel.org/r/alpine.LNX.2.00.1502101411280.10719@pobox.suse.cz [ Always dump correct kaslr status when panicking ] Signed-off-by: Borislav Petkov <bp@suse.de>
Diffstat (limited to 'arch/x86')
-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
7 files changed, 63 insertions, 17 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 ab4734e5411d..16b6043cb073 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;
@@ -451,6 +458,9 @@ static void __init parse_setup_data(void)
451 case SETUP_EFI: 458 case SETUP_EFI:
452 parse_efi_setup(pa_data, data_len); 459 parse_efi_setup(pa_data, data_len);
453 break; 460 break;
461 case SETUP_KASLR:
462 parse_kaslr_setup(pa_data, data_len);
463 break;
454 default: 464 default:
455 break; 465 break;
456 } 466 }
@@ -833,10 +843,14 @@ static void __init trim_low_memory_range(void)
833static int 843static int
834dump_kernel_offset(struct notifier_block *self, unsigned long v, void *p) 844dump_kernel_offset(struct notifier_block *self, unsigned long v, void *p)
835{ 845{
836 pr_emerg("Kernel Offset: 0x%lx from 0x%lx " 846 if (kaslr_enabled)
837 "(relocation range: 0x%lx-0x%lx)\n", 847 pr_emerg("Kernel Offset: 0x%lx from 0x%lx (relocation range: 0x%lx-0x%lx)\n",
838 (unsigned long)&_text - __START_KERNEL, __START_KERNEL, 848 (unsigned long)&_text - __START_KERNEL,
839 __START_KERNEL_map, MODULES_VADDR-1); 849 __START_KERNEL,
850 __START_KERNEL_map,
851 MODULES_VADDR-1);
852 else
853 pr_emerg("Kernel Offset: disabled\n");
840 854
841 return 0; 855 return 0;
842} 856}