Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1427328 > unrolled thread

[PATCH 0/6] kexec_file: Add buffer hand-over for the next kernel

Started byThiago Jung Bauermann <bauerman@linux.vnet.ibm.com>
First post2016-06-21 07:50 +0200
Last post2016-06-22 18:40 +0200
Articles 6 — 3 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH 0/6] kexec_file: Add buffer hand-over for the next kernel Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com> - 2016-06-21 07:50 +0200
    [PATCH 3/6] kexec_file: Allow skipping checksum calculation for some segments. Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com> - 2016-06-21 08:00 +0200
    [PATCH 1/6] kexec_file: Add buffer hand-over support for the next kernel Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com> - 2016-06-21 09:00 +0200
    Re: [PATCH 0/6] kexec_file: Add buffer hand-over for the next kernel Dave Young <dyoung@redhat.com> - 2016-06-22 03:30 +0200
      Re: [PATCH 0/6] kexec_file: Add buffer hand-over for the next kernel Mimi Zohar <zohar@linux.vnet.ibm.com> - 2016-06-22 15:30 +0200
      Re: [PATCH 0/6] kexec_file: Add buffer hand-over for the next kernel Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com> - 2016-06-22 18:40 +0200

#1427328 — [PATCH 0/6] kexec_file: Add buffer hand-over for the next kernel

FromThiago Jung Bauermann <bauerman@linux.vnet.ibm.com>
Date2016-06-21 07:50 +0200
Subject[PATCH 0/6] kexec_file: Add buffer hand-over for the next kernel
Message-ID<rMiZb-7y9-3@gated-at.bofh.it>
Hello,

This patch series implements a mechanism which allows the kernel to pass on
a buffer to the kernel that will be kexec'd. This buffer is passed as a
segment which is added to the kimage when it is being prepared by
kexec_file_load.

How the second kernel is informed of this buffer is architecture-specific.
On PowerPC, this is done via the device tree, by checking the properties
/chosen/linux,kexec-handover-buffer-start and
/chosen/linux,kexec-handover-buffer-end, which is analogous to how the
kernel finds the initrd.

This feature was implemented because the Integrity Measurement Architecture
subsystem needs to preserve its measurement list accross the kexec reboot.
This is so that IMA can implement trusted boot support on the OpenPower
platform, because on such systems an intermediary Linux instance running as
part of the firmware is used to boot the target operating system via kexec.
Using this mechanism, IMA on this intermediary instance can hand over to the
target OS the measurements of the components that were used to boot it.

Because there could be additional measurement events between the
kexec_file_load call and the actual reboot, IMA needs a way to update the
buffer with those additional events before rebooting. One can minimize
the interval between the kexec_file_load and the reboot syscalls, but as
small as it can be, there is always the possibility that the measurement
list will be out of date at the time of reboot.

To address this issue, this patch series also introduces kexec_update_segment,
which allows a reboot notifier to change the contents of the image segment
during the reboot process.

There's one patch which makes kimage_load_normal_segment and
kexec_update_segment share code. It's not much code that they can share
though, so I'm not sure if it's worth including this patch.

The last patch is not intended to be merged, it just demonstrates how this
feature can be used.

This series applies on top of v2 of the "kexec_file_load implementation
for PowerPC" patch series at:

http://lists.infradead.org/pipermail/kexec/2016-June/016078.html

Thiago Jung Bauermann (6):
  kexec_file: Add buffer hand-over support for the next kernel
  powerpc: kexec_file: Add buffer hand-over support for the next kernel
  kexec_file: Allow skipping checksum calculation for some segments.
  kexec_file: Add mechanism to update kexec segments.
  kexec: Share logic to copy segment page contents.
  IMA: Demonstration code for kexec buffer passing.

 arch/powerpc/include/asm/kexec.h       |   9 ++
 arch/powerpc/kernel/kexec_elf_64.c     |  50 +++++++-
 arch/powerpc/kernel/machine_kexec_64.c |  64 ++++++++++
 arch/x86/kernel/crash.c                |   4 +-
 arch/x86/kernel/kexec-bzimage64.c      |   6 +-
 include/linux/ima.h                    |  11 ++
 include/linux/kexec.h                  |  47 +++++++-
 kernel/kexec_core.c                    | 205 ++++++++++++++++++++++++++-------
 kernel/kexec_file.c                    | 102 ++++++++++++++--
 security/integrity/ima/ima.h           |   5 +
 security/integrity/ima/ima_init.c      |  26 +++++
 security/integrity/ima/ima_template.c  |  79 +++++++++++++
 12 files changed, 547 insertions(+), 61 deletions(-)

