hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/arch/arm64/kernel/kaslr.c
....@@ -1,9 +1,6 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (C) 2016 Linaro Ltd <ard.biesheuvel@linaro.org>
3
- *
4
- * This program is free software; you can redistribute it and/or modify
5
- * it under the terms of the GNU General Public License version 2 as
6
- * published by the Free Software Foundation.
74 */
85
96 #include <linux/cache.h>
....@@ -13,15 +10,25 @@
1310 #include <linux/mm_types.h>
1411 #include <linux/sched.h>
1512 #include <linux/types.h>
13
+#include <linux/pgtable.h>
14
+#include <linux/random.h>
1615
1716 #include <asm/cacheflush.h>
1817 #include <asm/fixmap.h>
1918 #include <asm/kernel-pgtable.h>
2019 #include <asm/memory.h>
2120 #include <asm/mmu.h>
22
-#include <asm/pgtable.h>
2321 #include <asm/sections.h>
22
+#include <asm/setup.h>
2423
24
+enum kaslr_status {
25
+ KASLR_ENABLED,
26
+ KASLR_DISABLED_CMDLINE,
27
+ KASLR_DISABLED_NO_SEED,
28
+ KASLR_DISABLED_FDT_REMAP,
29
+};
30
+
31
+static enum kaslr_status __initdata kaslr_status;
2532 u64 __ro_after_init module_alloc_base;
2633 u16 __initdata memstart_offset_seed;
2734
....@@ -44,26 +51,7 @@
4451 return ret;
4552 }
4653
47
-static __init const u8 *kaslr_get_cmdline(void *fdt)
48
-{
49
- static __initconst const u8 default_cmdline[] = CONFIG_CMDLINE;
50
-
51
- if (!IS_ENABLED(CONFIG_CMDLINE_FORCE)) {
52
- int node;
53
- const u8 *prop;
54
-
55
- node = fdt_path_offset(fdt, "/chosen");
56
- if (node < 0)
57
- goto out;
58
-
59
- prop = fdt_getprop(fdt, node, "bootargs", NULL);
60
- if (!prop)
61
- goto out;
62
- return prop;
63
- }
64
-out:
65
- return default_cmdline;
66
-}
54
+struct arm64_ftr_override kaslr_feature_override __initdata;
6755
6856 /*
6957 * This routine will be executed with the kernel mapped at its default virtual
....@@ -73,12 +61,11 @@
7361 * containing function pointers) to be reinitialized, and zero-initialized
7462 * .bss variables will be reset to 0.
7563 */
76
-u64 __init kaslr_early_init(u64 dt_phys)
64
+u64 __init kaslr_early_init(void)
7765 {
7866 void *fdt;
7967 u64 seed, offset, mask, module_range;
80
- const u8 *cmdline, *str;
81
- int size;
68
+ unsigned long raw;
8269
8370 /*
8471 * Set a reasonable default for module_alloc_base in case
....@@ -92,51 +79,66 @@
9279 * and proceed with KASLR disabled. We will make another
9380 * attempt at mapping the FDT in setup_machine()
9481 */
95
- early_fixmap_init();
96
- fdt = fixmap_remap_fdt(dt_phys, &size, PAGE_KERNEL);
97
- if (!fdt)
82
+ fdt = get_early_fdt_ptr();
83
+ if (!fdt) {
84
+ kaslr_status = KASLR_DISABLED_FDT_REMAP;
9885 return 0;
86
+ }
9987
10088 /*
10189 * Retrieve (and wipe) the seed from the FDT
10290 */
10391 seed = get_kaslr_seed(fdt);
104
- if (!seed)
105
- return 0;
10692
10793 /*
10894 * Check if 'nokaslr' appears on the command line, and
10995 * return 0 if that is the case.
11096 */
111
- cmdline = kaslr_get_cmdline(fdt);
112
- str = strstr(cmdline, "nokaslr");
113
- if (str == cmdline || (str > cmdline && *(str - 1) == ' '))
97
+ if (kaslr_feature_override.val & kaslr_feature_override.mask & 0xf) {
98
+ kaslr_status = KASLR_DISABLED_CMDLINE;
11499 return 0;
100
+ }
101
+
102
+ /*
103
+ * Mix in any entropy obtainable architecturally if enabled
104
+ * and supported.
105
+ */
106
+
107
+ if (arch_get_random_seed_long_early(&raw))
108
+ seed ^= raw;
109
+
110
+ if (!seed) {
111
+ kaslr_status = KASLR_DISABLED_NO_SEED;
112
+ return 0;
113
+ }
115114
116115 /*
117116 * OK, so we are proceeding with KASLR enabled. Calculate a suitable
118117 * kernel image offset from the seed. Let's place the kernel in the
119
- * middle half of the VMALLOC area (VA_BITS - 2), and stay clear of
118
+ * middle half of the VMALLOC area (VA_BITS_MIN - 2), and stay clear of
120119 * the lower and upper quarters to avoid colliding with other
121120 * allocations.
122121 * Even if we could randomize at page granularity for 16k and 64k pages,
123122 * let's always round to 2 MB so we don't interfere with the ability to
124123 * map using contiguous PTEs
125124 */
126
- mask = ((1UL << (VA_BITS - 2)) - 1) & ~(SZ_2M - 1);
127
- offset = BIT(VA_BITS - 3) + (seed & mask);
125
+ mask = ((1UL << (VA_BITS_MIN - 2)) - 1) & ~(SZ_2M - 1);
126
+ offset = BIT(VA_BITS_MIN - 3) + (seed & mask);
128127
129128 /* use the top 16 bits to randomize the linear region */
130129 memstart_offset_seed = seed >> 48;
131130
132
- if (IS_ENABLED(CONFIG_KASAN))
131
+ if (!IS_ENABLED(CONFIG_KASAN_VMALLOC) &&
132
+ (IS_ENABLED(CONFIG_KASAN_GENERIC) ||
133
+ IS_ENABLED(CONFIG_KASAN_SW_TAGS)))
133134 /*
134
- * KASAN does not expect the module region to intersect the
135
- * vmalloc region, since shadow memory is allocated for each
136
- * module at load time, whereas the vmalloc region is shadowed
137
- * by KASAN zero pages. So keep modules out of the vmalloc
138
- * region if KASAN is enabled, and put the kernel well within
139
- * 4 GB of the module region.
135
+ * KASAN without KASAN_VMALLOC does not expect the module region
136
+ * to intersect the vmalloc region, since shadow memory is
137
+ * allocated for each module at load time, whereas the vmalloc
138
+ * region is shadowed by KASAN zero pages. So keep modules
139
+ * out of the vmalloc region if KASAN is enabled without
140
+ * KASAN_VMALLOC, and put the kernel well within 4 GB of the
141
+ * module region.
140142 */
141143 return offset % SZ_2G;
142144
....@@ -173,3 +175,24 @@
173175
174176 return offset;
175177 }
178
+
179
+static int __init kaslr_init(void)
180
+{
181
+ switch (kaslr_status) {
182
+ case KASLR_ENABLED:
183
+ pr_info("KASLR enabled\n");
184
+ break;
185
+ case KASLR_DISABLED_CMDLINE:
186
+ pr_info("KASLR disabled on command line\n");
187
+ break;
188
+ case KASLR_DISABLED_NO_SEED:
189
+ pr_warn("KASLR disabled due to lack of seed\n");
190
+ break;
191
+ case KASLR_DISABLED_FDT_REMAP:
192
+ pr_warn("KASLR disabled due to FDT remapping failure\n");
193
+ break;
194
+ }
195
+
196
+ return 0;
197
+}
198
+core_initcall(kaslr_init)