summaryrefslogtreecommitdiff
path: root/arch/arm64/kernel/pi/kaslr_early.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm64/kernel/pi/kaslr_early.c')
-rw-r--r--arch/arm64/kernel/pi/kaslr_early.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/arch/arm64/kernel/pi/kaslr_early.c b/arch/arm64/kernel/pi/kaslr_early.c
new file mode 100644
index 000000000000..e0e018046a46
--- /dev/null
+++ b/arch/arm64/kernel/pi/kaslr_early.c
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright 2022 Google LLC
+// Author: Ard Biesheuvel <ardb@google.com>
+
+// NOTE: code in this file runs *very* early, and is not permitted to use
+// global variables or anything that relies on absolute addressing.
+
+#include <linux/libfdt.h>
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <linux/types.h>
+#include <linux/sizes.h>
+#include <linux/string.h>
+
+#include <asm/archrandom.h>
+#include <asm/memory.h>
+#include <asm/pgtable.h>
+
+#include "pi.h"
+
+static u64 __init get_kaslr_seed(void *fdt, int node)
+{
+ static char const seed_str[] __initconst = "kaslr-seed";
+ fdt64_t *prop;
+ u64 ret;
+ int len;
+
+ if (node < 0)
+ return 0;
+
+ prop = fdt_getprop_w(fdt, node, seed_str, &len);
+ if (!prop || len != sizeof(u64))
+ return 0;
+
+ ret = fdt64_to_cpu(*prop);
+ *prop = 0;
+ return ret;
+}
+
+u64 __init kaslr_early_init(void *fdt, int chosen)
+{
+ u64 seed, range;
+
+ if (kaslr_disabled_cmdline())
+ return 0;
+
+ seed = get_kaslr_seed(fdt, chosen);
+ if (!seed) {
+ if (!__early_cpu_has_rndr() ||
+ !__arm64_rndr((unsigned long *)&seed))
+ return 0;
+ }
+
+ /*
+ * OK, so we are proceeding with KASLR enabled. Calculate a suitable
+ * kernel image offset from the seed. Let's place the kernel in the
+ * 'middle' half of the VMALLOC area, and stay clear of the lower and
+ * upper quarters to avoid colliding with other allocations.
+ */
+ range = (VMALLOC_END - KIMAGE_VADDR) / 2;
+ return range / 2 + (((__uint128_t)range * seed) >> 64);
+}