diff options
Diffstat (limited to 'arch/x86/kernel/module.c')
| -rw-r--r-- | arch/x86/kernel/module.c | 46 | 
1 files changed, 43 insertions, 3 deletions
diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c index 216a4d754b0..e69f9882bf9 100644 --- a/arch/x86/kernel/module.c +++ b/arch/x86/kernel/module.c @@ -28,6 +28,7 @@  #include <linux/mm.h>  #include <linux/gfp.h>  #include <linux/jump_label.h> +#include <linux/random.h>  #include <asm/page.h>  #include <asm/pgtable.h> @@ -43,13 +44,52 @@ do {							\  } while (0)  #endif +#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) { +		mutex_lock(&module_kaslr_mutex); +		/* +		 * Calculate the module_load_offset the first time this +		 * code is called. Once calculated it stays the same until +		 * reboot. +		 */ +		if (module_load_offset == 0) +			module_load_offset = +				(get_random_int() % 1024 + 1) * PAGE_SIZE; +		mutex_unlock(&module_kaslr_mutex); +	} +	return module_load_offset; +} +#else +static unsigned long int get_module_load_offset(void) +{ +	return 0; +} +#endif +  void *module_alloc(unsigned long size)  {  	if (PAGE_ALIGN(size) > MODULES_LEN)  		return NULL; -	return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END, -				GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL_EXEC, -				-1, __builtin_return_address(0)); +	return __vmalloc_node_range(size, 1, +				    MODULES_VADDR + get_module_load_offset(), +				    MODULES_END, GFP_KERNEL | __GFP_HIGHMEM, +				    PAGE_KERNEL_EXEC, NUMA_NO_NODE, +				    __builtin_return_address(0));  }  #ifdef CONFIG_X86_32  | 