-- 
1.9.1

[toc] | [next] | [standalone]


#1427330 — [PATCH 3/6] kexec_file: Allow skipping checksum calculation for some segments.

FromThiago Jung Bauermann <bauerman@linux.vnet.ibm.com>
Date2016-06-21 08:00 +0200
Subject[PATCH 3/6] kexec_file: Allow skipping checksum calculation for some segments.
Message-ID<rMmT7-1HS-5@gated-at.bofh.it>
In reply to#1427328
Adds checksum argument to kexec_add_buffer specifying whether the given
segment should be part of the checksum calculation.

The next patch will add a way to update segments after a kimage is loaded.
Segments that will be updated in this way should not be checksummed,
otherwise they will cause the purgatory checksum verification to fail
when the machine is rebooted.

As a bonus, we don't need to special-case the purgatory segment anymore
to avoid checksumming it.

Adjust call sites for the new argument.

Signed-off-by: Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com>
---
 arch/powerpc/kernel/kexec_elf_64.c |  6 +++---
 arch/x86/kernel/crash.c            |  4 ++--
 arch/x86/kernel/kexec-bzimage64.c  |  6 +++---
 include/linux/kexec.h              |  7 +++++--
 kernel/kexec_file.c                | 22 +++++++++++-----------
 5 files changed, 24 insertions(+), 21 deletions(-)

diff --git a/arch/powerpc/kernel/kexec_elf_64.c b/arch/powerpc/kernel/kexec_elf_64.c
index 5d2b7036fee7..abbad484d7b2 100644
--- a/arch/powerpc/kernel/kexec_elf_64.c
+++ b/arch/powerpc/kernel/kexec_elf_64.c
@@ -311,7 +311,7 @@ static int elf_exec_load(struct kimage *image, struct elfhdr *ehdr,
 				       (char *) elf_info->buffer + phdr->p_offset,
 				       size, phdr->p_memsz, phdr->p_align,
 				       phdr->p_paddr + base, ppc64_rma_size,
-				       false, &load_addr);
+				       false, true, &load_addr);
 		if (ret)
 			goto out;
 
