From: Prakhar Srivastava <prsriva@linux.microsoft.com>
To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org
Cc: mark.rutland@arm.com, jean-philippe@linaro.org, arnd@arndb.de,
takahiro.akashi@linaro.org, sboyd@kernel.org,
catalin.marinas@arm.com, zohar@linux.ibm.com,
yamada.masahiro@socionext.com, kristina.martsenko@arm.org,
duwe@lst.de, bauerman@linux.ibm.com, james.morse@arm.org,
tglx@linutronix.de, allison@lohutok.net
Subject: [RFC PATCH v1 1/1] Add support for arm64 to carry ima measurement log in kexec_file_load
Date: Mon, 9 Sep 2019 16:14:09 -0700 [thread overview]
Message-ID: <20190909231409.20461-2-prsriva@linux.microsoft.com> (raw)
In-Reply-To: <20190909231409.20461-1-prsriva@linux.microsoft.com>
During kexec_file_load, carrying forward the ima measurement log allows
a verifying party to get the entire runtime event log since the last
full reboot since that is when PCRs were last reset.
Signed-off-by: Prakhar Srivastava <prsriva@linux.microsoft.com>
---
arch/arm64/Kconfig | 7 +
arch/arm64/include/asm/ima.h | 29 ++++
arch/arm64/include/asm/kexec.h | 5 +
arch/arm64/kernel/Makefile | 3 +-
arch/arm64/kernel/ima_kexec.c | 213 +++++++++++++++++++++++++
arch/arm64/kernel/machine_kexec_file.c | 6 +
6 files changed, 262 insertions(+), 1 deletion(-)
create mode 100644 arch/arm64/include/asm/ima.h
create mode 100644 arch/arm64/kernel/ima_kexec.c
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 3adcec05b1f6..f39b12dbf9e8 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -976,6 +976,13 @@ config KEXEC_VERIFY_SIG
verification for the corresponding kernel image type being
loaded in order for this to work.
+config HAVE_IMA_KEXEC
+ bool "Carry over IMA measurement log during kexec_file_load() syscall"
+ depends on KEXEC_FILE
+ help
+ Select this option to carry over IMA measurement log during
+ kexec_file_load.
+
config KEXEC_IMAGE_VERIFY_SIG
bool "Enable Image signature verification support"
default y
diff --git a/arch/arm64/include/asm/ima.h b/arch/arm64/include/asm/ima.h
new file mode 100644
index 000000000000..e23cee84729f
--- /dev/null
+++ b/arch/arm64/include/asm/ima.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_ARM64_IMA_H
+#define _ASM_ARM64_IMA_H
+
+struct kimage;
+
+int ima_get_kexec_buffer(void **addr, size_t *size);
+int ima_free_kexec_buffer(void);
+
+#ifdef CONFIG_IMA
+void remove_ima_buffer(void *fdt, int chosen_node);
+#else
+static inline void remove_ima_buffer(void *fdt, int chosen_node) {}
+#endif
+
+#ifdef CONFIG_IMA_KEXEC
+int arch_ima_add_kexec_buffer(struct kimage *image, unsigned long load_addr,
+ size_t size);
+
+int setup_ima_buffer(const struct kimage *image, void *fdt, int chosen_node);
+#else
+static inline int setup_ima_buffer(const struct kimage *image, void *fdt,
+ int chosen_node)
+{
+ remove_ima_buffer(fdt, chosen_node);
+ return 0;
+}
+#endif /* CONFIG_IMA_KEXEC */
+#endif /* _ASM_ARM64_IMA_H */
diff --git a/arch/arm64/include/asm/kexec.h b/arch/arm64/include/asm/kexec.h
index 12a561a54128..e8d2412066e7 100644
--- a/arch/arm64/include/asm/kexec.h
+++ b/arch/arm64/include/asm/kexec.h
@@ -96,6 +96,11 @@ static inline void crash_post_resume(void) {}
struct kimage_arch {
void *dtb;
unsigned long dtb_mem;
+
+#ifdef CONFIG_IMA_KEXEC
+ phys_addr_t ima_buffer_addr;
+ size_t ima_buffer_size;
+#endif
};
extern const struct kexec_file_ops kexec_image_ops;
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 478491f07b4f..580238f2e9a7 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -55,7 +55,8 @@ obj-$(CONFIG_RANDOMIZE_BASE) += kaslr.o
obj-$(CONFIG_HIBERNATION) += hibernate.o hibernate-asm.o
obj-$(CONFIG_KEXEC_CORE) += machine_kexec.o relocate_kernel.o \
cpu-reset.o
-obj-$(CONFIG_KEXEC_FILE) += machine_kexec_file.o kexec_image.o
+obj-$(CONFIG_KEXEC_FILE) += machine_kexec_file.o kexec_image.o \
+ ima_kexec.o
obj-$(CONFIG_ARM64_RELOC_TEST) += arm64-reloc-test.o
arm64-reloc-test-y := reloc_test_core.o reloc_test_syms.o
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
diff --git a/arch/arm64/kernel/ima_kexec.c b/arch/arm64/kernel/ima_kexec.c
new file mode 100644
index 000000000000..b14326d541f3
--- /dev/null
+++ b/arch/arm64/kernel/ima_kexec.c
@@ -0,0 +1,213 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Authors:
+ * Prakhar Srivastava <prsriva@linux.microsoft.com>
+ */
+
+#include <linux/slab.h>
+#include <linux/kexec.h>
+#include <linux/of.h>
+#include <linux/memblock.h>
+#include <linux/libfdt.h>
+
+
+/**
+ * delete_fdt_mem_rsv - delete memory reservation with given address and size
+ * @fdt - pointer to the fdt.
+ * @start - start address of the memory.
+ * @size - number of cells to be deletd.
+ *
+ * Return: 0 on success, or negative errno on error.
+ */
+int delete_fdt_mem_rsv(void *fdt, unsigned long start, unsigned long size)
+{
+ int i, ret, num_rsvs = fdt_num_mem_rsv(fdt);
+
+ for (i = 0; i < num_rsvs; i++) {
+ uint64_t rsv_start, rsv_size;
+
+ ret = fdt_get_mem_rsv(fdt, i, &rsv_start, &rsv_size);
+ if (ret) {
+ pr_err("Malformed device tree\n");
+ return -EINVAL;
+ }
+
+ if (rsv_start == start && rsv_size == size) {
+ ret = fdt_del_mem_rsv(fdt, i);
+ if (ret) {
+ pr_err("Error deleting device tree reservation\n");
+ return -EINVAL;
+ }
+
+ return 0;
+ }
+ }
+
+ return -ENOENT;
+}
+
+/**
+ * remove_ima_buffer - remove the IMA buffer property and reservation
+ * @fdt - pointer the fdt.
+ * @chosen_node - node under which property can be found.
+ *
+ * The IMA measurement buffer is either read by now and freeed or a kexec call
+ * needs to replace the ima measurement buffer, clear the property and memory
+ * reservation.
+ */
+void remove_ima_buffer(void *fdt, int chosen_node)
+{
+ int ret, len;
+ const void *prop;
+ uint64_t tmp_start, tmp_end;
+
+ prop = fdt_getprop(fdt, chosen_node, "linux,ima-kexec-buffer", &len);
+ if (prop) {
+ tmp_start = fdt64_to_cpu(*((const fdt64_t *) prop));
+
+ prop = fdt_getprop(fdt, chosen_node,
+ "linux,ima-kexec-buffer-end", &len);
+ if (!prop)
+ return;
+
+ tmp_end = fdt64_to_cpu(*((const fdt64_t *) prop));
+
+ ret = delete_fdt_mem_rsv(fdt, tmp_start, tmp_end - tmp_start);
+
+ if (ret == 0)
+ pr_debug("Removed old IMA buffer reservation.\n");
+ else if (ret != -ENOENT)
+ return;
+
+ fdt_delprop(fdt, chosen_node, "linux,ima-kexec-buffer");
+ fdt_delprop(fdt, chosen_node, "linux,ima-kexec-buffer-end");
+ }
+}
+
+/**
+ * ima_get_kexec_buffer - get IMA buffer from the previous kernel
+ * @addr: On successful return, set to point to the buffer contents.
+ * @size: On successful return, set to the buffer size.
+ *
+ * Return: 0 on success, negative errno on error.
+ */
+int ima_get_kexec_buffer(void **addr, size_t *size)
+{
+ int len;
+ const void *prop;
+ uint64_t tmp_start, tmp_end;
+
+ prop = of_get_property(of_chosen, "linux,ima-kexec-buffer", &len);
+ if (!prop)
+ return -ENOENT;
+
+ tmp_start = fdt64_to_cpu(*((const fdt64_t *) prop));
+
+ prop = of_get_property(of_chosen, "linux,ima-kexec-buffer-end", &len);
+ if (!prop)
+ return -ENOENT;
+
+ tmp_end = fdt64_to_cpu(*((const fdt64_t *) prop));
+
+ *addr = __va(tmp_start);
+ *size = tmp_end - tmp_start;
+
+ return 0;
+}
+
+/**
+ * ima_free_kexec_buffer - free memory used by the IMA buffer
+ *
+ * Return: 0 on success, negative errno on error.
+ */
+int ima_free_kexec_buffer(void)
+{
+ int ret;
+ void *propStart, *propEnd;
+ uint64_t tmp_start, tmp_end;
+
+ propStart = of_find_property(of_chosen, "linux,ima-kexec-buffer",
+ NULL);
+ if (propStart) {
+ tmp_start = fdt64_to_cpu(*((const fdt64_t *) propStart));
+ ret = of_remove_property(of_chosen, propStart);
+ if (!ret) {
+ return ret;
+ }
+
+ propEnd = of_find_property(of_chosen,
+ "linux,ima-kexec-buffer-end", NULL);
+ if (!propEnd) {
+ return -EINVAL;
+ }
+
+ tmp_end = fdt64_to_cpu(*((const fdt64_t *) propEnd));
+
+ ret = of_remove_property(of_chosen, propEnd);
+ if (!ret) {
+ return ret;
+ }
+
+ return memblock_free(tmp_start, tmp_end - tmp_start);
+ }
+ return 0;
+}
+
+#ifdef CONFIG_IMA_KEXEC
+/**
+ * arch_ima_add_kexec_buffer - do arch-specific steps to add the IMA
+ * measurement log.
+ * @image: - pointer to the kimage, to store the address and size of the
+ * IMA measurement log.
+ * @load_addr: - the address where the IMA measurement log is stored.
+ * @size - size of the IMA measurement log.
+ *
+ * Return: 0 on success, negative errno on error.
+ */
+int arch_ima_add_kexec_buffer(struct kimage *image, unsigned long load_addr,
+ size_t size)
+{
+ image->arch.ima_buffer_addr = load_addr;
+ image->arch.ima_buffer_size = size;
+ return 0;
+}
+
+/**
+ * setup_ima_buffer - update the fdt to contain the ima mesasurement log
+ * @image: - pointer to the kimage, containing the address and size of
+ * the IMA measurement log.
+ * @fdt: - pointer to the fdt.
+ * @chosen_node: - node under which property is to be defined.
+ *
+ * Return: 0 on success, negative errno on error.
+ */
+int setup_ima_buffer(const struct kimage *image, void *fdt, int chosen_node)
+{
+ int ret;
+
+ remove_ima_buffer(fdt, chosen_node);
+
+ if (!image->arch.ima_buffer_size)
+ return 0;
+
+ ret = fdt_setprop_u64(fdt, chosen_node, "linux,ima-kexec-buffer",
+ image->arch.ima_buffer_addr);
+ if (ret < 0)
+ return ret;
+
+ ret = fdt_setprop_u64(fdt, chosen_node, "linux,ima-kexec-buffer-end",
+ image->arch.ima_buffer_addr +
+ image->arch.ima_buffer_size);
+ if (ret < 0)
+ return ret;
+
+ ret = fdt_add_mem_rsv(fdt, image->arch.ima_buffer_addr,
+ image->arch.ima_buffer_size);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+#endif /* CONFIG_IMA_KEXEC */
diff --git a/arch/arm64/kernel/machine_kexec_file.c b/arch/arm64/kernel/machine_kexec_file.c
index 58871333737a..de5452539c67 100644
--- a/arch/arm64/kernel/machine_kexec_file.c
+++ b/arch/arm64/kernel/machine_kexec_file.c
@@ -21,6 +21,7 @@
#include <linux/types.h>
#include <linux/vmalloc.h>
#include <asm/byteorder.h>
+#include <asm/ima.h>
/* relevant device tree properties */
#define FDT_PROP_INITRD_START "linux,initrd-start"
@@ -85,6 +86,11 @@ static int setup_dtb(struct kimage *image,
goto out;
}
+ /* add ima measuremnet log buffer */
+ ret = setup_ima_buffer(image, dtb, off);
+ if (ret)
+ goto out;
+
/* add kaslr-seed */
ret = fdt_delprop(dtb, off, FDT_PROP_KASLR_SEED);
if (ret == -FDT_ERR_NOTFOUND)
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2019-09-09 23:14 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-09-09 23:14 [RFC PATCH v1 0/1] Add support for arm64 to carry ima measurement log in kexec_file_load Prakhar Srivastava
2019-09-09 23:14 ` Prakhar Srivastava [this message]
-- strict thread matches above, loose matches on Subject: below --
2019-09-13 22:50 Prakhar Srivastava
2019-09-13 22:50 ` [RFC PATCH v1 1/1] " Prakhar Srivastava
2019-09-18 14:15 ` Mimi Zohar
2019-09-18 21:21 ` Mimi Zohar
2019-09-19 3:59 ` Thiago Jung Bauermann
2019-09-20 0:32 ` Prakhar Srivastava
2019-09-20 3:07 ` Thiago Jung Bauermann
2019-09-24 19:54 ` prsriva
2019-09-24 20:25 ` Thiago Jung Bauermann
2019-09-24 20:27 ` prsriva
2019-09-06 23:51 [RFC][PATCH v1 0/1] " Prakhar Srivastava
2019-09-06 23:51 ` [RFC][PATCH v1 1/1] " Prakhar Srivastava
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190909231409.20461-2-prsriva@linux.microsoft.com \
--to=prsriva@linux.microsoft.com \
--cc=allison@lohutok.net \
--cc=arnd@arndb.de \
--cc=bauerman@linux.ibm.com \
--cc=catalin.marinas@arm.com \
--cc=duwe@lst.de \
--cc=james.morse@arm.org \
--cc=jean-philippe@linaro.org \
--cc=kristina.martsenko@arm.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=sboyd@kernel.org \
--cc=takahiro.akashi@linaro.org \
--cc=tglx@linutronix.de \
--cc=yamada.masahiro@socionext.com \
--cc=zohar@linux.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).