Message ID | YmgjXZphkmDKgaOA@noodles-fedora-PC23Y6EG (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v2] Carry forward IMA measurement log on kexec on x86_64 | expand |
> diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c > index 13753136f03f..419c50cfe6b9 100644 > --- a/security/integrity/ima/ima_kexec.c > +++ b/security/integrity/ima/ima_kexec.c > @@ -10,6 +10,7 @@ > #include <linux/seq_file.h> > #include <linux/vmalloc.h> > #include <linux/kexec.h> > +#include <linux/memblock.h> > #include <linux/of.h> > #include <linux/ima.h> > #include "ima.h" > @@ -134,10 +135,66 @@ void ima_add_kexec_buffer(struct kimage *image) > } > #endif /* IMA_KEXEC */ > > +#ifndef CONFIG_OF > +static phys_addr_t ima_early_kexec_buffer_phys; > +static size_t ima_early_kexec_buffer_size; > + > +void __init ima_set_kexec_buffer(phys_addr_t phys_addr, size_t size) > +{ > + if (size == 0) > + return; > + > + ima_early_kexec_buffer_phys = phys_addr; > + ima_early_kexec_buffer_size = size; > +} > + > +int __init ima_free_kexec_buffer(void) > +{ > + int rc; > + > + if (!IS_ENABLED(CONFIG_HAVE_IMA_KEXEC)) > + return -ENOTSUPP; > + > + if (ima_early_kexec_buffer_size == 0) > + return -ENOENT; > + > + rc = memblock_phys_free(ima_early_kexec_buffer_phys, > + ima_early_kexec_buffer_size); > + if (rc) > + return rc; > + > + ima_early_kexec_buffer_phys = 0; > + ima_early_kexec_buffer_size = 0; > + > + return 0; > +} > + > +int __init ima_get_kexec_buffer(void **addr, size_t *size) > +{ > + if (!IS_ENABLED(CONFIG_HAVE_IMA_KEXEC)) > + return -ENOTSUPP; > + > + if (ima_early_kexec_buffer_size == 0) > + return -ENOENT; > + > + *addr = __va(ima_early_kexec_buffer_phys); > + *size = ima_early_kexec_buffer_size; > + > + return 0; > +} > + Originally both ima_get_kexec_buffer() and ima_free_kexec_buffer() were architecture specific. Refer to commit 467d27824920 ("powerpc: ima: get the kexec buffer passed by the previous kernel"). Is there any need for defining them here behind an "#ifndef CONFIG_OF"? > +#else > + > +void __init ima_set_kexec_buffer(phys_addr_t phys_addr, size_t size) > +{ > + pr_warn("CONFIG_OF enabled, ignoring call to set buffer details.\n"); > +} > +#endif /* CONFIG_OF */ > + Only when "HAVE_IMA_KEXEC" is defined is this file included. Why is this warning needed? thanks, Mimi > /* > * Restore the measurement list from the previous kernel. > */ > -void ima_load_kexec_buffer(void) > +void __init ima_load_kexec_buffer(void) > { > void *kexec_buffer = NULL; > size_t kexec_buffer_size = 0;
On Fri, Apr 29, 2022 at 05:30:10PM -0400, Mimi Zohar wrote: > > diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c > > index 13753136f03f..419c50cfe6b9 100644 > > --- a/security/integrity/ima/ima_kexec.c > > +++ b/security/integrity/ima/ima_kexec.c > > @@ -10,6 +10,7 @@ > > #include <linux/seq_file.h> > > #include <linux/vmalloc.h> > > #include <linux/kexec.h> > > +#include <linux/memblock.h> > > #include <linux/of.h> > > #include <linux/ima.h> > > #include "ima.h" > > @@ -134,10 +135,66 @@ void ima_add_kexec_buffer(struct kimage *image) > > } > > #endif /* IMA_KEXEC */ > > > > +#ifndef CONFIG_OF > > +static phys_addr_t ima_early_kexec_buffer_phys; > > +static size_t ima_early_kexec_buffer_size; > > + > > +void __init ima_set_kexec_buffer(phys_addr_t phys_addr, size_t size) > > +{ > > + if (size == 0) > > + return; > > + > > + ima_early_kexec_buffer_phys = phys_addr; > > + ima_early_kexec_buffer_size = size; > > +} > > + > > +int __init ima_free_kexec_buffer(void) > > +{ > > + int rc; > > + > > + if (!IS_ENABLED(CONFIG_HAVE_IMA_KEXEC)) > > + return -ENOTSUPP; > > + > > + if (ima_early_kexec_buffer_size == 0) > > + return -ENOENT; > > + > > + rc = memblock_phys_free(ima_early_kexec_buffer_phys, > > + ima_early_kexec_buffer_size); > > + if (rc) > > + return rc; > > + > > + ima_early_kexec_buffer_phys = 0; > > + ima_early_kexec_buffer_size = 0; > > + > > + return 0; > > +} > > + > > +int __init ima_get_kexec_buffer(void **addr, size_t *size) > > +{ > > + if (!IS_ENABLED(CONFIG_HAVE_IMA_KEXEC)) > > + return -ENOTSUPP; > > + > > + if (ima_early_kexec_buffer_size == 0) > > + return -ENOENT; > > + > > + *addr = __va(ima_early_kexec_buffer_phys); > > + *size = ima_early_kexec_buffer_size; > > + > > + return 0; > > +} > > + > > Originally both ima_get_kexec_buffer() and ima_free_kexec_buffer() were > architecture specific. Refer to commit 467d27824920 ("powerpc: ima: > get the kexec buffer passed by the previous kernel"). Is there any > need for defining them here behind an "#ifndef CONFIG_OF"? Commit fee3ff99bc67 (powerpc: Move arch independent ima kexec functions to drivers/of/kexec.c) moved those functions to drivers/of/kexec.c as a more generic implementation so that ARM64 could use them too. I think for platforms that use device tree that's the way to go, but the functions to generically set + get the IMA buffer for non device tree systems were useful enough to put in the IMA code rather than being x86 specific. If you disagree I can move them under arch/x86/ (assuming the x86 folk agree using setup_data is the right way to go, I haven't seen any of them comment on this approach yet). > > +#else > > + > > +void __init ima_set_kexec_buffer(phys_addr_t phys_addr, size_t size) > > +{ > > + pr_warn("CONFIG_OF enabled, ignoring call to set buffer details.\n"); > > +} > > +#endif /* CONFIG_OF */ > > + > > Only when "HAVE_IMA_KEXEC" is defined is this file included. Why is > this warning needed? x86 *can* have device tree enabled, but the only platform I'm aware that did it was OLPC and I haven't seen any of the distros enable it. I put this in so there's a warning if we have CONFIG_OF enabled on x86 and tried to pass the IMA log via setup_data. Can remove (or fold into the x86 code if we go that way). > > /* > > * Restore the measurement list from the previous kernel. > > */ > > -void ima_load_kexec_buffer(void) > > +void __init ima_load_kexec_buffer(void) > > { > > void *kexec_buffer = NULL; > > size_t kexec_buffer_size = 0; J.
On Tue, 2022-05-03 at 12:02 +0000, Jonathan McDowell wrote: > On Fri, Apr 29, 2022 at 05:30:10PM -0400, Mimi Zohar wrote: > > > diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c > > > index 13753136f03f..419c50cfe6b9 100644 > > > --- a/security/integrity/ima/ima_kexec.c > > > +++ b/security/integrity/ima/ima_kexec.c > > > @@ -10,6 +10,7 @@ > > > #include <linux/seq_file.h> > > > #include <linux/vmalloc.h> > > > #include <linux/kexec.h> > > > +#include <linux/memblock.h> > > > #include <linux/of.h> > > > #include <linux/ima.h> > > > #include "ima.h" > > > @@ -134,10 +135,66 @@ void ima_add_kexec_buffer(struct kimage *image) > > > } > > > #endif /* IMA_KEXEC */ > > > > > > +#ifndef CONFIG_OF > > > +static phys_addr_t ima_early_kexec_buffer_phys; > > > +static size_t ima_early_kexec_buffer_size; > > > + > > > +void __init ima_set_kexec_buffer(phys_addr_t phys_addr, size_t size) > > > +{ > > > + if (size == 0) > > > + return; > > > + > > > + ima_early_kexec_buffer_phys = phys_addr; > > > + ima_early_kexec_buffer_size = size; > > > +} > > > + > > > +int __init ima_free_kexec_buffer(void) > > > +{ > > > + int rc; > > > + > > > + if (!IS_ENABLED(CONFIG_HAVE_IMA_KEXEC)) > > > + return -ENOTSUPP; > > > + > > > + if (ima_early_kexec_buffer_size == 0) > > > + return -ENOENT; > > > + > > > + rc = memblock_phys_free(ima_early_kexec_buffer_phys, > > > + ima_early_kexec_buffer_size); > > > + if (rc) > > > + return rc; > > > + > > > + ima_early_kexec_buffer_phys = 0; > > > + ima_early_kexec_buffer_size = 0; > > > + > > > + return 0; > > > +} > > > + > > > +int __init ima_get_kexec_buffer(void **addr, size_t *size) > > > +{ > > > + if (!IS_ENABLED(CONFIG_HAVE_IMA_KEXEC)) > > > + return -ENOTSUPP; The Kconfig conditionally compiles ima_kexec.c based on CONFIG_HAVE_IMA_KEXEC. This test should be removed from here and from ima_get_kexec_buffer(). CONFIG_IMA_KEXEC controls whether or not to carry the measurement list to the next kernel, not whether the measurement list should be restored. Notice that ima_load_kexec_buffer() is not within the ifdef CONFIG_IMA_KEXEC. > > > + > > > + if (ima_early_kexec_buffer_size == 0) > > > + return -ENOENT; There should always be at least one measurement - the boot_aggregate. > > > + > > > + *addr = __va(ima_early_kexec_buffer_phys); > > > + *size = ima_early_kexec_buffer_size; > > > + > > > + return 0; > > > +} > > > + > > > > Originally both ima_get_kexec_buffer() and ima_free_kexec_buffer() were > > architecture specific. Refer to commit 467d27824920 ("powerpc: ima: > > get the kexec buffer passed by the previous kernel"). Is there any > > need for defining them here behind an "#ifndef CONFIG_OF"? > > Commit fee3ff99bc67 (powerpc: Move arch independent ima kexec functions > to drivers/of/kexec.c) moved those functions to drivers/of/kexec.c as a > more generic implementation so that ARM64 could use them too. > > I think for platforms that use device tree that's the way to go, but the > functions to generically set + get the IMA buffer for non device tree > systems were useful enough to put in the IMA code rather than being x86 > specific. If you disagree I can move them under arch/x86/ (assuming the > x86 folk agree using setup_data is the right way to go, I haven't seen > any of them comment on this approach yet). So other architectures will need to define CONFIG_HAVE_IMA_KEXEC, a function to call ima_set_kexec_buffer() to restore the measurement list, and a function equivalent to ima_setup_state(). After removing the unnecessary tests mentioned above, consider whether there is still any benefit to defining these functions. > > > +#else > > > + > > > +void __init ima_set_kexec_buffer(phys_addr_t phys_addr, size_t size) > > > +{ > > > + pr_warn("CONFIG_OF enabled, ignoring call to set buffer details.\n"); > > > +} > > > +#endif /* CONFIG_OF */ > > > + > > > > Only when "HAVE_IMA_KEXEC" is defined is this file included. Why is > > this warning needed? > > x86 *can* have device tree enabled, but the only platform I'm aware that > did it was OLPC and I haven't seen any of the distros enable it. I put > this in so there's a warning if we have CONFIG_OF enabled on x86 and > tried to pass the IMA log via setup_data. Can remove (or fold into the > x86 code if we go that way). Thanks for the explanation. > > > /* > > > * Restore the measurement list from the previous kernel. > > > */ > > > -void ima_load_kexec_buffer(void) > > > +void __init ima_load_kexec_buffer(void) > > > { > > > void *kexec_buffer = NULL; > > > size_t kexec_buffer_size = 0; > > J. thanks, Mimi
Can someone from the x86 side provide some feedback on whether using setup_data to pass this data across the kexec boundary is appropriate, and if not point me in a better direction? On Tue, Apr 26, 2022 at 05:53:47PM +0100, Jonathan McDowell wrote: > On kexec file load Integrity Measurement Architecture (IMA) subsystem > may verify the IMA signature of the kernel and initramfs, and measure > it. The command line parameters passed to the kernel in the kexec call > may also be measured by IMA. A remote attestation service can verify > a TPM quote based on the TPM event log, the IMA measurement list, and > the TPM PCR data. This can be achieved only if the IMA measurement log > is carried over from the current kernel to the next kernel across > the kexec call. > > powerpc and ARM64 both achieve this using device tree with a > "linux,ima-kexec-buffer" node. x86 platforms generally don't make use of > device tree, so the IMA infrastructure is extended to allow non device > tree platforms to provide a log buffer. x86 then passes the IMA buffer > to the new kernel via the setup_data mechanism. > > Signed-off-by: Jonathan McDowell <noodles@fb.com> > --- > v2: > - Fix operation with EFI systems > --- > arch/x86/Kconfig | 1 + > arch/x86/include/uapi/asm/bootparam.h | 9 ++++ > arch/x86/kernel/e820.c | 6 +-- > arch/x86/kernel/kexec-bzimage64.c | 39 +++++++++++++++++- > arch/x86/kernel/setup.c | 26 ++++++++++++ > include/linux/ima.h | 1 + > security/integrity/ima/ima_kexec.c | 59 ++++++++++++++++++++++++++- > 7 files changed, 136 insertions(+), 5 deletions(-) > > diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig > index b0142e01002e..bde4959d9bdc 100644 > --- a/arch/x86/Kconfig > +++ b/arch/x86/Kconfig > @@ -2017,6 +2017,7 @@ config KEXEC_FILE > bool "kexec file based system call" > select KEXEC_CORE > select BUILD_BIN2C > + select HAVE_IMA_KEXEC if IMA > depends on X86_64 > depends on CRYPTO=y > depends on CRYPTO_SHA256=y > diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h > index b25d3f82c2f3..2f7b138a9388 100644 > --- a/arch/x86/include/uapi/asm/bootparam.h > +++ b/arch/x86/include/uapi/asm/bootparam.h > @@ -10,6 +10,7 @@ > #define SETUP_EFI 4 > #define SETUP_APPLE_PROPERTIES 5 > #define SETUP_JAILHOUSE 6 > +#define SETUP_IMA 7 > > #define SETUP_INDIRECT (1<<31) > > @@ -171,6 +172,14 @@ struct jailhouse_setup_data { > } __attribute__((packed)) v2; > } __attribute__((packed)); > > +/* > + * IMA buffer setup data information from the previous kernel during kexec > + */ > +struct ima_setup_data { > + __u64 addr; > + __u64 size; > +} __attribute__((packed)); > + > /* The so-called "zeropage" */ > struct boot_params { > struct screen_info screen_info; /* 0x000 */ > diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c > index f267205f2d5a..9dac24680ff8 100644 > --- a/arch/x86/kernel/e820.c > +++ b/arch/x86/kernel/e820.c > @@ -1017,10 +1017,10 @@ void __init e820__reserve_setup_data(void) > e820__range_update(pa_data, sizeof(*data)+data->len, E820_TYPE_RAM, E820_TYPE_RESERVED_KERN); > > /* > - * SETUP_EFI is supplied by kexec and does not need to be > - * reserved. > + * SETUP_EFI and SETUP_IMA are supplied by kexec and do not need > + * to be reserved. > */ > - if (data->type != SETUP_EFI) > + if (data->type != SETUP_EFI && data->type != SETUP_IMA) > e820__range_update_kexec(pa_data, > sizeof(*data) + data->len, > E820_TYPE_RAM, E820_TYPE_RESERVED_KERN); > diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c > index 170d0fd68b1f..cdc73e081585 100644 > --- a/arch/x86/kernel/kexec-bzimage64.c > +++ b/arch/x86/kernel/kexec-bzimage64.c > @@ -186,6 +186,32 @@ setup_efi_state(struct boot_params *params, unsigned long params_load_addr, > } > #endif /* CONFIG_EFI */ > > +#ifdef CONFIG_IMA_KEXEC > +static void > +setup_ima_state(const struct kimage *image, struct boot_params *params, > + unsigned long params_load_addr, > + unsigned int ima_setup_data_offset) > +{ > + struct setup_data *sd = (void *)params + ima_setup_data_offset; > + struct ima_setup_data *ima = (void *)sd + sizeof(struct setup_data); > + unsigned long setup_data_phys; > + > + if (!image->ima_buffer_size) > + return; > + > + sd->type = SETUP_IMA; > + sd->len = sizeof(*ima); > + > + ima->addr = image->ima_buffer_addr; > + ima->size = image->ima_buffer_size; > + > + /* Add setup data */ > + setup_data_phys = params_load_addr + ima_setup_data_offset; > + sd->next = params->hdr.setup_data; > + params->hdr.setup_data = setup_data_phys; > +} > +#endif /* CONFIG_IMA_KEXEC */ > + > static int > setup_boot_parameters(struct kimage *image, struct boot_params *params, > unsigned long params_load_addr, > @@ -247,6 +273,15 @@ setup_boot_parameters(struct kimage *image, struct boot_params *params, > setup_efi_state(params, params_load_addr, efi_map_offset, efi_map_sz, > efi_setup_data_offset); > #endif > + > +#ifdef CONFIG_IMA_KEXEC > + /* Setup IMA log buffer state */ > + setup_ima_state(image, params, params_load_addr, > + efi_setup_data_offset + > + sizeof(struct setup_data) + > + sizeof(struct efi_setup_data)); > +#endif > + > /* Setup EDD info */ > memcpy(params->eddbuf, boot_params.eddbuf, > EDDMAXNR * sizeof(struct edd_info)); > @@ -401,7 +436,9 @@ static void *bzImage64_load(struct kimage *image, char *kernel, > params_cmdline_sz = ALIGN(params_cmdline_sz, 16); > kbuf.bufsz = params_cmdline_sz + ALIGN(efi_map_sz, 16) + > sizeof(struct setup_data) + > - sizeof(struct efi_setup_data); > + sizeof(struct efi_setup_data) + > + sizeof(struct setup_data) + > + sizeof(struct ima_setup_data); > > params = kzalloc(kbuf.bufsz, GFP_KERNEL); > if (!params) > diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c > index c95b9ac5a457..8b0e7725f918 100644 > --- a/arch/x86/kernel/setup.c > +++ b/arch/x86/kernel/setup.c > @@ -11,6 +11,7 @@ > #include <linux/dma-map-ops.h> > #include <linux/dmi.h> > #include <linux/efi.h> > +#include <linux/ima.h> > #include <linux/init_ohci1394_dma.h> > #include <linux/initrd.h> > #include <linux/iscsi_ibft.h> > @@ -335,6 +336,28 @@ static void __init reserve_initrd(void) > } > #endif /* CONFIG_BLK_DEV_INITRD */ > > +#ifdef CONFIG_IMA_KEXEC > +static void __init add_early_ima_buffer(u64 phys_addr) > +{ > + struct ima_setup_data *data; > + > + data = early_memremap(phys_addr + sizeof(struct setup_data), > + sizeof(*data)); > + if (!data) { > + pr_warn("setup: failed to memremap ima_setup_data entry\n"); > + return; > + } > + memblock_reserve(data->addr, data->size); > + ima_set_kexec_buffer(data->addr, data->size); > + early_memunmap(data, sizeof(*data)); > +} > +#else > +static void __init add_early_ima_buffer(u64 phys_addr) > +{ > + pr_warn("Passed IMA kexec data, but CONFIG_IMA_KEXEC not set. Ignoring.\n"); > +} > +#endif > + > static void __init parse_setup_data(void) > { > struct setup_data *data; > @@ -360,6 +383,9 @@ static void __init parse_setup_data(void) > case SETUP_EFI: > parse_efi_setup(pa_data, data_len); > break; > + case SETUP_IMA: > + add_early_ima_buffer(pa_data); > + break; > default: > break; > } > diff --git a/include/linux/ima.h b/include/linux/ima.h > index 426b1744215e..f58aed7acad4 100644 > --- a/include/linux/ima.h > +++ b/include/linux/ima.h > @@ -48,6 +48,7 @@ static inline void ima_appraise_parse_cmdline(void) {} > > #ifdef CONFIG_IMA_KEXEC > extern void ima_add_kexec_buffer(struct kimage *image); > +extern void ima_set_kexec_buffer(phys_addr_t phys_addr, size_t size); > #endif > > #else > diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c > index 13753136f03f..419c50cfe6b9 100644 > --- a/security/integrity/ima/ima_kexec.c > +++ b/security/integrity/ima/ima_kexec.c > @@ -10,6 +10,7 @@ > #include <linux/seq_file.h> > #include <linux/vmalloc.h> > #include <linux/kexec.h> > +#include <linux/memblock.h> > #include <linux/of.h> > #include <linux/ima.h> > #include "ima.h" > @@ -134,10 +135,66 @@ void ima_add_kexec_buffer(struct kimage *image) > } > #endif /* IMA_KEXEC */ > > +#ifndef CONFIG_OF > +static phys_addr_t ima_early_kexec_buffer_phys; > +static size_t ima_early_kexec_buffer_size; > + > +void __init ima_set_kexec_buffer(phys_addr_t phys_addr, size_t size) > +{ > + if (size == 0) > + return; > + > + ima_early_kexec_buffer_phys = phys_addr; > + ima_early_kexec_buffer_size = size; > +} > + > +int __init ima_free_kexec_buffer(void) > +{ > + int rc; > + > + if (!IS_ENABLED(CONFIG_HAVE_IMA_KEXEC)) > + return -ENOTSUPP; > + > + if (ima_early_kexec_buffer_size == 0) > + return -ENOENT; > + > + rc = memblock_phys_free(ima_early_kexec_buffer_phys, > + ima_early_kexec_buffer_size); > + if (rc) > + return rc; > + > + ima_early_kexec_buffer_phys = 0; > + ima_early_kexec_buffer_size = 0; > + > + return 0; > +} > + > +int __init ima_get_kexec_buffer(void **addr, size_t *size) > +{ > + if (!IS_ENABLED(CONFIG_HAVE_IMA_KEXEC)) > + return -ENOTSUPP; > + > + if (ima_early_kexec_buffer_size == 0) > + return -ENOENT; > + > + *addr = __va(ima_early_kexec_buffer_phys); > + *size = ima_early_kexec_buffer_size; > + > + return 0; > +} > + > +#else > + > +void __init ima_set_kexec_buffer(phys_addr_t phys_addr, size_t size) > +{ > + pr_warn("CONFIG_OF enabled, ignoring call to set buffer details.\n"); > +} > +#endif /* CONFIG_OF */ > + > /* > * Restore the measurement list from the previous kernel. > */ > -void ima_load_kexec_buffer(void) > +void __init ima_load_kexec_buffer(void) > { > void *kexec_buffer = NULL; > size_t kexec_buffer_size = 0; > -- > 2.34.1 >
On May 9, 2022 10:40:01 AM UTC, Jonathan McDowell <noodles@fb.com> wrote: >> powerpc and ARM64 both achieve this using device tree with a >> "linux,ima-kexec-buffer" node. x86 platforms generally don't make use of >> device tree What's wrong with making x86 use the same devicetree node(s)?
On Mon, May 09, 2022 at 11:25:22AM +0000, Boris Petkov wrote: > On May 9, 2022 10:40:01 AM UTC, Jonathan McDowell <noodles@fb.com> wrote: > >> powerpc and ARM64 both achieve this using device tree with a > >> "linux,ima-kexec-buffer" node. x86 platforms generally don't make use of > >> device tree > > What's wrong with making x86 use the same devicetree node(s)? Device tree on x86 doesn't seem to be a thing; none of the distros I regularly use enable CONFIG_OF for x86, I can only find 2 32-bit x86 platforms that actually select it and none of the plumbing for kexec on x86 ties in device tree. I agree for platforms that make active use of device tree that's the appropriate path, but it doesn't seem to be the case for x86. J.
On Mon, May 09, 2022 at 05:46:22PM +0000, Jonathan McDowell wrote: > Device tree on x86 doesn't seem to be a thing; Not a thing? What does that even mean? We have arch/x86/kernel/devicetree.c which adds some minimal devicetree support. > none of the distros I regularly use enable CONFIG_OF for x86, I can > only find 2 32-bit x86 platforms that actually select it and none of > the plumbing for kexec on x86 ties in device tree. And? That can get changed and enabled and so on. > I agree for platforms that make active use of device tree that's the > appropriate path, but it doesn't seem to be the case for x86. I'm not sure what you're aim here is? You want to pass that IMA measurement to the kexec kernel with minimal changes, i.e., change only the kernel? Why can't distros be also changed to use devicetree for the IMA measurement, like the other arches do? Why does x86 need to do it differently? We also pass info to the kexec kernel by reading it from sysfs and having kexec tools pass it to the kexec-ed kernel, see Documentation/ABI/testing/sysfs-firmware-efi-runtime-map kexec(8) itself can do: kexec -l kernel-image --append=command-line-options ^^^^^^^^^^^^^^^^^ and add those cmdline options which are dug out from the first kernel. So is there any particular reason/pressing need to pass the measurement with setup_data?
On Mon, May 09, 2022 at 08:09:55PM +0200, Borislav Petkov wrote: > On Mon, May 09, 2022 at 05:46:22PM +0000, Jonathan McDowell wrote: > > Device tree on x86 doesn't seem to be a thing; > > Not a thing? What does that even mean? Let me rephrase more verbosely. Device tree on x86 seems to be a rarely enabled config option that is only required on a couple of platforms and lacks the same level of integration with the x86 boot process (compared to PowerPC and ARM64) such that a) there's a lot more code that would need to be written to even get to the point that it could be used in the same manner for passing the IMA buffer as on other platforms and b) I'm not sure whether or not it might introduce other issues due to this lack of use/testing. > We have arch/x86/kernel/devicetree.c which adds some minimal devicetree > support. > > > none of the distros I regularly use enable CONFIG_OF for x86, I can > > only find 2 32-bit x86 platforms that actually select it and none of > > the plumbing for kexec on x86 ties in device tree. > > And? That can get changed and enabled and so on. > > > I agree for platforms that make active use of device tree that's the > > appropriate path, but it doesn't seem to be the case for x86. > > I'm not sure what you're aim here is? > > You want to pass that IMA measurement to the kexec kernel with minimal > changes, i.e., change only the kernel? I'd like to be able to take an internal kernel buffer and pass it to the newly kexeced kernel, yes. I'd like that to be possible with the kexec_file_load() path, which allows for things like kernel signing, which I believe precludes providing the data from user space. > Why can't distros be also changed to use devicetree for the IMA > measurement, like the other arches do? Why does x86 need to do it > differently? > We also pass info to the kexec kernel by reading it from sysfs > and having kexec tools pass it to the kexec-ed kernel, see > Documentation/ABI/testing/sysfs-firmware-efi-runtime-map AFAICT kexec passes EFI details using SETUP_EFI, which is what I modelled the SETUP_IMA support on (1fec0533693cd74f2d1a46edd29449cfee429df0). In the old syscall variant the kexec tools do read /sys/firmware/efi/runtime-map and create a setup_data entry of type SETUP_EFI, in the new file based kexec that is done inside the kernel in a similar fashion to what I've done with SETUP_IMA. > So is there any particular reason/pressing need to pass the measurement > with setup_data? I'm not tied to setup_data but given the concerns I raise above with device tree on x86 and the need to handle this in the kernel it seemed like a reasonable first approach. You seem to be saying it's not and either adding the device tree infrastructure or doing a command line hack would be preferable? J.
On Mon, May 09, 2022 at 06:41:17PM +0000, Jonathan McDowell wrote: > I'm not tied to setup_data but given the concerns I raise above with > device tree on x86 and the need to handle this in the kernel it seemed > like a reasonable first approach. You seem to be saying it's not and > either adding the device tree infrastructure or doing a command line > hack would be preferable? All I'm doing is asking more questions to make you give more details as to why you wanna do it this way. I'll take a detailed look tomorrow but it looks ok from a quick glance. Thx.
On Mon, May 09, 2022 at 09:40:28PM +0200, Borislav Petkov wrote: > On Mon, May 09, 2022 at 06:41:17PM +0000, Jonathan McDowell wrote: > > I'm not tied to setup_data but given the concerns I raise above with > > device tree on x86 and the need to handle this in the kernel it seemed > > like a reasonable first approach. You seem to be saying it's not and > > either adding the device tree infrastructure or doing a command line > > hack would be preferable? > > All I'm doing is asking more questions to make you give more details as > to why you wanna do it this way. I'll take a detailed look tomorrow but > it looks ok from a quick glance. That's reasonable, thanks for taking the time to do so. I realised another problem with the command line approach is that this is a flow involving attestation and potentially signing across the kexec boundary, so if the command line changes every time due to the memory address we pass the IMA buffer in then we have to recalculate the expected PCR etc values for every kexec after we've done the user space buffer allocation, rather than being able to do so once + offline in advance for a particular kexec across multiple machines. J.
On Tue, Apr 26, 2022 at 04:52:49PM +0000, Jonathan McDowell wrote: > Subject: Re: [PATCH v2] Carry forward IMA measurement log on kexec on x86_64 The tip tree preferred format for patch subject prefixes is 'subsys/component:', e.g. 'x86/apic:', 'x86/mm/fault:', 'sched/fair:', 'genirq/core:'. Please do not use file names or complete file paths as prefix. 'git log path/to/file' should give you a reasonable hint in most cases. The condensed patch description in the subject line should start with a uppercase letter and should be written in imperative tone. I guess in your case "x86/kexec: Carry ..." > diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h > index b25d3f82c2f3..2f7b138a9388 100644 > --- a/arch/x86/include/uapi/asm/bootparam.h > +++ b/arch/x86/include/uapi/asm/bootparam.h > @@ -10,6 +10,7 @@ > #define SETUP_EFI 4 > #define SETUP_APPLE_PROPERTIES 5 > #define SETUP_JAILHOUSE 6 > +#define SETUP_IMA 7 There's already #define SETUP_CC_BLOB 7 in the tip tree - please redo your patch against current tip/master. > diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c > index 170d0fd68b1f..cdc73e081585 100644 > --- a/arch/x86/kernel/kexec-bzimage64.c > +++ b/arch/x86/kernel/kexec-bzimage64.c > @@ -186,6 +186,32 @@ setup_efi_state(struct boot_params *params, unsigned long params_load_addr, > } > #endif /* CONFIG_EFI */ > > +#ifdef CONFIG_IMA_KEXEC > +static void > +setup_ima_state(const struct kimage *image, struct boot_params *params, You can push that ugly ifdeffery inside the function like so: diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c index cdc73e081585..47ba7083fd44 100644 --- a/arch/x86/kernel/kexec-bzimage64.c +++ b/arch/x86/kernel/kexec-bzimage64.c @@ -186,12 +186,12 @@ setup_efi_state(struct boot_params *params, unsigned long params_load_addr, } #endif /* CONFIG_EFI */ -#ifdef CONFIG_IMA_KEXEC static void setup_ima_state(const struct kimage *image, struct boot_params *params, unsigned long params_load_addr, unsigned int ima_setup_data_offset) { +#ifdef CONFIG_IMA_KEXEC struct setup_data *sd = (void *)params + ima_setup_data_offset; struct ima_setup_data *ima = (void *)sd + sizeof(struct setup_data); unsigned long setup_data_phys; @@ -209,8 +209,8 @@ setup_ima_state(const struct kimage *image, struct boot_params *params, setup_data_phys = params_load_addr + ima_setup_data_offset; sd->next = params->hdr.setup_data; params->hdr.setup_data = setup_data_phys; -} #endif /* CONFIG_IMA_KEXEC */ +} static int setup_boot_parameters(struct kimage *image, struct boot_params *params, @@ -274,13 +274,11 @@ setup_boot_parameters(struct kimage *image, struct boot_params *params, efi_setup_data_offset); #endif -#ifdef CONFIG_IMA_KEXEC /* Setup IMA log buffer state */ setup_ima_state(image, params, params_load_addr, efi_setup_data_offset + sizeof(struct setup_data) + sizeof(struct efi_setup_data)); -#endif /* Setup EDD info */ memcpy(params->eddbuf, boot_params.eddbuf, > + unsigned long params_load_addr, > + unsigned int ima_setup_data_offset) > +{ > + struct setup_data *sd = (void *)params + ima_setup_data_offset; > + struct ima_setup_data *ima = (void *)sd + sizeof(struct setup_data); > + unsigned long setup_data_phys; The tip-tree preferred ordering of variable declarations at the beginning of a function is reverse fir tree order:: struct long_struct_name *descriptive_name; unsigned long foo, bar; unsigned int tmp; int ret; The above is faster to parse than the reverse ordering:: int ret; unsigned int tmp; unsigned long foo, bar; struct long_struct_name *descriptive_name; And even more so than random ordering:: unsigned long foo, bar; int ret; struct long_struct_name *descriptive_name; unsigned int tmp; > + > + if (!image->ima_buffer_size) > + return; > + > + sd->type = SETUP_IMA; > + sd->len = sizeof(*ima); > + > + ima->addr = image->ima_buffer_addr; > + ima->size = image->ima_buffer_size; > + > + /* Add setup data */ > + setup_data_phys = params_load_addr + ima_setup_data_offset; > + sd->next = params->hdr.setup_data; > + params->hdr.setup_data = setup_data_phys; > +} > +#endif /* CONFIG_IMA_KEXEC */ > + > static int > setup_boot_parameters(struct kimage *image, struct boot_params *params, > unsigned long params_load_addr, > @@ -247,6 +273,15 @@ setup_boot_parameters(struct kimage *image, struct boot_params *params, > setup_efi_state(params, params_load_addr, efi_map_offset, efi_map_sz, > efi_setup_data_offset); > #endif > + > +#ifdef CONFIG_IMA_KEXEC > + /* Setup IMA log buffer state */ > + setup_ima_state(image, params, params_load_addr, > + efi_setup_data_offset + > + sizeof(struct setup_data) + > + sizeof(struct efi_setup_data)); > +#endif > + > /* Setup EDD info */ > memcpy(params->eddbuf, boot_params.eddbuf, > EDDMAXNR * sizeof(struct edd_info)); > @@ -401,7 +436,9 @@ static void *bzImage64_load(struct kimage *image, char *kernel, > params_cmdline_sz = ALIGN(params_cmdline_sz, 16); > kbuf.bufsz = params_cmdline_sz + ALIGN(efi_map_sz, 16) + > sizeof(struct setup_data) + > - sizeof(struct efi_setup_data); > + sizeof(struct efi_setup_data) + > + sizeof(struct setup_data) + > + sizeof(struct ima_setup_data); Just because the EFI thing did it unconditionally, regardless of CONFIG_EFI, you don't have to copy that sloppiness: unsigned long ima_buf_sz = 0; ... if (IS_ENABLED(CONFIG_IMA_EXEC)) ima_buf_sz = ... kbuf.bufsz = ... + ima_buf_sz); > diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c > index c95b9ac5a457..8b0e7725f918 100644 > --- a/arch/x86/kernel/setup.c > +++ b/arch/x86/kernel/setup.c > @@ -11,6 +11,7 @@ > #include <linux/dma-map-ops.h> > #include <linux/dmi.h> > #include <linux/efi.h> > +#include <linux/ima.h> > #include <linux/init_ohci1394_dma.h> > #include <linux/initrd.h> > #include <linux/iscsi_ibft.h> > @@ -335,6 +336,28 @@ static void __init reserve_initrd(void) > } > #endif /* CONFIG_BLK_DEV_INITRD */ > > +#ifdef CONFIG_IMA_KEXEC > +static void __init add_early_ima_buffer(u64 phys_addr) > +{ > + struct ima_setup_data *data; > + > + data = early_memremap(phys_addr + sizeof(struct setup_data), > + sizeof(*data)); > + if (!data) { > + pr_warn("setup: failed to memremap ima_setup_data entry\n"); > + return; > + } > + memblock_reserve(data->addr, data->size); > + ima_set_kexec_buffer(data->addr, data->size); > + early_memunmap(data, sizeof(*data)); > +} > +#else > +static void __init add_early_ima_buffer(u64 phys_addr) > +{ > + pr_warn("Passed IMA kexec data, but CONFIG_IMA_KEXEC not set. Ignoring.\n"); > +} > +#endif ditto: diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 9324c30755c5..32403d693bf3 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -336,9 +336,9 @@ static void __init reserve_initrd(void) } #endif /* CONFIG_BLK_DEV_INITRD */ -#ifdef CONFIG_IMA_KEXEC static void __init add_early_ima_buffer(u64 phys_addr) { +#ifdef CONFIG_IMA_KEXEC struct ima_setup_data *data; data = early_memremap(phys_addr + sizeof(struct setup_data), @@ -350,13 +350,10 @@ static void __init add_early_ima_buffer(u64 phys_addr) memblock_reserve(data->addr, data->size); ima_set_kexec_buffer(data->addr, data->size); early_memunmap(data, sizeof(*data)); -} #else -static void __init add_early_ima_buffer(u64 phys_addr) -{ pr_warn("Passed IMA kexec data, but CONFIG_IMA_KEXEC not set. Ignoring.\n"); -} #endif +} static void __init parse_setup_data(void) { > diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c > index 13753136f03f..419c50cfe6b9 100644 > --- a/security/integrity/ima/ima_kexec.c > +++ b/security/integrity/ima/ima_kexec.c > @@ -10,6 +10,7 @@ > #include <linux/seq_file.h> > #include <linux/vmalloc.h> > #include <linux/kexec.h> > +#include <linux/memblock.h> > #include <linux/of.h> > #include <linux/ima.h> > #include "ima.h" > @@ -134,10 +135,66 @@ void ima_add_kexec_buffer(struct kimage *image) > } > #endif /* IMA_KEXEC */ > > +#ifndef CONFIG_OF > +static phys_addr_t ima_early_kexec_buffer_phys; > +static size_t ima_early_kexec_buffer_size; > + > +void __init ima_set_kexec_buffer(phys_addr_t phys_addr, size_t size) > +{ > + if (size == 0) > + return; > + > + ima_early_kexec_buffer_phys = phys_addr; > + ima_early_kexec_buffer_size = size; > +} > + > +int __init ima_free_kexec_buffer(void) WARNING: modpost: vmlinux.o(.text+0xe4e785): Section mismatch in reference from the function ima_free_kexec_buffer() to the function .meminit.text:memblock_phys_free() The function ima_free_kexec_buffer() references the function __meminit memblock_phys_free(). This is often because ima_free_kexec_buffer lacks a __meminit annotation or the annotation of memblock_phys_free is wrong. Thx.
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index b0142e01002e..bde4959d9bdc 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -2017,6 +2017,7 @@ config KEXEC_FILE bool "kexec file based system call" select KEXEC_CORE select BUILD_BIN2C + select HAVE_IMA_KEXEC if IMA depends on X86_64 depends on CRYPTO=y depends on CRYPTO_SHA256=y diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h index b25d3f82c2f3..2f7b138a9388 100644 --- a/arch/x86/include/uapi/asm/bootparam.h +++ b/arch/x86/include/uapi/asm/bootparam.h @@ -10,6 +10,7 @@ #define SETUP_EFI 4 #define SETUP_APPLE_PROPERTIES 5 #define SETUP_JAILHOUSE 6 +#define SETUP_IMA 7 #define SETUP_INDIRECT (1<<31) @@ -171,6 +172,14 @@ struct jailhouse_setup_data { } __attribute__((packed)) v2; } __attribute__((packed)); +/* + * IMA buffer setup data information from the previous kernel during kexec + */ +struct ima_setup_data { + __u64 addr; + __u64 size; +} __attribute__((packed)); + /* The so-called "zeropage" */ struct boot_params { struct screen_info screen_info; /* 0x000 */ diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index f267205f2d5a..9dac24680ff8 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -1017,10 +1017,10 @@ void __init e820__reserve_setup_data(void) e820__range_update(pa_data, sizeof(*data)+data->len, E820_TYPE_RAM, E820_TYPE_RESERVED_KERN); /* - * SETUP_EFI is supplied by kexec and does not need to be - * reserved. + * SETUP_EFI and SETUP_IMA are supplied by kexec and do not need + * to be reserved. */ - if (data->type != SETUP_EFI) + if (data->type != SETUP_EFI && data->type != SETUP_IMA) e820__range_update_kexec(pa_data, sizeof(*data) + data->len, E820_TYPE_RAM, E820_TYPE_RESERVED_KERN); diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c index 170d0fd68b1f..cdc73e081585 100644 --- a/arch/x86/kernel/kexec-bzimage64.c +++ b/arch/x86/kernel/kexec-bzimage64.c @@ -186,6 +186,32 @@ setup_efi_state(struct boot_params *params, unsigned long params_load_addr, } #endif /* CONFIG_EFI */ +#ifdef CONFIG_IMA_KEXEC +static void +setup_ima_state(const struct kimage *image, struct boot_params *params, + unsigned long params_load_addr, + unsigned int ima_setup_data_offset) +{ + struct setup_data *sd = (void *)params + ima_setup_data_offset; + struct ima_setup_data *ima = (void *)sd + sizeof(struct setup_data); + unsigned long setup_data_phys; + + if (!image->ima_buffer_size) + return; + + sd->type = SETUP_IMA; + sd->len = sizeof(*ima); + + ima->addr = image->ima_buffer_addr; + ima->size = image->ima_buffer_size; + + /* Add setup data */ + setup_data_phys = params_load_addr + ima_setup_data_offset; + sd->next = params->hdr.setup_data; + params->hdr.setup_data = setup_data_phys; +} +#endif /* CONFIG_IMA_KEXEC */ + static int setup_boot_parameters(struct kimage *image, struct boot_params *params, unsigned long params_load_addr, @@ -247,6 +273,15 @@ setup_boot_parameters(struct kimage *image, struct boot_params *params, setup_efi_state(params, params_load_addr, efi_map_offset, efi_map_sz, efi_setup_data_offset); #endif + +#ifdef CONFIG_IMA_KEXEC + /* Setup IMA log buffer state */ + setup_ima_state(image, params, params_load_addr, + efi_setup_data_offset + + sizeof(struct setup_data) + + sizeof(struct efi_setup_data)); +#endif + /* Setup EDD info */ memcpy(params->eddbuf, boot_params.eddbuf, EDDMAXNR * sizeof(struct edd_info)); @@ -401,7 +436,9 @@ static void *bzImage64_load(struct kimage *image, char *kernel, params_cmdline_sz = ALIGN(params_cmdline_sz, 16); kbuf.bufsz = params_cmdline_sz + ALIGN(efi_map_sz, 16) + sizeof(struct setup_data) + - sizeof(struct efi_setup_data); + sizeof(struct efi_setup_data) + + sizeof(struct setup_data) + + sizeof(struct ima_setup_data); params = kzalloc(kbuf.bufsz, GFP_KERNEL); if (!params) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index c95b9ac5a457..8b0e7725f918 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -11,6 +11,7 @@ #include <linux/dma-map-ops.h> #include <linux/dmi.h> #include <linux/efi.h> +#include <linux/ima.h> #include <linux/init_ohci1394_dma.h> #include <linux/initrd.h> #include <linux/iscsi_ibft.h> @@ -335,6 +336,28 @@ static void __init reserve_initrd(void) } #endif /* CONFIG_BLK_DEV_INITRD */ +#ifdef CONFIG_IMA_KEXEC +static void __init add_early_ima_buffer(u64 phys_addr) +{ + struct ima_setup_data *data; + + data = early_memremap(phys_addr + sizeof(struct setup_data), + sizeof(*data)); + if (!data) { + pr_warn("setup: failed to memremap ima_setup_data entry\n"); + return; + } + memblock_reserve(data->addr, data->size); + ima_set_kexec_buffer(data->addr, data->size); + early_memunmap(data, sizeof(*data)); +} +#else +static void __init add_early_ima_buffer(u64 phys_addr) +{ + pr_warn("Passed IMA kexec data, but CONFIG_IMA_KEXEC not set. Ignoring.\n"); +} +#endif + static void __init parse_setup_data(void) { struct setup_data *data; @@ -360,6 +383,9 @@ static void __init parse_setup_data(void) case SETUP_EFI: parse_efi_setup(pa_data, data_len); break; + case SETUP_IMA: + add_early_ima_buffer(pa_data); + break; default: break; } diff --git a/include/linux/ima.h b/include/linux/ima.h index 426b1744215e..f58aed7acad4 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -48,6 +48,7 @@ static inline void ima_appraise_parse_cmdline(void) {} #ifdef CONFIG_IMA_KEXEC extern void ima_add_kexec_buffer(struct kimage *image); +extern void ima_set_kexec_buffer(phys_addr_t phys_addr, size_t size); #endif #else diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c index 13753136f03f..419c50cfe6b9 100644 --- a/security/integrity/ima/ima_kexec.c +++ b/security/integrity/ima/ima_kexec.c @@ -10,6 +10,7 @@ #include <linux/seq_file.h> #include <linux/vmalloc.h> #include <linux/kexec.h> +#include <linux/memblock.h> #include <linux/of.h> #include <linux/ima.h> #include "ima.h" @@ -134,10 +135,66 @@ void ima_add_kexec_buffer(struct kimage *image) } #endif /* IMA_KEXEC */ +#ifndef CONFIG_OF +static phys_addr_t ima_early_kexec_buffer_phys; +static size_t ima_early_kexec_buffer_size; + +void __init ima_set_kexec_buffer(phys_addr_t phys_addr, size_t size) +{ + if (size == 0) + return; + + ima_early_kexec_buffer_phys = phys_addr; + ima_early_kexec_buffer_size = size; +} + +int __init ima_free_kexec_buffer(void) +{ + int rc; + + if (!IS_ENABLED(CONFIG_HAVE_IMA_KEXEC)) + return -ENOTSUPP; + + if (ima_early_kexec_buffer_size == 0) + return -ENOENT; + + rc = memblock_phys_free(ima_early_kexec_buffer_phys, + ima_early_kexec_buffer_size); + if (rc) + return rc; + + ima_early_kexec_buffer_phys = 0; + ima_early_kexec_buffer_size = 0; + + return 0; +} + +int __init ima_get_kexec_buffer(void **addr, size_t *size) +{ + if (!IS_ENABLED(CONFIG_HAVE_IMA_KEXEC)) + return -ENOTSUPP; + + if (ima_early_kexec_buffer_size == 0) + return -ENOENT; + + *addr = __va(ima_early_kexec_buffer_phys); + *size = ima_early_kexec_buffer_size; + + return 0; +} + +#else + +void __init ima_set_kexec_buffer(phys_addr_t phys_addr, size_t size) +{ + pr_warn("CONFIG_OF enabled, ignoring call to set buffer details.\n"); +} +#endif /* CONFIG_OF */ + /* * Restore the measurement list from the previous kernel. */ -void ima_load_kexec_buffer(void) +void __init ima_load_kexec_buffer(void) { void *kexec_buffer = NULL; size_t kexec_buffer_size = 0;
On kexec file load Integrity Measurement Architecture (IMA) subsystem may verify the IMA signature of the kernel and initramfs, and measure it. The command line parameters passed to the kernel in the kexec call may also be measured by IMA. A remote attestation service can verify a TPM quote based on the TPM event log, the IMA measurement list, and the TPM PCR data. This can be achieved only if the IMA measurement log is carried over from the current kernel to the next kernel across the kexec call. powerpc and ARM64 both achieve this using device tree with a "linux,ima-kexec-buffer" node. x86 platforms generally don't make use of device tree, so the IMA infrastructure is extended to allow non device tree platforms to provide a log buffer. x86 then passes the IMA buffer to the new kernel via the setup_data mechanism. Signed-off-by: Jonathan McDowell <noodles@fb.com> --- v2: - Fix operation with EFI systems --- arch/x86/Kconfig | 1 + arch/x86/include/uapi/asm/bootparam.h | 9 ++++ arch/x86/kernel/e820.c | 6 +-- arch/x86/kernel/kexec-bzimage64.c | 39 +++++++++++++++++- arch/x86/kernel/setup.c | 26 ++++++++++++ include/linux/ima.h | 1 + security/integrity/ima/ima_kexec.c | 59 ++++++++++++++++++++++++++- 7 files changed, 136 insertions(+), 5 deletions(-)