@@ -487,7 +487,7 @@ void *elf64_load(struct kimage *image, char *kernel_buf,
 	if (initrd != NULL) {
 		ret = kexec_add_buffer(image, initrd, initrd_len, initrd_len,
 				       PAGE_SIZE, 0, ppc64_rma_size, false,
-				       &initrd_load_addr);
+				       true, &initrd_load_addr);
 		if (ret)
 			goto out;
 
@@ -564,7 +564,7 @@ void *elf64_load(struct kimage *image, char *kernel_buf,
 	fdt_pack(fdt);
 
 	ret = kexec_add_buffer(image, fdt, fdt_size, fdt_size, PAGE_SIZE, 0,
-			       ppc64_rma_size, true, &fdt_load_addr);
+			       ppc64_rma_size, true, true, &fdt_load_addr);
 	if (ret)
 		goto out;
 
diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c
index 9ef978d69c22..c8b16f2ca321 100644
--- a/arch/x86/kernel/crash.c
+++ b/arch/x86/kernel/crash.c
@@ -643,7 +643,7 @@ int crash_load_segments(struct kimage *image)
 		 */
 		ret = kexec_add_buffer(image, (char *)&crash_zero_bytes,
 				       sizeof(crash_zero_bytes), src_sz,
-				       PAGE_SIZE, 0, -1, 0,
+				       PAGE_SIZE, 0, -1, false, true,
 				       &image->arch.backup_load_addr);
 		if (ret)
 			return ret;
@@ -660,7 +660,7 @@ int crash_load_segments(struct kimage *image)
 	image->arch.elf_headers_sz = elf_sz;
 
 	ret = kexec_add_buffer(image, (char *)elf_addr, elf_sz, elf_sz,
-			ELF_CORE_HEADER_ALIGN, 0, -1, 0,
+			ELF_CORE_HEADER_ALIGN, 0, -1, false, true,
 			&image->arch.elf_load_addr);
 	if (ret) {
 		vfree((void *)image->arch.elf_headers);
diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c
index f2356bda2b05..f9016be44da6 100644
--- a/arch/x86/kernel/kexec-bzimage64.c
+++ b/arch/x86/kernel/kexec-bzimage64.c
@@ -420,7 +420,7 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
 
 	ret = kexec_add_buffer(image, (char *)params, params_misc_sz,
 			       params_misc_sz, 16, MIN_BOOTPARAM_ADDR,
-			       ULONG_MAX, 1, &bootparam_load_addr);
+			       ULONG_MAX, true, true, &bootparam_load_addr);
 	if (ret)
 		goto out_free_params;
 	pr_debug("Loaded boot_param, command line and misc at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
@@ -434,7 +434,7 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
 
 	ret = kexec_add_buffer(image, kernel_buf,
 			       kernel_bufsz, kernel_memsz, kernel_align,
-			       MIN_KERNEL_LOAD_ADDR, ULONG_MAX, 1,
+			       MIN_KERNEL_LOAD_ADDR, ULONG_MAX, true, true,
 			       &kernel_load_addr);
 	if (ret)
 		goto out_free_params;
@@ -446,7 +446,7 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
 	if (initrd) {
 		ret = kexec_add_buffer(image, initrd, initrd_len, initrd_len,
 				       PAGE_SIZE, MIN_INITRD_LOAD_ADDR,
-				       ULONG_MAX, 1, &initrd_load_addr);
+				       ULONG_MAX, true, true, &initrd_load_addr);
 		if (ret)
 			goto out_free_params;
 
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index 72db95c623b3..131b1fc7820e 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -98,6 +98,9 @@ struct kexec_segment {
 	size_t bufsz;
 	unsigned long mem;
 	size_t memsz;
+
+	/* Whether this segment is part of the checksum calculation. */
+	bool do_checksum;
 };
 
 #ifdef CONFIG_COMPAT
@@ -217,7 +220,7 @@ int kexec_locate_mem_hole(struct kimage *image, unsigned long size,
 extern int kexec_add_buffer(struct kimage *image, char *buffer,
 			    unsigned long bufsz, unsigned long memsz,
 			    unsigned long buf_align, unsigned long buf_min,
-			    unsigned long buf_max, bool top_down,
+			    unsigned long buf_max, bool top_down, bool checksum,
 			    unsigned long *load_addr);
 extern struct page *kimage_alloc_control_pages(struct kimage *image,
 						unsigned int order);
@@ -334,7 +337,7 @@ int kexec_add_handover_buffer(struct kimage *image, void *buffer,
 			      unsigned long bufsz, unsigned long memsz,
 			      unsigned long buf_align, unsigned long buf_min,
 			      unsigned long buf_max, bool top_down,
-			      unsigned long *load_addr);
+			      bool checksum, unsigned long *load_addr);
 int __weak kexec_get_handover_buffer(void **addr, unsigned long *size);
 int __weak kexec_free_handover_buffer(void);
 #else
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index d6ba702654f5..3aa829a78f50 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -146,6 +146,7 @@ int __weak arch_kexec_add_handover_buffer(struct kimage *image,
  * @buf_min:	Minimum address where buffer can be placed.
  * @buf_max:	Maximum address where buffer can be placed.
  * @top_down:	Find the highest available memory position for the buffer?
+ * @checksum:	Should this buffer checksum be verified by the purgatory?
  * @load_addr:	On successful return, set to the physical memory address of the
  * 		buffer in the next kernel.
  *
@@ -157,7 +158,7 @@ int kexec_add_handover_buffer(struct kimage *image, void *buffer,
 			      unsigned long bufsz, unsigned long memsz,
 			      unsigned long buf_align, unsigned long buf_min,
 			      unsigned long buf_max, bool top_down,
-			      unsigned long *load_addr)
+			      bool checksum, unsigned long *load_addr)
 {
 	int ret;
 
@@ -165,7 +166,7 @@ int kexec_add_handover_buffer(struct kimage *image, void *buffer,
 		return -ENOTSUPP;
 
 	ret = kexec_add_buffer(image, buffer, bufsz, memsz, buf_align, buf_min,
-			       buf_max, top_down, load_addr);
+			       buf_max, top_down, checksum, load_addr);
 	if (ret)
 		return ret;
 
@@ -590,7 +591,7 @@ int kexec_locate_mem_hole(struct kimage *image, unsigned long size,
 int kexec_add_buffer(struct kimage *image, char *buffer, unsigned long bufsz,
 		     unsigned long memsz, unsigned long buf_align,
 		     unsigned long buf_min, unsigned long buf_max,
-		     bool top_down, unsigned long *load_addr)
+		     bool top_down, bool checksum, unsigned long *load_addr)
 {
 
 	struct kexec_segment *ksegment;
@@ -630,6 +631,7 @@ int kexec_add_buffer(struct kimage *image, char *buffer, unsigned long bufsz,
 	ksegment->bufsz = bufsz;
 	ksegment->mem = addr;
 	ksegment->memsz = size;
+	ksegment->do_checksum = checksum;
 	image->nr_segments++;
 	*load_addr = ksegment->mem;
 	return 0;
@@ -645,7 +647,6 @@ static int kexec_calculate_store_digests(struct kimage *image)
 	char *digest;
 	void *zero_buf;
 	struct kexec_sha_region *sha_regions;
-	struct purgatory_info *pi = &image->purgatory_info;
 
 	zero_buf = __va(page_to_pfn(ZERO_PAGE(0)) << PAGE_SHIFT);
 	zero_buf_sz = PAGE_SIZE;
@@ -685,11 +686,7 @@ static int kexec_calculate_store_digests(struct kimage *image)
 		struct kexec_segment *ksegment;
 
 		ksegment = &image->segment[i];
-		/*
-		 * Skip purgatory as it will be modified once we put digest
-		 * info in purgatory.
-		 */
-		if (ksegment->kbuf == pi->purgatory_buf)
+		if (!ksegment->do_checksum)
 			continue;
 
 		ret = crypto_shash_update(desc, ksegment->kbuf,
@@ -866,9 +863,12 @@ static int __kexec_load_purgatory(struct kimage *image, unsigned long min,
 	if (buf_align < bss_align)
 		buf_align = bss_align;
 
-	/* Add buffer to segment list */
+	/*
+	 * Add buffer to segment list. Don't checksum the segment as
+	 * it will be modified once we put digest info in purgatory.
+	 */
 	ret = kexec_add_buffer(image, purgatory_buf, buf_sz, memsz,
-				buf_align, min, max, top_down,
+				buf_align, min, max, top_down, false,
 				&pi->purgatory_load_addr);
 	if (ret)
 		goto out;
-- 
1.9.1

[toc] | [prev] | [next] | [standalone]


#1427360 — [PATCH 1/6] kexec_file: Add buffer hand-over support for the next kernel

FromThiago Jung Bauermann <bauerman@linux.vnet.ibm.com>
Date2016-06-21 09:00 +0200
Subject[PATCH 1/6] kexec_file: Add buffer hand-over support for the next kernel
Message-ID<rMnPb-2gH-13@gated-at.bofh.it>
In reply to#1427328
The buffer hand-over mechanism allows the currently running kernel to pass
data to kernel that will be kexec'd via a kexec segment. The second kernel
can check whether the previous kernel sent data and retrieve it.

This is the architecture-independent part of the feature.

Signed-off-by: Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com>
---
 include/linux/kexec.h | 40 ++++++++++++++++++++++++++
 kernel/kexec_file.c   | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 119 insertions(+)

diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index a08cd986b5a1..72db95c623b3 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -325,6 +325,46 @@ int __weak arch_kexec_walk_mem(unsigned int image_type, unsigned long start,
 void arch_kexec_protect_crashkres(void);
 void arch_kexec_unprotect_crashkres(void);
 
+#ifdef CONFIG_KEXEC_FILE
+bool __weak kexec_can_hand_over_buffer(void);
+int __weak arch_kexec_add_handover_buffer(struct kimage *image,
+					  unsigned long load_addr,
+					  unsigned long size);
+int kexec_add_handover_buffer(struct kimage *image, void *buffer,
+			      unsigned long bufsz, unsigned long memsz,
+			      unsigned long buf_align, unsigned long buf_min,
+			      unsigned long buf_max, bool top_down,
+			      unsigned long *load_addr);
+int __weak kexec_get_handover_buffer(void **addr, unsigned long *size);
+int __weak kexec_free_handover_buffer(void);
+#else
+static inline bool kexec_can_hand_over_buffer(void)
+{
+	return false;
+}
+
+static inline int kexec_add_handover_buffer(struct kimage *image, void *buffer,
+					    unsigned long bufsz,
+					    unsigned long memsz,
+					    unsigned long buf_align,
+					    unsigned long buf_min,
+					    unsigned long buf_max,
+					    bool top_down, bool checksum,
+					    unsigned long *load_addr)
+{
+	return -ENOTSUPP;
+}
+
+static inline int kexec_get_handover_buffer(void **addr, unsigned long *size)
+{
+	return -ENOTSUPP;
+}
+
+static inline int kexec_free_handover_buffer(void)
+{
+	return -ENOTSUPP;
+}
+#endif /* CONFIG_KEXEC_FILE */
 #else /* !CONFIG_KEXEC_CORE */
 struct pt_regs;
 struct task_struct;
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 3e494261d32a..d6ba702654f5 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -113,6 +113,85 @@ void kimage_file_post_load_cleanup(struct kimage *image)
 	image->image_loader_data = NULL;
 }
 
+/**
+ * kexec_can_hand_over_buffer - can we pass data to the kexec'd kernel?
+ */
+bool __weak kexec_can_hand_over_buffer(void)
+{
+	return false;
+}
+
+/**
+ * arch_kexec_add_handover_buffer - do arch-specific steps to handover buffer
+ *
+ * Architectures should use this function to pass on the handover buffer
+ * information to the next kernel.
+ *
+ * Return: 0 on success, negative errno on error.
+ */
+int __weak arch_kexec_add_handover_buffer(struct kimage *image,
+					  unsigned long load_addr,
+					  unsigned long size)
+{
+	return -ENOTSUPP;
+}
+
+/**
+ * kexec_add_handover_buffer - add buffer to be used by the next kernel
+ * @image:	kexec image to add buffer to.
+ * @buffer:	Contents of the handover buffer.
+ * @bufsz:	@buffer size.
+ * @memsz:	Handover buffer size in memory.
+ * @buf_align:	Buffer alignment restriction.
+ * @buf_min:	Minimum address where buffer can be placed.
+ * @buf_max:	Maximum address where buffer can be placed.
+ * @top_down:	Find the highest available memory position for the buffer?
+ * @load_addr:	On successful return, set to the physical memory address of the
+ * 		buffer in the next kernel.
+ *
+ * This function assumes that kexec_mutex is held.
+ *
+ * Return: 0 on success, negative errno on error.
+ */
+int kexec_add_handover_buffer(struct kimage *image, void *buffer,
+			      unsigned long bufsz, unsigned long memsz,
+			      unsigned long buf_align, unsigned long buf_min,
+			      unsigned long buf_max, bool top_down,
+			      unsigned long *load_addr)
+{
+	int ret;
+
+	if (!kexec_can_hand_over_buffer())
+		return -ENOTSUPP;
+
+	ret = kexec_add_buffer(image, buffer, bufsz, memsz, buf_align, buf_min,
+			       buf_max, top_down, load_addr);
+	if (ret)
+		return ret;
+
+	return arch_kexec_add_handover_buffer(image, *load_addr, memsz);
+}
+
+/**
+ * kexec_get_handover_buffer - get the handover 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 __weak kexec_get_handover_buffer(void **addr, unsigned long *size)
+{
+	return -ENOTSUPP;
+}
+
+/**
+ * kexec_free_handover_buffer - free memory used by the handover buffer
+ */
+int __weak kexec_free_handover_buffer(void)
+{
+	return -ENOTSUPP;
+}
+
 /*
  * In file mode list of segments is prepared by kernel. Copy relevant
  * data from user space, do error checking, prepare segment list
-- 
1.9.1

[toc] | [prev] | [next] | [standalone]


#1428314

FromDave Young <dyoung@redhat.com>
Date2016-06-22 03:30 +0200
Message-ID<rMF9n-57L-1@gated-at.bofh.it>
In reply to#1427328
On 06/20/16 at 10:44pm, Thiago Jung Bauermann wrote:
> Hello,
> 
> This patch series implements a mechanism which allows the kernel to pass on
> a buffer to the kernel that will be kexec'd. This buffer is passed as a
> segment which is added to the kimage when it is being prepared by
> kexec_file_load.
> 
> How the second kernel is informed of this buffer is architecture-specific.
> On PowerPC, this is done via the device tree, by checking the properties
> /chosen/linux,kexec-handover-buffer-start and
> /chosen/linux,kexec-handover-buffer-end, which is analogous to how the
> kernel finds the initrd.
> 
> This feature was implemented because the Integrity Measurement Architecture
> subsystem needs to preserve its measurement list accross the kexec reboot.
> This is so that IMA can implement trusted boot support on the OpenPower
> platform, because on such systems an intermediary Linux instance running as
> part of the firmware is used to boot the target operating system via kexec.
> Using this mechanism, IMA on this intermediary instance can hand over to the
> target OS the measurements of the components that were used to boot it.

We have CONFIG_KEXEC_VERIFY_SIG, why not verifying the kernel to be
loaded instead?  I feel IMA should rebuild its measurement instead of
passing it to another kernel. Kexec reboot is also a reboot. If we have
to preserve something get from firmware we can do it, but other than
that I think it sounds not a good idea.

> 
> Because there could be additional measurement events between the
> kexec_file_load call and the actual reboot, IMA needs a way to update the
> buffer with those additional events before rebooting. One can minimize
> the interval between the kexec_file_load and the reboot syscalls, but as
> small as it can be, there is always the possibility that the measurement
> list will be out of date at the time of reboot.
> 
> To address this issue, this patch series also introduces kexec_update_segment,
> which allows a reboot notifier to change the contents of the image segment
> during the reboot process.
> 
> There's one patch which makes kimage_load_normal_segment and
> kexec_update_segment share code. It's not much code that they can share
> though, so I'm not sure if it's worth including this patch.
> 
> The last patch is not intended to be merged, it just demonstrates how this
> feature can be used.
> 
> This series applies on top of v2 of the "kexec_file_load implementation
> for PowerPC" patch series at:

The kexec_file_load patches should be addressed first, no?

> 
> http://lists.infradead.org/pipermail/kexec/2016-June/016078.html
> 
> Thiago Jung Bauermann (6):
>   kexec_file: Add buffer hand-over support for the next kernel
>   powerpc: kexec_file: Add buffer hand-over support for the next kernel
>   kexec_file: Allow skipping checksum calculation for some segments.
>   kexec_file: Add mechanism to update kexec segments.
>   kexec: Share logic to copy segment page contents.
>   IMA: Demonstration code for kexec buffer passing.
> 
>  arch/powerpc/include/asm/kexec.h       |   9 ++
>  arch/powerpc/kernel/kexec_elf_64.c     |  50 +++++++-
>  arch/powerpc/kernel/machine_kexec_64.c |  64 ++++++++++
>  arch/x86/kernel/crash.c                |   4 +-
>  arch/x86/kernel/kexec-bzimage64.c      |   6 +-
>  include/linux/ima.h                    |  11 ++
>  include/linux/kexec.h                  |  47 +++++++-
>  kernel/kexec_core.c                    | 205 ++++++++++++++++++++++++++-------
>  kernel/kexec_file.c                    | 102 ++++++++++++++--
>  security/integrity/ima/ima.h           |   5 +
>  security/integrity/ima/ima_init.c      |  26 +++++
>  security/integrity/ima/ima_template.c  |  79 +++++++++++++
>  12 files changed, 547 insertions(+), 61 deletions(-)
> 
> -- 
> 1.9.1
> 

Thanks
Dave

[toc] | [prev] | [next] | [standalone]


#1428787

FromMimi Zohar <zohar@linux.vnet.ibm.com>
Date2016-06-22 15:30 +0200
Message-ID<rMQoa-41d-17@gated-at.bofh.it>
In reply to#1428314
Hi Dave,

On Wed, 2016-06-22 at 09:20 +0800, Dave Young wrote:
> On 06/20/16 at 10:44pm, Thiago Jung Bauermann wrote:
> > Hello,
> > 
> > This patch series implements a mechanism which allows the kernel to pass on
> > a buffer to the kernel that will be kexec'd. This buffer is passed as a
> > segment which is added to the kimage when it is being prepared by
> > kexec_file_load.
> > 
> > How the second kernel is informed of this buffer is architecture-specific.
> > On PowerPC, this is done via the device tree, by checking the properties
> > /chosen/linux,kexec-handover-buffer-start and
> > /chosen/linux,kexec-handover-buffer-end, which is analogous to how the
> > kernel finds the initrd.
> > 
> > This feature was implemented because the Integrity Measurement Architecture
> > subsystem needs to preserve its measurement list accross the kexec reboot.
> > This is so that IMA can implement trusted boot support on the OpenPower
> > platform, because on such systems an intermediary Linux instance running as
> > part of the firmware is used to boot the target operating system via kexec.
> > Using this mechanism, IMA on this intermediary instance can hand over to the
> > target OS the measurements of the components that were used to boot it.
> 
> We have CONFIG_KEXEC_VERIFY_SIG, why not verifying the kernel to be
> loaded instead?  I feel IMA should rebuild its measurement instead of
> passing it to another kernel. Kexec reboot is also a reboot. If we have
> to preserve something get from firmware we can do it, but other than
> that I think it sounds not a good idea.

The signature verification is needed for secure boot.  Carrying the IMA
measurement list across kexec is needed for trusted boot.  In this case,
the boot loader is Linux, which needs to carry the measurements, stored
in memory, across kexec to the target system.

The kernel_read_file_from_fd() calls the pre and post security
kernel_read hooks.  These hooks can verify file signatures, store
measurements in the IMA measurement list and extend the TPM.  To enable
both measuring and appraising (signature verification) of the kernel
image and the initramfs, include the following rules in the IMA policy:

measure func=KEXEC_KERNEL_CHECK
appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig
#
measure func=KEXEC_INITRAMFS_CHECK
appraise func=KEXEC_INITRAMFS_CHECK appraise_type=imasig

Thiago's path set provides the means for carrying the trusted boot
measurements across kexec.

Mimi

[toc] | [prev] | [next] | [standalone]


#1428964

FromThiago Jung Bauermann <bauerman@linux.vnet.ibm.com>
Date2016-06-22 18:40 +0200
Message-ID<rMTm2-5QR-7@gated-at.bofh.it>
In reply to#1428314
Hello Dave,

Thanks for your considerations on this feature.

Am Mittwoch, 22 Juni 2016, 09:20:46 schrieb Dave Young:
> On 06/20/16 at 10:44pm, Thiago Jung Bauermann wrote:
> > This feature was implemented because the Integrity Measurement
> > Architecture subsystem needs to preserve its measurement list accross
> > the kexec reboot. This is so that IMA can implement trusted boot
> > support on the OpenPower platform, because on such systems an
> > intermediary Linux instance running as part of the firmware is used to
> > boot the target operating system via kexec. Using this mechanism, IMA
> > on this intermediary instance can hand over to the target OS the
> > measurements of the components that were used to boot it.
> We have CONFIG_KEXEC_VERIFY_SIG, why not verifying the kernel to be
> loaded instead?  I feel IMA should rebuild its measurement instead of
> passing it to another kernel.

In trusted boot, each stage of the boot process (firmware, boot loader, 
target OS) measures the following stage before passing control to it, and 
records that measurement cumulatively so that the target OS can look back 
and see measurements of all the components that were used from the earliest 
boot stages until the target OS was loaded (including a measurement of the 
OS itself).

If IMA had to rebuild the measurements, it would mean that one stage is 
measuring itself. This violates this design property of the trusted boot 
process (i.e., each boot stage is measured by the one before it) so it's not 
really an option. It has to receive the measurements from the boot stage 
that ran before it.

> Kexec reboot is also a reboot. If we have
> to preserve something get from firmware we can do it, but other than
> that I think it sounds not a good idea.

OpenPower uses a Linux kernel (and initrd with a tiny system image) as a 
boot loader, so in this platform a kexec reboot is not a reboot. It is part 
of the boot process itself as the way of passing control from the boot 
loader to the target OS.

> > This series applies on top of v2 of the "kexec_file_load implementation
> 
> > for PowerPC" patch series at:
> The kexec_file_load patches should be addressed first, no?

Yes. I posted this series for two reasons:

1. The PowerPC maintainer asked why he would want to have the 
kexec_file_load system call, and this feature is one of the reasons. I 
wanted to show that it is not an hypothetical feature, there is a 
functioning implementation.

2. I want to start discussion on this feature with the community early, so 
that I can incorporate feedback and have it ready to be accepted (or closer 
to ready at least) by the time the kexec_file_load patches are accepted.

[]'s
Thiago Jung Bauermann
IBM Linux Technology Center

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web