|
@@ -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,49 @@ do { \
|
|
|
} while (0)
|
|
|
#endif
|
|
|
|
|
|
+#ifdef CONFIG_RANDOMIZE_BASE
|
|
|
+static unsigned long module_load_offset;
|
|
|
+static int randomize_modules = 1;
|
|
|
+
|
|
|
+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_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_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,
|
|
|
- NUMA_NO_NODE, __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
|