* [PATCH v3 1/2] Add support for arm64 to carry ima measurement log in kexec_file_load
2019-10-10 0:12 [PATCH v3 0/2] Add support for arm64 to carry ima measurement log in kexec_file_load Prakhar Srivastava
@ 2019-10-10 0:12 ` Prakhar Srivastava
2019-10-10 0:12 ` [PATCH v3 2/2] update powerpc implementation to call into of_ima* Prakhar Srivastava
1 sibling, 0 replies; 3+ messages in thread
From: Prakhar Srivastava @ 2019-10-10 0:12 UTC (permalink / raw)
To: linux-kernel, linux-arm-kernel, linux-integrity, kexec
Cc: arnd, jean-philippe, allison, kristina.martsenko,
yamada.masahiro, duwe, mark.rutland, tglx, takahiro.akashi,
james.morse, catalin.marinas, sboyd, bauerman, zohar
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 | 24 +++
arch/arm64/include/asm/kexec.h | 5 +
arch/arm64/kernel/Makefile | 3 +-
arch/arm64/kernel/ima_kexec.c | 78 ++++++++++
arch/arm64/kernel/machine_kexec_file.c | 6 +
arch/powerpc/Kconfig | 6 +
drivers/of/Kconfig | 6 +
drivers/of/Makefile | 1 +
drivers/of/of_ima.c | 204 +++++++++++++++++++++++++
include/linux/of.h | 31 ++++
11 files changed, 370 insertions(+), 1 deletion(-)
create mode 100644 arch/arm64/include/asm/ima.h
create mode 100644 arch/arm64/kernel/ima_kexec.c
create mode 100644 drivers/of/of_ima.c
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 3adcec05b1f6..017eb73b9c69 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -988,6 +988,13 @@ comment "Support for PE file signature verification disabled"
depends on KEXEC_VERIFY_SIG
depends on !EFI || !SIGNED_PE_FILE_VERIFICATION
+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 CRASH_DUMP
bool "Build kdump crash kernel"
help
diff --git a/arch/arm64/include/asm/ima.h b/arch/arm64/include/asm/ima.h
new file mode 100644
index 000000000000..287dbcefd15e
--- /dev/null
+++ b/arch/arm64/include/asm/ima.h
@@ -0,0 +1,24 @@
+/* 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);
+void remove_ima_buffer(void *fdt, int chosen_node);
+
+#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..c2450aaa42c8
--- /dev/null
+++ b/arch/arm64/kernel/ima_kexec.c
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Authors:
+ * Prakhar Srivastava <prsriva@linux.microsoft.com>
+ */
+
+#include <linux/kexec.h>
+#include <linux/of.h>
+
+/**
+ * remove_ima_buffer - remove the IMA buffer property and reservation from @fdt
+ * The IMA measurement buffer once read needs to be freed.
+ */
+void remove_ima_buffer(void *fdt, int chosen_node)
+{
+ fdt_remove_ima_buffer(fdt, chosen_node);
+}
+
+/**
+ * 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)
+{
+ return of_get_ima_buffer(addr, size);
+}
+
+/**
+ * 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)
+{
+ return of_remove_ima_buffer();
+}
+
+#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)
+{
+ return fdt_setup_ima_buffer(image->arch.ima_buffer_addr,
+ image->arch.ima_buffer_size,
+ fdt, chosen_node);
+
+}
+#endif /* CONFIG_IMA_KEXEC */
diff --git a/arch/arm64/kernel/machine_kexec_file.c b/arch/arm64/kernel/machine_kexec_file.c
index 58871333737a..86d57198d739 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 < 0)
+ goto out;
+
/* add kaslr-seed */
ret = fdt_delprop(dtb, off, FDT_PROP_KASLR_SEED);
if (ret == -FDT_ERR_NOTFOUND)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index d8dcd8820369..961dd4e220a2 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -506,6 +506,12 @@ config KEXEC
interface is strongly in flux, so no good recommendation can be
made.
+config HAVE_IMA_KEXEC
+ bool "Carry over IMA measurement log during kexec_file_load() syscall"
+ help
+ Select this option to carry over IMA measurement log during
+ kexec_file_load.
+
config KEXEC_FILE
bool "kexec file based system call"
select KEXEC_CORE
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index 37c2ccbefecd..167c6ecb64aa 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -103,4 +103,10 @@ config OF_OVERLAY
config OF_NUMA
bool
+config OF_IMA
+ def_bool y
+ help
+ IMA related wrapper functions to add/remove ima measurement logs during
+ kexec_file_load call.
+
endif # OF
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index 663a4af0cccd..b4caf083df4e 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -14,5 +14,6 @@ obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o
obj-$(CONFIG_OF_RESOLVE) += resolver.o
obj-$(CONFIG_OF_OVERLAY) += overlay.o
obj-$(CONFIG_OF_NUMA) += of_numa.o
+obj-$(CONFIG_OF_IMA) += of_ima.o
obj-$(CONFIG_OF_UNITTEST) += unittest-data/
diff --git a/drivers/of/of_ima.c b/drivers/of/of_ima.c
new file mode 100644
index 000000000000..cfc3cb4522b0
--- /dev/null
+++ b/drivers/of/of_ima.c
@@ -0,0 +1,204 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ */
+
+#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 fdt_delete_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 < 0) {
+ pr_err("Malformed device tree\n");
+ return ret;
+ }
+
+ if (rsv_start == start && rsv_size == size) {
+ ret = fdt_del_mem_rsv(fdt, i);
+ if (ret < 0) {
+ pr_err("Error deleting device tree reservation\n");
+ return ret;
+ }
+
+ return 0;
+ }
+ }
+
+ return -ENOENT;
+}
+
+/**
+ * of_get_ima_buffer_properties - get the properties for ima buffer
+ * @ima_buf_start - start of the ima buffer
+ * @ima_buf_end - end of the ima buffer
+ * If any one of the properties is not found. The device tree
+ * is malformed or something went wrong.
+ *
+ * Return: 0 on success, negative errno on error.
+ */
+int of_get_ima_buffer_properties(void **ima_buf_start, void **ima_buf_end)
+{
+ struct property *pproperty;
+
+ pproperty = of_find_property(of_chosen, "linux,ima-kexec-buffer",
+ NULL);
+ *ima_buf_start = pproperty ? pproperty->value : NULL;
+
+ pproperty = of_find_property(of_chosen, "linux,ima-kexec-buffer-end",
+ NULL);
+ *ima_buf_end = pproperty ? pproperty->value : NULL;
+
+ if (!*ima_buf_start || !*ima_buf_end)
+ return -EINVAL;
+
+ return 0;
+}
+
+/**
+ * of_remove_ima_buffer - free memory used by the IMA buffer
+ *
+ * Return: 0 on success, negative errno on error.
+ */
+int of_remove_ima_buffer(void)
+{
+ int ret;
+ void *ima_buf_start, *ima_buf_end;
+ uint64_t buf_start, buf_end;
+
+ ret = of_get_ima_buffer_properties(&ima_buf_start, &ima_buf_end);
+ if (ret < 0)
+ return ret;
+
+ buf_start = fdt64_to_cpu(*((const fdt64_t *) ima_buf_start));
+ buf_end = fdt64_to_cpu(*((const fdt64_t *) ima_buf_end));
+
+ ret = of_remove_property(of_chosen, ima_buf_start);
+ if (ret < 0)
+ return ret;
+
+ ret = of_remove_property(of_chosen, ima_buf_end);
+ if (ret < 0)
+ return ret;
+
+ return memblock_free(buf_start, buf_end - buf_start);
+}
+
+/**
+ * of_get_ima_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 of_get_ima_buffer(void **addr, size_t *size)
+{
+ int ret;
+ void *ima_buf_start, *ima_buf_end;
+ uint64_t buf_start, buf_end;
+
+ ret = of_get_ima_buffer_properties(&ima_buf_start, &ima_buf_end);
+ if (ret < 0)
+ return ret;
+
+ buf_start = fdt64_to_cpu(*((const fdt64_t *) ima_buf_start));
+ buf_end = fdt64_to_cpu(*((const fdt64_t *) ima_buf_end));
+
+ *addr = __va(buf_start);
+ *size = buf_end - buf_start;
+
+ return 0;
+}
+
+/**
+ * fdt_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 fdt_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 = fdt_delete_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");
+ }
+}
+
+/**
+ * fdt_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 fdt_setup_ima_buffer(const phys_addr_t ima_buffer_addr,
+ const size_t ima_buffer_size,
+ void *fdt, int chosen_node)
+{
+ int ret;
+
+ fdt_remove_ima_buffer(fdt, chosen_node);
+
+ if (!ima_buffer_addr)
+ return 0;
+
+ ret = fdt_setprop_u64(fdt, chosen_node, "linux,ima-kexec-buffer",
+ ima_buffer_addr);
+ if (ret < 0)
+ return ret;
+
+ ret = fdt_setprop_u64(fdt, chosen_node, "linux,ima-kexec-buffer-end",
+ ima_buffer_addr +
+ ima_buffer_size);
+ if (ret < 0)
+ return ret;
+
+ ret = fdt_add_mem_rsv(fdt, ima_buffer_addr,
+ ima_buffer_size);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
diff --git a/include/linux/of.h b/include/linux/of.h
index 844f89e1b039..c24baca43f18 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -1477,4 +1477,35 @@ static inline int of_overlay_notifier_unregister(struct notifier_block *nb)
#endif
+#ifdef CONFIG_OF_IMA
+int of_remove_ima_buffer(void);
+int of_get_ima_buffer(void **addr, size_t *size);
+void fdt_remove_ima_buffer(void *fdt, int chosen_node);
+int fdt_setup_ima_buffer(const phys_addr_t ima_buffer_addr,
+ const size_t ima_buffer_size,
+ void *fdt, int chosen_node);
+#else
+static inline int of_remove_ima_buffer(void)
+{
+ return -ENOTSUPP;
+};
+
+static inline int of_get_ima_buffer(void **addr, size_t *size)
+{
+ return -ENOTSUPP;
+};
+
+static inline void fdt_remove_ima_buffer(void *fdt, int chosen_node)
+{
+ return;
+};
+
+static inline int fdt_setup_ima_buffer(const phys_addr_t ima_buffer_addr,
+ const size_t ima_buffer_size, void *fdt, int chosen_node)
+{
+ return -ENOTSUPP;
+};
+
+#endif
+
#endif /* _LINUX_OF_H */
--
2.17.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH v3 2/2] update powerpc implementation to call into of_ima*
2019-10-10 0:12 [PATCH v3 0/2] Add support for arm64 to carry ima measurement log in kexec_file_load Prakhar Srivastava
2019-10-10 0:12 ` [PATCH v3 1/2] " Prakhar Srivastava
@ 2019-10-10 0:12 ` Prakhar Srivastava
1 sibling, 0 replies; 3+ messages in thread
From: Prakhar Srivastava @ 2019-10-10 0:12 UTC (permalink / raw)
To: linux-kernel, linux-arm-kernel, linux-integrity, kexec
Cc: arnd, jean-philippe, allison, kristina.martsenko,
yamada.masahiro, duwe, mark.rutland, tglx, takahiro.akashi,
james.morse, catalin.marinas, sboyd, bauerman, zohar
update powerpc ima buffer pass implementationt to call into
of_ima* for a cross architecture support.
Signed-off-by: Prakhar Srivastava <prsriva@linux.microsoft.com>
---
arch/powerpc/include/asm/ima.h | 6 --
arch/powerpc/kernel/Makefile | 8 +-
arch/powerpc/kernel/ima_kexec.c | 170 +++-----------------------------
3 files changed, 16 insertions(+), 168 deletions(-)
diff --git a/arch/powerpc/include/asm/ima.h b/arch/powerpc/include/asm/ima.h
index ead488cf3981..5ecff8896eed 100644
--- a/arch/powerpc/include/asm/ima.h
+++ b/arch/powerpc/include/asm/ima.h
@@ -6,12 +6,7 @@ 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,
@@ -26,5 +21,4 @@ static inline int setup_ima_buffer(const struct kimage *image, void *fdt,
return 0;
}
#endif /* CONFIG_IMA_KEXEC */
-
#endif /* _ASM_POWERPC_IMA_H */
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 56dfa7a2a6f2..6a3d8fd6f1df 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -126,12 +126,8 @@ obj-$(CONFIG_PCI) += pci_$(BITS).o $(pci64-y) \
obj-$(CONFIG_PCI_MSI) += msi.o
obj-$(CONFIG_KEXEC_CORE) += machine_kexec.o crash.o \
machine_kexec_$(BITS).o
-obj-$(CONFIG_KEXEC_FILE) += machine_kexec_file_$(BITS).o kexec_elf_$(BITS).o
-ifdef CONFIG_HAVE_IMA_KEXEC
-ifdef CONFIG_IMA
-obj-y += ima_kexec.o
-endif
-endif
+obj-$(CONFIG_KEXEC_FILE) += machine_kexec_file_$(BITS).o kexec_elf_$(BITS).o \
+ ima_kexec.o
obj-$(CONFIG_AUDIT) += audit.o
obj64-$(CONFIG_AUDIT) += compat_audit.o
diff --git a/arch/powerpc/kernel/ima_kexec.c b/arch/powerpc/kernel/ima_kexec.c
index 720e50e490b6..41f52297de0c 100644
--- a/arch/powerpc/kernel/ima_kexec.c
+++ b/arch/powerpc/kernel/ima_kexec.c
@@ -6,45 +6,21 @@
* Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com>
*/
-#include <linux/slab.h>
#include <linux/kexec.h>
#include <linux/of.h>
-#include <linux/memblock.h>
-#include <linux/libfdt.h>
-static int get_addr_size_cells(int *addr_cells, int *size_cells)
+/**
+ * remove_ima_buffer - remove the IMA buffer property and reservation from @fdt
+ *
+ * The IMA measurement buffer is of no use to a subsequent kernel, so we always
+ * remove it from the device tree.
+ */
+void remove_ima_buffer(void *fdt, int chosen_node)
{
- struct device_node *root;
-
- root = of_find_node_by_path("/");
- if (!root)
- return -EINVAL;
-
- *addr_cells = of_n_addr_cells(root);
- *size_cells = of_n_size_cells(root);
-
- of_node_put(root);
-
- return 0;
+ fdt_remove_ima_buffer(fdt, chosen_node);
+ return;
}
-static int do_get_kexec_buffer(const void *prop, int len, unsigned long *addr,
- size_t *size)
-{
- int ret, addr_cells, size_cells;
-
- ret = get_addr_size_cells(&addr_cells, &size_cells);
- if (ret)
- return ret;
-
- if (len < 4 * (addr_cells + size_cells))
- return -ENOENT;
-
- *addr = of_read_number(prop, addr_cells);
- *size = of_read_number(prop + 4 * addr_cells, size_cells);
-
- return 0;
-}
/**
* ima_get_kexec_buffer - get IMA buffer from the previous kernel
@@ -55,23 +31,7 @@ static int do_get_kexec_buffer(const void *prop, int len, unsigned long *addr,
*/
int ima_get_kexec_buffer(void **addr, size_t *size)
{
- int ret, len;
- unsigned long tmp_addr;
- size_t tmp_size;
- const void *prop;
-
- prop = of_get_property(of_chosen, "linux,ima-kexec-buffer", &len);
- if (!prop)
- return -ENOENT;
-
- ret = do_get_kexec_buffer(prop, len, &tmp_addr, &tmp_size);
- if (ret)
- return ret;
-
- *addr = __va(tmp_addr);
- *size = tmp_size;
-
- return 0;
+ return of_get_ima_buffer(addr, size);
}
/**
@@ -79,52 +39,7 @@ int ima_get_kexec_buffer(void **addr, size_t *size)
*/
int ima_free_kexec_buffer(void)
{
- int ret;
- unsigned long addr;
- size_t size;
- struct property *prop;
-
- prop = of_find_property(of_chosen, "linux,ima-kexec-buffer", NULL);
- if (!prop)
- return -ENOENT;
-
- ret = do_get_kexec_buffer(prop->value, prop->length, &addr, &size);
- if (ret)
- return ret;
-
- ret = of_remove_property(of_chosen, prop);
- if (ret)
- return ret;
-
- return memblock_free(addr, size);
-
-}
-
-/**
- * remove_ima_buffer - remove the IMA buffer property and reservation from @fdt
- *
- * The IMA measurement buffer is of no use to a subsequent kernel, so we always
- * remove it from the device tree.
- */
-void remove_ima_buffer(void *fdt, int chosen_node)
-{
- int ret, len;
- unsigned long addr;
- size_t size;
- const void *prop;
-
- prop = fdt_getprop(fdt, chosen_node, "linux,ima-kexec-buffer", &len);
- if (!prop)
- return;
-
- ret = do_get_kexec_buffer(prop, len, &addr, &size);
- fdt_delprop(fdt, chosen_node, "linux,ima-kexec-buffer");
- if (ret)
- return;
-
- ret = delete_fdt_mem_rsv(fdt, addr, size);
- if (!ret)
- pr_debug("Removed old IMA buffer reservation.\n");
+ return of_remove_ima_buffer();
}
#ifdef CONFIG_IMA_KEXEC
@@ -145,27 +60,6 @@ int arch_ima_add_kexec_buffer(struct kimage *image, unsigned long load_addr,
return 0;
}
-static int write_number(void *p, u64 value, int cells)
-{
- if (cells == 1) {
- u32 tmp;
-
- if (value > U32_MAX)
- return -EINVAL;
-
- tmp = cpu_to_be32(value);
- memcpy(p, &tmp, sizeof(tmp));
- } else if (cells == 2) {
- u64 tmp;
-
- tmp = cpu_to_be64(value);
- memcpy(p, &tmp, sizeof(tmp));
- } else
- return -EINVAL;
-
- return 0;
-}
-
/**
* setup_ima_buffer - add IMA buffer information to the fdt
* @image: kexec image being loaded.
@@ -176,44 +70,8 @@ static int write_number(void *p, u64 value, int cells)
*/
int setup_ima_buffer(const struct kimage *image, void *fdt, int chosen_node)
{
- int ret, addr_cells, size_cells, entry_size;
- u8 value[16];
-
- remove_ima_buffer(fdt, chosen_node);
- if (!image->arch.ima_buffer_size)
- return 0;
-
- ret = get_addr_size_cells(&addr_cells, &size_cells);
- if (ret)
- return ret;
-
- entry_size = 4 * (addr_cells + size_cells);
-
- if (entry_size > sizeof(value))
- return -EINVAL;
-
- ret = write_number(value, image->arch.ima_buffer_addr, addr_cells);
- if (ret)
- return ret;
-
- ret = write_number(value + 4 * addr_cells, image->arch.ima_buffer_size,
- size_cells);
- if (ret)
- return ret;
-
- ret = fdt_setprop(fdt, chosen_node, "linux,ima-kexec-buffer", value,
- entry_size);
- if (ret < 0)
- return -EINVAL;
-
- ret = fdt_add_mem_rsv(fdt, image->arch.ima_buffer_addr,
- image->arch.ima_buffer_size);
- if (ret)
- return -EINVAL;
-
- pr_debug("IMA buffer at 0x%llx, size = 0x%zx\n",
- image->arch.ima_buffer_addr, image->arch.ima_buffer_size);
-
- return 0;
+ return fdt_setup_ima_buffer(image->arch.ima_buffer_addr,
+ image->arch.ima_buffer_size,
+ fdt, chosen_node);
}
#endif /* CONFIG_IMA_KEXEC */
--
2.17.1
^ permalink raw reply related [flat|nested] 3+ messages in thread