|
12 | 12 | #include <linux/bitops.h>
|
13 | 13 | #include <linux/elf.h>
|
14 | 14 | #include <linux/ftrace.h>
|
15 |
| -#include <linux/gfp.h> |
16 | 15 | #include <linux/kasan.h>
|
17 | 16 | #include <linux/kernel.h>
|
18 | 17 | #include <linux/mm.h>
|
19 | 18 | #include <linux/moduleloader.h>
|
20 | 19 | #include <linux/random.h>
|
21 | 20 | #include <linux/scs.h>
|
22 |
| -#include <linux/vmalloc.h> |
23 |
| -#include <linux/execmem.h> |
24 | 21 |
|
25 | 22 | #include <asm/alternative.h>
|
26 | 23 | #include <asm/insn.h>
|
27 | 24 | #include <asm/scs.h>
|
28 | 25 | #include <asm/sections.h>
|
29 | 26 |
|
30 |
| -static u64 module_direct_base __ro_after_init = 0; |
31 |
| -static u64 module_plt_base __ro_after_init = 0; |
32 |
| - |
33 |
| -/* |
34 |
| - * Choose a random page-aligned base address for a window of 'size' bytes which |
35 |
| - * entirely contains the interval [start, end - 1]. |
36 |
| - */ |
37 |
| -static u64 __init random_bounding_box(u64 size, u64 start, u64 end) |
38 |
| -{ |
39 |
| - u64 max_pgoff, pgoff; |
40 |
| - |
41 |
| - if ((end - start) >= size) |
42 |
| - return 0; |
43 |
| - |
44 |
| - max_pgoff = (size - (end - start)) / PAGE_SIZE; |
45 |
| - pgoff = get_random_u32_inclusive(0, max_pgoff); |
46 |
| - |
47 |
| - return start - pgoff * PAGE_SIZE; |
48 |
| -} |
49 |
| - |
50 |
| -/* |
51 |
| - * Modules may directly reference data and text anywhere within the kernel |
52 |
| - * image and other modules. References using PREL32 relocations have a +/-2G |
53 |
| - * range, and so we need to ensure that the entire kernel image and all modules |
54 |
| - * fall within a 2G window such that these are always within range. |
55 |
| - * |
56 |
| - * Modules may directly branch to functions and code within the kernel text, |
57 |
| - * and to functions and code within other modules. These branches will use |
58 |
| - * CALL26/JUMP26 relocations with a +/-128M range. Without PLTs, we must ensure |
59 |
| - * that the entire kernel text and all module text falls within a 128M window |
60 |
| - * such that these are always within range. With PLTs, we can expand this to a |
61 |
| - * 2G window. |
62 |
| - * |
63 |
| - * We chose the 128M region to surround the entire kernel image (rather than |
64 |
| - * just the text) as using the same bounds for the 128M and 2G regions ensures |
65 |
| - * by construction that we never select a 128M region that is not a subset of |
66 |
| - * the 2G region. For very large and unusual kernel configurations this means |
67 |
| - * we may fall back to PLTs where they could have been avoided, but this keeps |
68 |
| - * the logic significantly simpler. |
69 |
| - */ |
70 |
| -static int __init module_init_limits(void) |
71 |
| -{ |
72 |
| - u64 kernel_end = (u64)_end; |
73 |
| - u64 kernel_start = (u64)_text; |
74 |
| - u64 kernel_size = kernel_end - kernel_start; |
75 |
| - |
76 |
| - /* |
77 |
| - * The default modules region is placed immediately below the kernel |
78 |
| - * image, and is large enough to use the full 2G relocation range. |
79 |
| - */ |
80 |
| - BUILD_BUG_ON(KIMAGE_VADDR != MODULES_END); |
81 |
| - BUILD_BUG_ON(MODULES_VSIZE < SZ_2G); |
82 |
| - |
83 |
| - if (!kaslr_enabled()) { |
84 |
| - if (kernel_size < SZ_128M) |
85 |
| - module_direct_base = kernel_end - SZ_128M; |
86 |
| - if (kernel_size < SZ_2G) |
87 |
| - module_plt_base = kernel_end - SZ_2G; |
88 |
| - } else { |
89 |
| - u64 min = kernel_start; |
90 |
| - u64 max = kernel_end; |
91 |
| - |
92 |
| - if (IS_ENABLED(CONFIG_RANDOMIZE_MODULE_REGION_FULL)) { |
93 |
| - pr_info("2G module region forced by RANDOMIZE_MODULE_REGION_FULL\n"); |
94 |
| - } else { |
95 |
| - module_direct_base = random_bounding_box(SZ_128M, min, max); |
96 |
| - if (module_direct_base) { |
97 |
| - min = module_direct_base; |
98 |
| - max = module_direct_base + SZ_128M; |
99 |
| - } |
100 |
| - } |
101 |
| - |
102 |
| - module_plt_base = random_bounding_box(SZ_2G, min, max); |
103 |
| - } |
104 |
| - |
105 |
| - pr_info("%llu pages in range for non-PLT usage", |
106 |
| - module_direct_base ? (SZ_128M - kernel_size) / PAGE_SIZE : 0); |
107 |
| - pr_info("%llu pages in range for PLT usage", |
108 |
| - module_plt_base ? (SZ_2G - kernel_size) / PAGE_SIZE : 0); |
109 |
| - |
110 |
| - return 0; |
111 |
| -} |
112 |
| - |
113 |
| -static struct execmem_info execmem_info __ro_after_init; |
114 |
| - |
115 |
| -struct execmem_info __init *execmem_arch_setup(void) |
116 |
| -{ |
117 |
| - unsigned long fallback_start = 0, fallback_end = 0; |
118 |
| - unsigned long start = 0, end = 0; |
119 |
| - |
120 |
| - module_init_limits(); |
121 |
| - |
122 |
| - /* |
123 |
| - * Where possible, prefer to allocate within direct branch range of the |
124 |
| - * kernel such that no PLTs are necessary. |
125 |
| - */ |
126 |
| - if (module_direct_base) { |
127 |
| - start = module_direct_base; |
128 |
| - end = module_direct_base + SZ_128M; |
129 |
| - |
130 |
| - if (module_plt_base) { |
131 |
| - fallback_start = module_plt_base; |
132 |
| - fallback_end = module_plt_base + SZ_2G; |
133 |
| - } |
134 |
| - } else if (module_plt_base) { |
135 |
| - start = module_plt_base; |
136 |
| - end = module_plt_base + SZ_2G; |
137 |
| - } |
138 |
| - |
139 |
| - execmem_info = (struct execmem_info){ |
140 |
| - .ranges = { |
141 |
| - [EXECMEM_DEFAULT] = { |
142 |
| - .start = start, |
143 |
| - .end = end, |
144 |
| - .pgprot = PAGE_KERNEL, |
145 |
| - .alignment = 1, |
146 |
| - .fallback_start = fallback_start, |
147 |
| - .fallback_end = fallback_end, |
148 |
| - }, |
149 |
| - [EXECMEM_KPROBES] = { |
150 |
| - .start = VMALLOC_START, |
151 |
| - .end = VMALLOC_END, |
152 |
| - .pgprot = PAGE_KERNEL_ROX, |
153 |
| - .alignment = 1, |
154 |
| - }, |
155 |
| - [EXECMEM_BPF] = { |
156 |
| - .start = VMALLOC_START, |
157 |
| - .end = VMALLOC_END, |
158 |
| - .pgprot = PAGE_KERNEL, |
159 |
| - .alignment = 1, |
160 |
| - }, |
161 |
| - }, |
162 |
| - }; |
163 |
| - |
164 |
| - return &execmem_info; |
165 |
| -} |
166 |
| - |
167 | 27 | enum aarch64_reloc_op {
|
168 | 28 | RELOC_OP_NONE,
|
169 | 29 | RELOC_OP_ABS,
|
|
0 commit comments