1
2
3
4
5#include <linux/kernel.h>
6#include <linux/errno.h>
7#include <linux/string.h>
8#include <linux/types.h>
9#include <linux/mm.h>
10#include <linux/swap.h>
11#include <linux/stddef.h>
12#include <linux/init.h>
13#include <linux/delay.h>
14#include <linux/memblock.h>
15#include <linux/libfdt.h>
16#include <linux/crash_core.h>
17#include <asm/cacheflush.h>
18#include <asm/prom.h>
19#include <asm/kdump.h>
20#include <mm/mmu_decl.h>
21#include <generated/compile.h>
22#include <generated/utsrelease.h>
23
24struct regions {
25 unsigned long pa_start;
26 unsigned long pa_end;
27 unsigned long kernel_size;
28 unsigned long dtb_start;
29 unsigned long dtb_end;
30 unsigned long initrd_start;
31 unsigned long initrd_end;
32 unsigned long crash_start;
33 unsigned long crash_end;
34 int reserved_mem;
35 int reserved_mem_addr_cells;
36 int reserved_mem_size_cells;
37};
38
39
40static const char build_str[] = UTS_RELEASE " (" LINUX_COMPILE_BY "@"
41 LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION;
42
43struct regions __initdata regions;
44
45static __init void kaslr_get_cmdline(void *fdt)
46{
47 early_init_dt_scan_chosen(boot_command_line);
48}
49
50static unsigned long __init rotate_xor(unsigned long hash, const void *area,
51 size_t size)
52{
53 size_t i;
54 const unsigned long *ptr = area;
55
56 for (i = 0; i < size / sizeof(hash); i++) {
57
58 hash = (hash << ((sizeof(hash) * 8) - 7)) | (hash >> 7);
59 hash ^= ptr[i];
60 }
61
62 return hash;
63}
64
65
66
67
68
69static unsigned long __init get_boot_seed(void *fdt)
70{
71 unsigned long hash = 0;
72
73 hash = rotate_xor(hash, build_str, sizeof(build_str));
74 hash = rotate_xor(hash, fdt, fdt_totalsize(fdt));
75
76 return hash;
77}
78
79static __init u64 get_kaslr_seed(void *fdt)
80{
81 int node, len;
82 fdt64_t *prop;
83 u64 ret;
84
85 node = fdt_path_offset(fdt, "/chosen");
86 if (node < 0)
87 return 0;
88
89 prop = fdt_getprop_w(fdt, node, "kaslr-seed", &len);
90 if (!prop || len != sizeof(u64))
91 return 0;
92
93 ret = fdt64_to_cpu(*prop);
94 *prop = 0;
95 return ret;
96}
97
98static __init bool regions_overlap(u32 s1, u32 e1, u32 s2, u32 e2)
99{
100 return e1 >= s2 && e2 >= s1;
101}
102
103static __init bool overlaps_reserved_region(const void *fdt, u32 start,
104 u32 end)
105{
106 int subnode, len, i;
107 u64 base, size;
108
109
110 for (i = 0; i < fdt_num_mem_rsv(fdt); i++) {
111 if (fdt_get_mem_rsv(fdt, i, &base, &size) < 0)
112 continue;
113 if (regions_overlap(start, end, base, base + size))
114 return true;
115 }
116
117 if (regions.reserved_mem < 0)
118 return false;
119
120
121 for (subnode = fdt_first_subnode(fdt, regions.reserved_mem);
122 subnode >= 0;
123 subnode = fdt_next_subnode(fdt, subnode)) {
124 const fdt32_t *reg;
125 u64 rsv_end;
126
127 len = 0;
128 reg = fdt_getprop(fdt, subnode, "reg", &len);
129 while (len >= (regions.reserved_mem_addr_cells +
130 regions.reserved_mem_size_cells)) {
131 base = fdt32_to_cpu(reg[0]);
132 if (regions.reserved_mem_addr_cells == 2)
133 base = (base << 32) | fdt32_to_cpu(reg[1]);
134
135 reg += regions.reserved_mem_addr_cells;
136 len -= 4 * regions.reserved_mem_addr_cells;
137
138 size = fdt32_to_cpu(reg[0]);
139 if (regions.reserved_mem_size_cells == 2)
140 size = (size << 32) | fdt32_to_cpu(reg[1]);
141
142 reg += regions.reserved_mem_size_cells;
143 len -= 4 * regions.reserved_mem_size_cells;
144
145 if (base >= regions.pa_end)
146 continue;
147
148 rsv_end = min(base + size, (u64)U32_MAX);
149
150 if (regions_overlap(start, end, base, rsv_end))
151 return true;
152 }
153 }
154 return false;
155}
156
157static __init bool overlaps_region(const void *fdt, u32 start,
158 u32 end)
159{
160 if (regions_overlap(start, end, __pa(_stext), __pa(_end)))
161 return true;
162
163 if (regions_overlap(start, end, regions.dtb_start,
164 regions.dtb_end))
165 return true;
166
167 if (regions_overlap(start, end, regions.initrd_start,
168 regions.initrd_end))
169 return true;
170
171 if (regions_overlap(start, end, regions.crash_start,
172 regions.crash_end))
173 return true;
174
175 return overlaps_reserved_region(fdt, start, end);
176}
177
178static void __init get_crash_kernel(void *fdt, unsigned long size)
179{
180#ifdef CONFIG_CRASH_CORE
181 unsigned long long crash_size, crash_base;
182 int ret;
183
184 ret = parse_crashkernel(boot_command_line, size, &crash_size,
185 &crash_base);
186 if (ret != 0 || crash_size == 0)
187 return;
188 if (crash_base == 0)
189 crash_base = KDUMP_KERNELBASE;
190
191 regions.crash_start = (unsigned long)crash_base;
192 regions.crash_end = (unsigned long)(crash_base + crash_size);
193
194 pr_debug("crash_base=0x%llx crash_size=0x%llx\n", crash_base, crash_size);
195#endif
196}
197
198static void __init get_initrd_range(void *fdt)
199{
200 u64 start, end;
201 int node, len;
202 const __be32 *prop;
203
204 node = fdt_path_offset(fdt, "/chosen");
205 if (node < 0)
206 return;
207
208 prop = fdt_getprop(fdt, node, "linux,initrd-start", &len);
209 if (!prop)
210 return;
211 start = of_read_number(prop, len / 4);
212
213 prop = fdt_getprop(fdt, node, "linux,initrd-end", &len);
214 if (!prop)
215 return;
216 end = of_read_number(prop, len / 4);
217
218 regions.initrd_start = (unsigned long)start;
219 regions.initrd_end = (unsigned long)end;
220
221 pr_debug("initrd_start=0x%llx initrd_end=0x%llx\n", start, end);
222}
223
224static __init unsigned long get_usable_address(const void *fdt,
225 unsigned long start,
226 unsigned long offset)
227{
228 unsigned long pa;
229 unsigned long pa_end;
230
231 for (pa = offset; (long)pa > (long)start; pa -= SZ_16K) {
232 pa_end = pa + regions.kernel_size;
233 if (overlaps_region(fdt, pa, pa_end))
234 continue;
235
236 return pa;
237 }
238 return 0;
239}
240
241static __init void get_cell_sizes(const void *fdt, int node, int *addr_cells,
242 int *size_cells)
243{
244 const int *prop;
245 int len;
246
247
248
249
250
251 *addr_cells = *size_cells = 1;
252
253 prop = fdt_getprop(fdt, node, "#address-cells", &len);
254 if (len == 4)
255 *addr_cells = fdt32_to_cpu(*prop);
256 prop = fdt_getprop(fdt, node, "#size-cells", &len);
257 if (len == 4)
258 *size_cells = fdt32_to_cpu(*prop);
259}
260
261static unsigned long __init kaslr_legal_offset(void *dt_ptr, unsigned long index,
262 unsigned long offset)
263{
264 unsigned long koffset = 0;
265 unsigned long start;
266
267 while ((long)index >= 0) {
268 offset = memstart_addr + index * SZ_64M + offset;
269 start = memstart_addr + index * SZ_64M;
270 koffset = get_usable_address(dt_ptr, start, offset);
271 if (koffset)
272 break;
273 index--;
274 }
275
276 if (koffset != 0)
277 koffset -= memstart_addr;
278
279 return koffset;
280}
281
282static inline __init bool kaslr_disabled(void)
283{
284 return strstr(boot_command_line, "nokaslr") != NULL;
285}
286
287static unsigned long __init kaslr_choose_location(void *dt_ptr, phys_addr_t size,
288 unsigned long kernel_sz)
289{
290 unsigned long offset, random;
291 unsigned long ram, linear_sz;
292 u64 seed;
293 unsigned long index;
294
295 kaslr_get_cmdline(dt_ptr);
296 if (kaslr_disabled())
297 return 0;
298
299 random = get_boot_seed(dt_ptr);
300
301 seed = get_tb() << 32;
302 seed ^= get_tb();
303 random = rotate_xor(random, &seed, sizeof(seed));
304
305
306
307
308 seed = get_kaslr_seed(dt_ptr);
309 if (seed)
310 random = rotate_xor(random, &seed, sizeof(seed));
311 else
312 pr_warn("KASLR: No safe seed for randomizing the kernel base.\n");
313
314 ram = min_t(phys_addr_t, __max_low_memory, size);
315 ram = map_mem_in_cams(ram, CONFIG_LOWMEM_CAM_NUM, true, true);
316 linear_sz = min_t(unsigned long, ram, SZ_512M);
317
318
319 if (linear_sz < SZ_64M)
320 return 0;
321
322
323 regions.reserved_mem = fdt_path_offset(dt_ptr, "/reserved-memory");
324 if (regions.reserved_mem >= 0)
325 get_cell_sizes(dt_ptr, regions.reserved_mem,
326 ®ions.reserved_mem_addr_cells,
327 ®ions.reserved_mem_size_cells);
328
329 regions.pa_start = memstart_addr;
330 regions.pa_end = memstart_addr + linear_sz;
331 regions.dtb_start = __pa(dt_ptr);
332 regions.dtb_end = __pa(dt_ptr) + fdt_totalsize(dt_ptr);
333 regions.kernel_size = kernel_sz;
334
335 get_initrd_range(dt_ptr);
336 get_crash_kernel(dt_ptr, ram);
337
338
339
340
341
342 index = random & 0xFF;
343 index %= linear_sz / SZ_64M;
344
345
346 offset = random % (SZ_64M - kernel_sz);
347 offset = round_down(offset, SZ_16K);
348
349 return kaslr_legal_offset(dt_ptr, index, offset);
350}
351
352
353
354
355
356
357notrace void __init kaslr_early_init(void *dt_ptr, phys_addr_t size)
358{
359 unsigned long tlb_virt;
360 phys_addr_t tlb_phys;
361 unsigned long offset;
362 unsigned long kernel_sz;
363
364 kernel_sz = (unsigned long)_end - (unsigned long)_stext;
365
366 offset = kaslr_choose_location(dt_ptr, size, kernel_sz);
367 if (offset == 0)
368 return;
369
370 kernstart_virt_addr += offset;
371 kernstart_addr += offset;
372
373 is_second_reloc = 1;
374
375 if (offset >= SZ_64M) {
376 tlb_virt = round_down(kernstart_virt_addr, SZ_64M);
377 tlb_phys = round_down(kernstart_addr, SZ_64M);
378
379
380 create_kaslr_tlb_entry(1, tlb_virt, tlb_phys);
381 }
382
383
384 memcpy((void *)kernstart_virt_addr, (void *)_stext, kernel_sz);
385 flush_icache_range(kernstart_virt_addr, kernstart_virt_addr + kernel_sz);
386
387 reloc_kernel_entry(dt_ptr, kernstart_virt_addr);
388}
389
390void __init kaslr_late_init(void)
391{
392
393 if (kernstart_virt_addr != KERNELBASE) {
394 unsigned long kernel_sz;
395
396 kernel_sz = (unsigned long)_end - kernstart_virt_addr;
397 memzero_explicit((void *)KERNELBASE, kernel_sz);
398 }
399}
400