From: Stephen Boyd <sboyd@kernel.org>
To: Prakhar Srivastava <prsriva@linux.microsoft.com>,
linux-arm-msm@vger.kernel.org, linux-integrity@vger.kernel.org,
linux-kernel@vger.kernel.org
Cc: jmorris@namei.org, zohar@linux.ibm.com, bauerman@linux.ibm.com
Subject: Re: [RFC][PATCH 1/1] Carry ima measurement log for arm64 via kexec_file_load
Date: Thu, 29 Aug 2019 22:23:46 -0700 [thread overview]
Message-ID: <20190830052347.8032F2073F@mail.kernel.org> (raw)
In-Reply-To: <20190829200532.13545-2-prsriva@linux.microsoft.com>
Why is linux-arm-msm list CCed on this topic?
Quoting Prakhar Srivastava (2019-08-29 13:05:32)
> Carry ima measurement log for arm64 via kexec_file_load.
> add support to kexec_file_load to pass the ima measurement log
These first two sentences look sort of odd for a commit text.
>
> This patch adds entry for the ima measurement log in the
Don't use 'this patch' in commit text. It's in the wrong voice.
> dtb which is then used in the kexec'ed session to fetch the
> segment and then load the ima measurement log.
>
> Signed-off-by: Prakhar Srivastava <prsriva@linux.microsoft.com>
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 3adcec05b1f6..9e1b831e7baa 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -964,6 +964,13 @@ config KEXEC_FILE
> for kernel and initramfs as opposed to list of segments as
> accepted by previous system call.
>
> +config HAVE_IMA_KEXEC
> + bool "enable arch specific ima buffer pass"
> + depends on KEXEC_FILE
> + help
> + This adds support to carry ima log to the next kernel in case
Should ima be all caps here?
> + of kexec_file_load
Add a full-stop?
> +
> config KEXEC_VERIFY_SIG
> bool "Verify kernel signature during kexec_file_load() syscall"
> depends on KEXEC_FILE
> diff --git a/arch/arm64/include/asm/ima.h b/arch/arm64/include/asm/ima.h
> new file mode 100644
> index 000000000000..2c504281028d
> --- /dev/null
> +++ b/arch/arm64/include/asm/ima.h
> @@ -0,0 +1,31 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef _ASM_ARM64_IMA_H
> +#define _ASM_ARM64_IMA_H
> +
> +#define FDT_PROP_KEXEC_BUFFER "linux,ima-kexec-buffer"
Is this documented somewhere in the DT bindings?
> +
> +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..ca1f9ad5c4d4 100644
> --- a/arch/arm64/include/asm/kexec.h
> +++ b/arch/arm64/include/asm/kexec.h
> @@ -96,6 +96,8 @@ static inline void crash_post_resume(void) {}
> struct kimage_arch {
> void *dtb;
> unsigned long dtb_mem;
> + phys_addr_t ima_buffer_addr;
> + size_t ima_buffer_size;
Should this be in an ifdef?
> };
>
> extern const struct kexec_file_ops kexec_image_ops;
> @@ -107,6 +109,8 @@ extern int load_other_segments(struct kimage *image,
> unsigned long kernel_load_addr, unsigned long kernel_size,
> char *initrd, unsigned long initrd_len,
> char *cmdline);
> +extern int delete_fdt_mem_rsv(void *fdt, unsigned long start,
> + unsigned long size);
> #endif
>
> #endif /* __ASSEMBLY__ */
> diff --git a/arch/arm64/kernel/ima_kexec.c b/arch/arm64/kernel/ima_kexec.c
> new file mode 100644
> index 000000000000..5ae0d776ec42
> --- /dev/null
> +++ b/arch/arm64/kernel/ima_kexec.c
> @@ -0,0 +1,219 @@
> +/*
> + * Copyright (C) 2016 IBM Corporation
> + *
> + * Authors:
> + * Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
Please use a SPDX tag instead of this boiler plate.
> + */
> +
> +#include <linux/slab.h>
> +#include <linux/kexec.h>
> +#include <linux/of.h>
> +#include <linux/memblock.h>
> +#include <linux/libfdt.h>
> +#include <asm/kexec.h>
> +#include <asm/ima.h>
> +
> +static int get_addr_size_cells(int *addr_cells, int *size_cells)
> +{
> + 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;
> +}
> +
> +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
> + * @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 ret, len;
> + unsigned long tmp_addr;
> + size_t tmp_size;
> + const void *prop;
> +
> + prop = of_get_property(of_chosen, FDT_PROP_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;
> +}
> +
> +/**
> + * ima_free_kexec_buffer - free memory used by the IMA buffer
> + */
> +int ima_free_kexec_buffer(void)
> +{
> + int ret;
> + unsigned long addr;
> + size_t size;
> + struct property *prop;
> +
> + prop = of_find_property(of_chosen, FDT_PROP_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);
> +}
> +
> +#ifdef CONFIG_IMA
> +/**
> + * 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, FDT_PROP_KEXEC_BUFFER, &len);
> + if (!prop)
> + return;
> +
> + ret = do_get_kexec_buffer(prop, len, &addr, &size);
> + fdt_delprop(fdt, chosen_node, FDT_PROP_KEXEC_BUFFER);
> + if (ret)
> + return;
> +
> + ret = delete_fdt_mem_rsv(fdt, addr, size);
> + if (!ret)
> + pr_debug("Removed old IMA buffer reservation.\n");
> +}
> +#endif /* CONFIG_IMA */
> +
> +#ifdef CONFIG_IMA_KEXEC
> +/**
> + * arch_ima_add_kexec_buffer - do arch-specific steps to add the IMA buffer
> + *
> + * Architectures should use this function to pass on the IMA buffer
> + * information to the next kernel.
> + *
> + * 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;
> +}
> +
> +static int write_number(void *p, u64 value, int cells)
Maybe this should be an of_write_number() API exposed by the DT parsing
code?
> +{
> + 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;
Put braces around this else please.
> + return 0;
> +}
> +
> +/**
> + * setup_ima_buffer - add IMA buffer information to the fdt
> + * @image: kexec image being loaded.
> + * @dtb: Flattened device tree for the next kernel.
> + * @chosen_node: Offset to the chosen node.
Why capitalize Flattened and Offset?
> + *
> + * Return: 0 on success, or negative errno on error.
> + */
> +int setup_ima_buffer(const struct kimage *image, void *dtb, int chosen_node)
> +{
> + int ret, addr_cells, size_cells, entry_size;
> + u8 value[16];
> +
> + remove_ima_buffer(dtb, chosen_node);
> +
> + 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(dtb, chosen_node, FDT_PROP_KEXEC_BUFFER, value,
> + entry_size);
> + if (ret < 0)
> + return -EINVAL;
> +
> + ret = fdt_add_mem_rsv(dtb, image->segment[0].mem,
> + image->segment[0].memsz);
> + if (ret)
> + return -EINVAL;
> +
> + 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..c05ad6b74b62 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_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)
> @@ -114,6 +120,39 @@ static int setup_dtb(struct kimage *image,
> */
> #define DTB_EXTRA_SPACE 0x1000
>
> +
> +/**
> + * delete_fdt_mem_rsv - delete memory reservation with given address and size
> + *
Can you document the arguments too?
> + * 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");
Please drop the full-stop on this printk.
> + 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");
Same comment.
> + return -EINVAL;
> + }
> +
> + return 0;
> + }
> + }
> +
> + return -ENOENT;
> +}
A lot of this code looks DT generic. Can it be moved out of the arch
layer to drivers/of/?
next prev parent reply other threads:[~2019-08-30 5:23 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-08-29 20:05 [RFC][PATCH v1 0/1] Carry ima measurement log for arm64 via kexec_file_load Prakhar Srivastava
2019-08-29 20:05 ` [RFC][PATCH 1/1] " Prakhar Srivastava
2019-08-30 5:23 ` Stephen Boyd [this message]
2019-08-31 0:17 ` Thiago Jung Bauermann
2019-08-31 0:11 ` Thiago Jung Bauermann
2019-09-06 23:56 ` prsriva
2019-09-08 23:31 ` Mimi Zohar
2019-09-09 23:18 ` prsriva
-- strict thread matches above, loose matches on Subject: below --
2019-08-29 19:00 [RFC][PATCH v1 0/1] " Prakhar Srivastava
2019-08-29 19:00 ` [RFC][PATCH 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=20190830052347.8032F2073F@mail.kernel.org \
--to=sboyd@kernel.org \
--cc=bauerman@linux.ibm.com \
--cc=jmorris@namei.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-integrity@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=prsriva@linux.microsoft.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.