s390/kaslr: randomize module base load address
authorHeiko Carstens <hca@linux.ibm.com>
Fri, 31 Mar 2023 13:03:23 +0000 (15:03 +0200)
committerVasily Gorbik <gor@linux.ibm.com>
Thu, 13 Apr 2023 15:36:26 +0000 (17:36 +0200)
Randomize the load address of modules in the kernel to make KASLR effective
for modules.
This is the s390 variant of commit e2b32e678513 ("x86, kaslr: randomize
module base load address").

Reviewed-by: Vasily Gorbik <gor@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
arch/s390/kernel/module.c

index 2d159b32885bc8434d0ddbd6443c47a12b57e0c4..6588f4efe378b14e2fcb3e19d55d131174ab3acd 100644 (file)
@@ -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
 
 #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)) {