Skip to content

Commit

Permalink
x86/mm/KASLR: Propagate KASLR status to kernel proper
Browse files Browse the repository at this point in the history
Commit:

  e2b32e6 ("x86, kaslr: randomize module base load address")

made module base address randomization unconditional and didn't regard
disabled KKASLR due to CONFIG_HIBERNATION and command line option
"nokaslr". For more info see (now reverted) commit:

  f47233c ("x86/mm/ASLR: Propagate base load address calculation")

In order to propagate KASLR status to kernel proper, we need a single bit
in boot_params.hdr.loadflags and we've chosen bit 1 thus leaving the
top-down allocated bits for bits supposed to be used by the bootloader.

Originally-From: Jiri Kosina <jkosina@suse.cz>
Suggested-by: H. Peter Anvin <hpa@zytor.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Cc: Kees Cook <keescook@chromium.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
  • Loading branch information
Borislav Petkov authored and Ingo Molnar committed Apr 3, 2015
1 parent 47091e3 commit 78cac48
Show file tree
Hide file tree
Showing 8 changed files with 35 additions and 17 deletions.
6 changes: 6 additions & 0 deletions Documentation/x86/boot.txt
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,12 @@ Protocol: 2.00+
- If 0, the protected-mode code is loaded at 0x10000.
- If 1, the protected-mode code is loaded at 0x100000.

Bit 1 (kernel internal): ALSR_FLAG
- Used internally by the compressed kernel to communicate
KASLR status to kernel proper.
If 1, KASLR enabled.
If 0, KASLR disabled.

Bit 5 (write): QUIET_FLAG
- If 0, print early messages.
- If 1, suppress early messages.
Expand Down
5 changes: 4 additions & 1 deletion arch/x86/boot/compressed/aslr.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,8 @@ static unsigned long find_random_addr(unsigned long minimum,
return slots_fetch_random();
}

unsigned char *choose_kernel_location(unsigned char *input,
unsigned char *choose_kernel_location(struct boot_params *boot_params,
unsigned char *input,
unsigned long input_size,
unsigned char *output,
unsigned long output_size)
Expand All @@ -315,6 +316,8 @@ unsigned char *choose_kernel_location(unsigned char *input,
}
#endif

boot_params->hdr.loadflags |= KASLR_FLAG;

/* Record the various known unsafe memory ranges. */
mem_avoid_init((unsigned long)input, input_size,
(unsigned long)output, output_size);
Expand Down
5 changes: 4 additions & 1 deletion arch/x86/boot/compressed/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,9 @@ asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap,

real_mode = rmode;

/* Clear it for solely in-kernel use */
real_mode->hdr.loadflags &= ~KASLR_FLAG;

sanitize_boot_params(real_mode);

if (real_mode->screen_info.orig_video_mode == 7) {
Expand All @@ -401,7 +404,7 @@ asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap,
* the entire decompressed kernel plus relocation table, or the
* entire decompressed kernel plus .bss and .brk sections.
*/
output = choose_kernel_location(input_data, input_len, output,
output = choose_kernel_location(real_mode, input_data, input_len, output,
output_len > run_size ? output_len
: run_size);

Expand Down
6 changes: 4 additions & 2 deletions arch/x86/boot/compressed/misc.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,17 @@ int cmdline_find_option_bool(const char *option);

#if CONFIG_RANDOMIZE_BASE
/* aslr.c */
unsigned char *choose_kernel_location(unsigned char *input,
unsigned char *choose_kernel_location(struct boot_params *boot_params,
unsigned char *input,
unsigned long input_size,
unsigned char *output,
unsigned long output_size);
/* cpuflags.c */
bool has_cpuflag(int flag);
#else
static inline
unsigned char *choose_kernel_location(unsigned char *input,
unsigned char *choose_kernel_location(struct boot_params *boot_params,
unsigned char *input,
unsigned long input_size,
unsigned char *output,
unsigned long output_size)
Expand Down
5 changes: 5 additions & 0 deletions arch/x86/include/asm/setup.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ static inline void x86_ce4100_early_setup(void) { }
*/
extern struct boot_params boot_params;

static inline bool kaslr_enabled(void)
{
return !!(boot_params.hdr.loadflags & KASLR_FLAG);
}

/*
* Do NOT EVER look at the BIOS memory size location.
* It does not work on many machines.
Expand Down
1 change: 1 addition & 0 deletions arch/x86/include/uapi/asm/bootparam.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

/* loadflags */
#define LOADED_HIGH (1<<0)
#define KASLR_FLAG (1<<1)
#define QUIET_FLAG (1<<5)
#define KEEP_SEGMENTS (1<<6)
#define CAN_USE_HEAP (1<<7)
Expand Down
11 changes: 2 additions & 9 deletions arch/x86/kernel/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/setup.h>

#if 0
#define DEBUGP(fmt, ...) \
Expand All @@ -47,21 +48,13 @@ do { \

#ifdef CONFIG_RANDOMIZE_BASE
static unsigned long module_load_offset;
static int randomize_modules = 1;

/* Mutex protects the module_load_offset. */
static DEFINE_MUTEX(module_kaslr_mutex);

static int __init parse_nokaslr(char *p)
{
randomize_modules = 0;
return 0;
}
early_param("nokaslr", parse_nokaslr);

static unsigned long int get_module_load_offset(void)
{
if (randomize_modules) {
if (kaslr_enabled()) {
mutex_lock(&module_kaslr_mutex);
/*
* Calculate the module_load_offset the first time this
Expand Down
13 changes: 9 additions & 4 deletions arch/x86/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -832,10 +832,15 @@ static void __init trim_low_memory_range(void)
static int
dump_kernel_offset(struct notifier_block *self, unsigned long v, void *p)
{
pr_emerg("Kernel Offset: 0x%lx from 0x%lx "
"(relocation range: 0x%lx-0x%lx)\n",
(unsigned long)&_text - __START_KERNEL, __START_KERNEL,
__START_KERNEL_map, MODULES_VADDR-1);
if (kaslr_enabled()) {
pr_emerg("Kernel Offset: 0x%lx from 0x%lx (relocation range: 0x%lx-0x%lx)\n",
(unsigned long)&_text - __START_KERNEL,
__START_KERNEL,
__START_KERNEL_map,
MODULES_VADDR-1);
} else {
pr_emerg("Kernel Offset: disabled\n");
}

return 0;
}
Expand Down

0 comments on commit 78cac48

Please sign in to comment.