diff options
Diffstat (limited to 'arch')
-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 18be189368bb..e69f9882bf95 100644 --- a/arch/x86/kernel/module.c +++ b/arch/x86/kernel/module.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/mm.h> | 28 | #include <linux/mm.h> |
29 | #include <linux/gfp.h> | 29 | #include <linux/gfp.h> |
30 | #include <linux/jump_label.h> | 30 | #include <linux/jump_label.h> |
31 | #include <linux/random.h> | ||
31 | 32 | ||
32 | #include <asm/page.h> | 33 | #include <asm/page.h> |
33 | #include <asm/pgtable.h> | 34 | #include <asm/pgtable.h> |
@@ -43,13 +44,52 @@ do { \ | |||
43 | } while (0) | 44 | } while (0) |
44 | #endif | 45 | #endif |
45 | 46 | ||
47 | #ifdef CONFIG_RANDOMIZE_BASE | ||
48 | static unsigned long module_load_offset; | ||
49 | static int randomize_modules = 1; | ||
50 | |||
51 | /* Mutex protects the module_load_offset. */ | ||
52 | static DEFINE_MUTEX(module_kaslr_mutex); | ||
53 | |||
54 | static int __init parse_nokaslr(char *p) | ||
55 | { | ||
56 | randomize_modules = 0; | ||
57 | return 0; | ||
58 | } | ||
59 | early_param("nokaslr", parse_nokaslr); | ||
60 | |||
61 | static unsigned long int get_module_load_offset(void) | ||
62 | { | ||
63 | if (randomize_modules) { | ||
64 | mutex_lock(&module_kaslr_mutex); | ||
65 | /* | ||
66 | * Calculate the module_load_offset the first time this | ||
67 | * code is called. Once calculated it stays the same until | ||
68 | * reboot. | ||
69 | */ | ||
70 | if (module_load_offset == 0) | ||
71 | module_load_offset = | ||
72 | (get_random_int() % 1024 + 1) * PAGE_SIZE; | ||
73 | mutex_unlock(&module_kaslr_mutex); | ||
74 | } | ||
75 | return module_load_offset; | ||
76 | } | ||
77 | #else | ||
78 | static unsigned long int get_module_load_offset(void) | ||
79 | { | ||
80 | return 0; | ||
81 | } | ||
82 | #endif | ||
83 | |||
46 | void *module_alloc(unsigned long size) | 84 | void *module_alloc(unsigned long size) |
47 | { | 85 | { |
48 | if (PAGE_ALIGN(size) > MODULES_LEN) | 86 | if (PAGE_ALIGN(size) > MODULES_LEN) |
49 | return NULL; | 87 | return NULL; |
50 | return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END, | 88 | return __vmalloc_node_range(size, 1, |
51 | GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL_EXEC, | 89 | MODULES_VADDR + get_module_load_offset(), |
52 | NUMA_NO_NODE, __builtin_return_address(0)); | 90 | MODULES_END, GFP_KERNEL | __GFP_HIGHMEM, |
91 | PAGE_KERNEL_EXEC, NUMA_NO_NODE, | ||
92 | __builtin_return_address(0)); | ||
53 | } | 93 | } |
54 | 94 | ||
55 | #ifdef CONFIG_X86_32 | 95 | #ifdef CONFIG_X86_32 |