|
7 | 7 | * Author: Will Deacon <[email protected]>
|
8 | 8 | */
|
9 | 9 |
|
| 10 | +#define pr_fmt(fmt) "Modules: " fmt |
| 11 | + |
10 | 12 | #include <linux/bitops.h>
|
11 | 13 | #include <linux/elf.h>
|
12 | 14 | #include <linux/ftrace.h>
|
|
24 | 26 | #include <asm/scs.h>
|
25 | 27 | #include <asm/sections.h>
|
26 | 28 |
|
27 |
| -static u64 __ro_after_init module_alloc_base = (u64)_etext - MODULES_VSIZE; |
| 29 | +static u64 module_direct_base __ro_after_init = 0; |
| 30 | +static u64 module_plt_base __ro_after_init = 0; |
28 | 31 |
|
29 |
| -#ifdef CONFIG_RANDOMIZE_BASE |
30 |
| -static int __init kaslr_module_init(void) |
| 32 | +/* |
| 33 | + * Choose a random page-aligned base address for a window of 'size' bytes which |
| 34 | + * entirely contains the interval [start, end - 1]. |
| 35 | + */ |
| 36 | +static u64 __init random_bounding_box(u64 size, u64 start, u64 end) |
31 | 37 | {
|
32 |
| - u64 module_range; |
33 |
| - u32 seed; |
| 38 | + u64 max_pgoff, pgoff; |
34 | 39 |
|
35 |
| - if (!kaslr_enabled()) |
| 40 | + if ((end - start) >= size) |
36 | 41 | return 0;
|
37 | 42 |
|
38 |
| - seed = get_random_u32(); |
| 43 | + max_pgoff = (size - (end - start)) / PAGE_SIZE; |
| 44 | + pgoff = get_random_u32_inclusive(0, max_pgoff); |
39 | 45 |
|
40 |
| - if (IS_ENABLED(CONFIG_RANDOMIZE_MODULE_REGION_FULL)) { |
41 |
| - /* |
42 |
| - * Randomize the module region over a 2 GB window covering the |
43 |
| - * kernel. This reduces the risk of modules leaking information |
44 |
| - * about the address of the kernel itself, but results in |
45 |
| - * branches between modules and the core kernel that are |
46 |
| - * resolved via PLTs. (Branches between modules will be |
47 |
| - * resolved normally.) |
48 |
| - */ |
49 |
| - module_range = SZ_2G - (u64)(_end - _stext); |
50 |
| - module_alloc_base = max((u64)_end - SZ_2G, (u64)MODULES_VADDR); |
| 46 | + return start - pgoff * PAGE_SIZE; |
| 47 | +} |
| 48 | + |
| 49 | +/* |
| 50 | + * Modules may directly reference data and text anywhere within the kernel |
| 51 | + * image and other modules. References using PREL32 relocations have a +/-2G |
| 52 | + * range, and so we need to ensure that the entire kernel image and all modules |
| 53 | + * fall within a 2G window such that these are always within range. |
| 54 | + * |
| 55 | + * Modules may directly branch to functions and code within the kernel text, |
| 56 | + * and to functions and code within other modules. These branches will use |
| 57 | + * CALL26/JUMP26 relocations with a +/-128M range. Without PLTs, we must ensure |
| 58 | + * that the entire kernel text and all module text falls within a 128M window |
| 59 | + * such that these are always within range. With PLTs, we can expand this to a |
| 60 | + * 2G window. |
| 61 | + * |
| 62 | + * We chose the 128M region to surround the entire kernel image (rather than |
| 63 | + * just the text) as using the same bounds for the 128M and 2G regions ensures |
| 64 | + * by construction that we never select a 128M region that is not a subset of |
| 65 | + * the 2G region. For very large and unusual kernel configurations this means |
| 66 | + * we may fall back to PLTs where they could have been avoided, but this keeps |
| 67 | + * the logic significantly simpler. |
| 68 | + */ |
| 69 | +static int __init module_init_limits(void) |
| 70 | +{ |
| 71 | + u64 kernel_end = (u64)_end; |
| 72 | + u64 kernel_start = (u64)_text; |
| 73 | + u64 kernel_size = kernel_end - kernel_start; |
| 74 | + |
| 75 | + /* |
| 76 | + * The default modules region is placed immediately below the kernel |
| 77 | + * image, and is large enough to use the full 2G relocation range. |
| 78 | + */ |
| 79 | + BUILD_BUG_ON(KIMAGE_VADDR != MODULES_END); |
| 80 | + BUILD_BUG_ON(MODULES_VSIZE < SZ_2G); |
| 81 | + |
| 82 | + if (!kaslr_enabled()) { |
| 83 | + if (kernel_size < SZ_128M) |
| 84 | + module_direct_base = kernel_end - SZ_128M; |
| 85 | + if (kernel_size < SZ_2G) |
| 86 | + module_plt_base = kernel_end - SZ_2G; |
51 | 87 | } else {
|
52 |
| - /* |
53 |
| - * Randomize the module region by setting module_alloc_base to |
54 |
| - * a PAGE_SIZE multiple in the range [_etext - MODULES_VSIZE, |
55 |
| - * _stext) . This guarantees that the resulting region still |
56 |
| - * covers [_stext, _etext], and that all relative branches can |
57 |
| - * be resolved without veneers unless this region is exhausted |
58 |
| - * and we fall back to a larger 2GB window in module_alloc() |
59 |
| - * when ARM64_MODULE_PLTS is enabled. |
60 |
| - */ |
61 |
| - module_range = MODULES_VSIZE - (u64)(_etext - _stext); |
| 88 | + u64 min = kernel_start; |
| 89 | + u64 max = kernel_end; |
| 90 | + |
| 91 | + if (IS_ENABLED(CONFIG_RANDOMIZE_MODULE_REGION_FULL)) { |
| 92 | + pr_info("2G module region forced by RANDOMIZE_MODULE_REGION_FULL\n"); |
| 93 | + } else { |
| 94 | + module_direct_base = random_bounding_box(SZ_128M, min, max); |
| 95 | + if (module_direct_base) { |
| 96 | + min = module_direct_base; |
| 97 | + max = module_direct_base + SZ_128M; |
| 98 | + } |
| 99 | + } |
| 100 | + |
| 101 | + module_plt_base = random_bounding_box(SZ_2G, min, max); |
62 | 102 | }
|
63 | 103 |
|
64 |
| - /* use the lower 21 bits to randomize the base of the module region */ |
65 |
| - module_alloc_base += (module_range * (seed & ((1 << 21) - 1))) >> 21; |
66 |
| - module_alloc_base &= PAGE_MASK; |
| 104 | + pr_info("%llu pages in range for non-PLT usage", |
| 105 | + module_direct_base ? (SZ_128M - kernel_size) / PAGE_SIZE : 0); |
| 106 | + pr_info("%llu pages in range for PLT usage", |
| 107 | + module_plt_base ? (SZ_2G - kernel_size) / PAGE_SIZE : 0); |
67 | 108 |
|
68 | 109 | return 0;
|
69 | 110 | }
|
70 |
| -subsys_initcall(kaslr_module_init) |
71 |
| -#endif |
| 111 | +subsys_initcall(module_init_limits); |
72 | 112 |
|
73 | 113 | void *module_alloc(unsigned long size)
|
74 | 114 | {
|
75 |
| - u64 module_alloc_end = module_alloc_base + MODULES_VSIZE; |
76 |
| - void *p; |
| 115 | + void *p = NULL; |
77 | 116 |
|
78 | 117 | /*
|
79 | 118 | * Where possible, prefer to allocate within direct branch range of the
|
80 |
| - * kernel such that no PLTs are necessary. This may fail, so we pass |
81 |
| - * __GFP_NOWARN to silence the resulting warning. |
| 119 | + * kernel such that no PLTs are necessary. |
82 | 120 | */
|
83 |
| - p = __vmalloc_node_range(size, MODULE_ALIGN, module_alloc_base, |
84 |
| - module_alloc_end, GFP_KERNEL | __GFP_NOWARN, |
85 |
| - PAGE_KERNEL, 0, NUMA_NO_NODE, |
86 |
| - __builtin_return_address(0)); |
| 121 | + if (module_direct_base) { |
| 122 | + p = __vmalloc_node_range(size, MODULE_ALIGN, |
| 123 | + module_direct_base, |
| 124 | + module_direct_base + SZ_128M, |
| 125 | + GFP_KERNEL | __GFP_NOWARN, |
| 126 | + PAGE_KERNEL, 0, NUMA_NO_NODE, |
| 127 | + __builtin_return_address(0)); |
| 128 | + } |
| 129 | + |
| 130 | + if (!p && module_plt_base) { |
| 131 | + p = __vmalloc_node_range(size, MODULE_ALIGN, |
| 132 | + module_plt_base, |
| 133 | + module_plt_base + SZ_2G, |
| 134 | + GFP_KERNEL | __GFP_NOWARN, |
| 135 | + PAGE_KERNEL, 0, NUMA_NO_NODE, |
| 136 | + __builtin_return_address(0)); |
| 137 | + } |
87 | 138 |
|
88 | 139 | if (!p) {
|
89 |
| - p = __vmalloc_node_range(size, MODULE_ALIGN, module_alloc_base, |
90 |
| - module_alloc_base + SZ_2G, GFP_KERNEL, |
91 |
| - PAGE_KERNEL, 0, NUMA_NO_NODE, |
92 |
| - __builtin_return_address(0)); |
| 140 | + pr_warn_ratelimited("%s: unable to allocate memory\n", |
| 141 | + __func__); |
93 | 142 | }
|
94 | 143 |
|
95 | 144 | if (p && (kasan_alloc_module_shadow(p, size, GFP_KERNEL) < 0)) {
|
|
0 commit comments