diff options
-rw-r--r-- | arch/s390/kernel/module.c | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c index 2d159b32885b..6588f4efe378 100644 --- a/arch/s390/kernel/module.c +++ b/arch/s390/kernel/module.c @@ -26,6 +26,7 @@ #include <asm/facility.h> #include <asm/ftrace.lds.h> #include <asm/set_memory.h> +#include <asm/setup.h> #if 0 #define DEBUGP printk @@ -35,6 +36,24 @@ #define PLT_ENTRY_SIZE 22 +static unsigned long get_module_load_offset(void) +{ + static DEFINE_MUTEX(module_kaslr_mutex); + static unsigned long module_load_offset; + + if (!kaslr_enabled()) + return 0; + /* + * Calculate the module_load_offset the first time this code + * is called. Once calculated it stays the same until reboot. + */ + mutex_lock(&module_kaslr_mutex); + if (!module_load_offset) + module_load_offset = get_random_u32_inclusive(1, 1024) * PAGE_SIZE; + mutex_unlock(&module_kaslr_mutex); + return module_load_offset; +} + void *module_alloc(unsigned long size) { gfp_t gfp_mask = GFP_KERNEL; @@ -42,7 +61,8 @@ void *module_alloc(unsigned long size) if (PAGE_ALIGN(size) > MODULES_LEN) return NULL; - p = __vmalloc_node_range(size, MODULE_ALIGN, MODULES_VADDR, MODULES_END, + p = __vmalloc_node_range(size, MODULE_ALIGN, + MODULES_VADDR + get_module_load_offset(), MODULES_END, gfp_mask, PAGE_KERNEL_EXEC, VM_DEFER_KMEMLEAK, NUMA_NO_NODE, __builtin_return_address(0)); if (p && (kasan_alloc_module_shadow(p, size, gfp_mask) < 0)) { |