diff options
Diffstat (limited to 'arch/arm64/kernel/module.c')
| -rw-r--r-- | arch/arm64/kernel/module.c | 126 | 
1 files changed, 0 insertions, 126 deletions
diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c index 47e0be610bb6..36b25af56324 100644 --- a/arch/arm64/kernel/module.c +++ b/arch/arm64/kernel/module.c @@ -12,144 +12,18 @@  #include <linux/bitops.h>  #include <linux/elf.h>  #include <linux/ftrace.h> -#include <linux/gfp.h>  #include <linux/kasan.h>  #include <linux/kernel.h>  #include <linux/mm.h>  #include <linux/moduleloader.h>  #include <linux/random.h>  #include <linux/scs.h> -#include <linux/vmalloc.h>  #include <asm/alternative.h>  #include <asm/insn.h>  #include <asm/scs.h>  #include <asm/sections.h> -static u64 module_direct_base __ro_after_init = 0; -static u64 module_plt_base __ro_after_init = 0; - -/* - * Choose a random page-aligned base address for a window of 'size' bytes which - * entirely contains the interval [start, end - 1]. - */ -static u64 __init random_bounding_box(u64 size, u64 start, u64 end) -{ -	u64 max_pgoff, pgoff; - -	if ((end - start) >= size) -		return 0; - -	max_pgoff = (size - (end - start)) / PAGE_SIZE; -	pgoff = get_random_u32_inclusive(0, max_pgoff); - -	return start - pgoff * PAGE_SIZE; -} - -/* - * Modules may directly reference data and text anywhere within the kernel - * image and other modules. References using PREL32 relocations have a +/-2G - * range, and so we need to ensure that the entire kernel image and all modules - * fall within a 2G window such that these are always within range. - * - * Modules may directly branch to functions and code within the kernel text, - * and to functions and code within other modules. These branches will use - * CALL26/JUMP26 relocations with a +/-128M range. Without PLTs, we must ensure - * that the entire kernel text and all module text falls within a 128M window - * such that these are always within range. With PLTs, we can expand this to a - * 2G window. - * - * We chose the 128M region to surround the entire kernel image (rather than - * just the text) as using the same bounds for the 128M and 2G regions ensures - * by construction that we never select a 128M region that is not a subset of - * the 2G region. For very large and unusual kernel configurations this means - * we may fall back to PLTs where they could have been avoided, but this keeps - * the logic significantly simpler. - */ -static int __init module_init_limits(void) -{ -	u64 kernel_end = (u64)_end; -	u64 kernel_start = (u64)_text; -	u64 kernel_size = kernel_end - kernel_start; - -	/* -	 * The default modules region is placed immediately below the kernel -	 * image, and is large enough to use the full 2G relocation range. -	 */ -	BUILD_BUG_ON(KIMAGE_VADDR != MODULES_END); -	BUILD_BUG_ON(MODULES_VSIZE < SZ_2G); - -	if (!kaslr_enabled()) { -		if (kernel_size < SZ_128M) -			module_direct_base = kernel_end - SZ_128M; -		if (kernel_size < SZ_2G) -			module_plt_base = kernel_end - SZ_2G; -	} else { -		u64 min = kernel_start; -		u64 max = kernel_end; - -		if (IS_ENABLED(CONFIG_RANDOMIZE_MODULE_REGION_FULL)) { -			pr_info("2G module region forced by RANDOMIZE_MODULE_REGION_FULL\n"); -		} else { -			module_direct_base = random_bounding_box(SZ_128M, min, max); -			if (module_direct_base) { -				min = module_direct_base; -				max = module_direct_base + SZ_128M; -			} -		} - -		module_plt_base = random_bounding_box(SZ_2G, min, max); -	} - -	pr_info("%llu pages in range for non-PLT usage", -		module_direct_base ? (SZ_128M - kernel_size) / PAGE_SIZE : 0); -	pr_info("%llu pages in range for PLT usage", -		module_plt_base ? (SZ_2G - kernel_size) / PAGE_SIZE : 0); - -	return 0; -} -subsys_initcall(module_init_limits); - -void *module_alloc(unsigned long size) -{ -	void *p = NULL; - -	/* -	 * Where possible, prefer to allocate within direct branch range of the -	 * kernel such that no PLTs are necessary. -	 */ -	if (module_direct_base) { -		p = __vmalloc_node_range(size, MODULE_ALIGN, -					 module_direct_base, -					 module_direct_base + SZ_128M, -					 GFP_KERNEL | __GFP_NOWARN, -					 PAGE_KERNEL, 0, NUMA_NO_NODE, -					 __builtin_return_address(0)); -	} - -	if (!p && module_plt_base) { -		p = __vmalloc_node_range(size, MODULE_ALIGN, -					 module_plt_base, -					 module_plt_base + SZ_2G, -					 GFP_KERNEL | __GFP_NOWARN, -					 PAGE_KERNEL, 0, NUMA_NO_NODE, -					 __builtin_return_address(0)); -	} - -	if (!p) { -		pr_warn_ratelimited("%s: unable to allocate memory\n", -				    __func__); -	} - -	if (p && (kasan_alloc_module_shadow(p, size, GFP_KERNEL) < 0)) { -		vfree(p); -		return NULL; -	} - -	/* Memory is intended to be executable, reset the pointer tag. */ -	return kasan_reset_tag(p); -} -  enum aarch64_reloc_op {  	RELOC_OP_NONE,  	RELOC_OP_ABS,  |