Messages in this thread Patch in this message | | | From | Thomas Gleixner <> | Subject | [patch 13/38] x86/modules: Make module_alloc() generally available | Date | Sun, 17 Jul 2022 01:17:30 +0200 (CEST) |
| |
module_alloc() allocates from the module region which is also available when CONFIG_MODULES=n. Non module builds should be able to allocate from that region nevertheless e.g. for creating call thunks.
Split the code out and make it possible to select for !MODULES builds.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de> --- arch/x86/Kconfig | 3 ++ arch/x86/kernel/module.c | 58 ------------------------------------------ arch/x86/mm/Makefile | 2 + arch/x86/mm/module_alloc.c | 62 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 67 insertions(+), 58 deletions(-)
--- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -2236,6 +2236,9 @@ config RANDOMIZE_MEMORY_PHYSICAL_PADDING If unsure, leave at the default value. +config MODULE_ALLOC + def_bool MODULES + config HOTPLUG_CPU def_bool y depends on SMP --- a/arch/x86/kernel/module.c +++ b/arch/x86/kernel/module.c @@ -8,21 +8,14 @@ #include <linux/moduleloader.h> #include <linux/elf.h> -#include <linux/vmalloc.h> #include <linux/fs.h> #include <linux/string.h> #include <linux/kernel.h> -#include <linux/kasan.h> #include <linux/bug.h> -#include <linux/mm.h> -#include <linux/gfp.h> #include <linux/jump_label.h> -#include <linux/random.h> #include <linux/memory.h> #include <asm/text-patching.h> -#include <asm/page.h> -#include <asm/setup.h> #include <asm/unwind.h> #if 0 @@ -36,57 +29,6 @@ do { \ } while (0) #endif -#ifdef CONFIG_RANDOMIZE_BASE -static unsigned long module_load_offset; - -/* Mutex protects the module_load_offset. */ -static DEFINE_MUTEX(module_kaslr_mutex); - -static unsigned long int get_module_load_offset(void) -{ - if (kaslr_enabled()) { - 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) -{ - gfp_t gfp_mask = GFP_KERNEL; - void *p; - - if (PAGE_ALIGN(size) > MODULES_LEN) - return NULL; - - p = __vmalloc_node_range(size, MODULE_ALIGN, - MODULES_VADDR + get_module_load_offset(), - MODULES_END, gfp_mask, PAGE_KERNEL, - VM_FLUSH_RESET_PERMS | VM_DEFER_KMEMLEAK, - NUMA_NO_NODE, __builtin_return_address(0)); - - if (p && (kasan_alloc_module_shadow(p, size, gfp_mask) < 0)) { - vfree(p); - return NULL; - } - - return p; -} - #ifdef CONFIG_X86_32 int apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, --- a/arch/x86/mm/Makefile +++ b/arch/x86/mm/Makefile @@ -59,3 +59,5 @@ obj-$(CONFIG_AMD_MEM_ENCRYPT) += mem_enc obj-$(CONFIG_AMD_MEM_ENCRYPT) += mem_encrypt_identity.o obj-$(CONFIG_AMD_MEM_ENCRYPT) += mem_encrypt_boot.o + +obj-$(CONFIG_MODULE_ALLOC) += module_alloc.o --- /dev/null +++ b/arch/x86/mm/module_alloc.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include <linux/kasan.h> +#include <linux/mm.h> +#include <linux/moduleloader.h> +#include <linux/mutex.h> +#include <linux/random.h> +#include <linux/vmalloc.h> + +#include <asm/setup.h> +#include <asm/page.h> + +#ifdef CONFIG_RANDOMIZE_BASE +static unsigned long module_load_offset; + +/* Mutex protects the module_load_offset. */ +static DEFINE_MUTEX(module_kaslr_mutex); + +static unsigned long int get_module_load_offset(void) +{ + if (kaslr_enabled()) { + 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) +{ + gfp_t gfp_mask = GFP_KERNEL; + void *p; + + if (PAGE_ALIGN(size) > MODULES_LEN) + return NULL; + + p = __vmalloc_node_range(size, MODULE_ALIGN, + MODULES_VADDR + get_module_load_offset(), + MODULES_END, gfp_mask, PAGE_KERNEL, + VM_FLUSH_RESET_PERMS | VM_DEFER_KMEMLEAK, + NUMA_NO_NODE, __builtin_return_address(0)); + + if (p && (kasan_alloc_module_shadow(p, size, gfp_mask) < 0)) { + vfree(p); + return NULL; + } + + return p; +}
| |