kexec.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v13 0/9] ima: kexec: measure events between kexec load and execute
@ 2025-04-21 22:25 steven chen
  2025-04-21 22:25 ` [PATCH v13 1/9] ima: rename variable the seq_file "file" to "ima_kexec_file" steven chen
                   ` (9 more replies)
  0 siblings, 10 replies; 23+ messages in thread
From: steven chen @ 2025-04-21 22:25 UTC (permalink / raw)
  To: zohar, stefanb, roberto.sassu, roberto.sassu, eric.snowberg,
	ebiederm, paul, code, bauermann, linux-integrity, kexec,
	linux-security-module, linux-kernel
  Cc: madvenka, nramas, James.Bottomley, bhe, vgoyal, dyoung

From: Steven Chen <chenste@linux.microsoft.com>

The current kernel behavior is IMA measurements snapshot is taken at
kexec 'load' and not at kexec 'execute'.  IMA log is then carried
over to the new kernel after kexec 'execute'.

Currently, the kernel behavior during kexec load is to fetch the IMA
measurements log from TPM PCRs and store it in a buffer. When a kexec 
reboot is triggered, this stored log buffer is carried over to the second
kernel. However, the time gap between kexec load and kexec reboot can be
very long. During this time window, new events extended into TPM PCRs miss
the chance to be carried over to the second kernel. This results in 
mismatch between TPM PCR quotes and the actual IMA measurements list after 
kexec soft reboot, which in turn results in remote attestation failure.

To solve this problem - 
 - allocate the necessary buffer at kexec 'load' time,
 - populate the buffer with the IMA measurements at kexec 'execute' time, 
 - and measure two new IMA events 'kexec_load' and 'kexec_execute' as
   critical data to help detect missing events after kexec soft reboot.

The solution details include:
 - refactoring the existing code to allocate a buffer to hold IMA
   measurements at kexec 'load', and dump the measurements at kexec
   'execute'

 - kexec functionality for mapping the segments from the current kernel
   to the subsequent one, 

 - necessary changes to the kexec_file_load syscall, enabling it to call
   the ima functions,

 - registering a reboot notifier which gets called during kexec 'execute',

 - introducing a new Kconfig option to configure the extra memory to be
   allocated for passing IMA log from the current Kernel to the next,
   
 - introducing two new events to be measured by IMA during kexec, to
   help diagnose if the IMA log was copied fully or partially, from the
   current Kernel to the next, 

 - excluding IMA segment while calculating and storing digest in function
   kexec_calculate_store_digests(), since IMA segment can be modified
   after the digest is computed during kexec 'load'.  This will ensure
   that the segment is not added to the 'purgatory_sha_regions', and thus
   not verified by verify_sha256_digest().

The changes proposed in this series ensure the integrity of the IMA
measurements is preserved across kexec soft reboots, thus significantly
improving the security of the kernel post kexec soft reboots.

There were previous attempts to fix this issue [1], [2], [3].  But they
were not merged into the mainline kernel.

We took inspiration from the past work [1] and [2] while working on this
patch series.

V4 of this series is available here[6] for reference.

V5 of this series is available here[7] for reference.

V6 of this series is available here[8] for reference.

V7 of this series is available here[9] for reference.

V8 of this series is available here[10] for reference.

V9 of this series is available here[11] for reference.

V10 of this series is available here[12] for reference.

V11 of this series is available here[13] for reference.

V12 of this series is available here[14] for reference.

References:
-----------

[1] [PATHC v2 5/9] ima: on soft reboot, save the measurement list
https://lore.kernel.org/lkml/1472596811-9596-6-git-send-email-zohar@linux.vnet.ibm.com/

[2] PATCH v2 4/6] kexec_file: Add mechanism to update kexec segments.
https://lkml.org/lkml/2016/8/16/577

[3] [PATCH 1/6] kexec_file: Add buffer hand-over support
https://lore.kernel.org/linuxppc-dev/1466473476-10104-6-git-send-email-bauerman@linux.vnet.ibm.com/T/

[4] [PATCH v2 0/7] ima: kexec: measure events between kexec load and execute
https://lore.kernel.org/all/20231005182602.634615-1-tusharsu@linux.microsoft.com/

[5] [PATCH v3 0/7] ima: kexec: measure events between kexec load and execute
https://lore.kernel.org/all/20231216010729.2904751-1-tusharsu@linux.microsoft.com/

[6] [PATCH v4 0/7] ima: kexec: measure events between kexec load and execute
https://lore.kernel.org/all/20240122183804.3293904-1-tusharsu@linux.microsoft.com/

[7] [PATCH v5 0/8] ima: kexec: measure events between kexec load and execute
https://lore.kernel.org/all/20240214153827.1087657-1-tusharsu@linux.microsoft.com/

[8] [PATCH v6 0/7] ima: kexec: measure events between kexec load and execute
https://lore.kernel.org/all/20250124225547.22684-1-chenste@linux.microsoft.com/

[9] [PATCH v7 0/7] ima: kexec: measure events between kexec load and execute
https://lore.kernel.org/all/20250203232033.64123-1-chenste@linux.microsoft.com/

[10] [PATCH v8 0/7] ima: kexec: measure events between kexec load and execute
https://lore.kernel.org/all/20250218225502.747963-1-chenste@linux.microsoft.com/

[11] [PATCH v9 0/7] ima: kexec: measure events between kexec load and execute
https://lore.kernel.org/all/20250304190351.96975-1-chenste@linux.microsoft.com/

[12] [PATCH v10 0/8] ima: kexec: measure events between kexec load and execute
https://lore.kernel.org/all/20250318010448.954-1-chenste@linux.microsoft.com/

[13] [PATCH v11 0/9] ima: kexec: measure events between kexec load and execute
https://lore.kernel.org/all/20250402124725.5601-1-chenste@linux.microsoft.com/

[14] [PATCH v12 0/9] ima: kexec: measure events between kexec load and execute
https://lore.kernel.org/all/20250416021028.1403-1-chenste@linux.microsoft.com/

Change Log v13:
 - Incorporated feedback from the community (Mimi Zohar and Baoquan He) on
   v12 of this series[14].
 - Verified all the patches are bisect-safe by booting into each
   patch and verifying multiple kexec 'load' operations work,
   and also verifying kexec soft reboot works, and IMA log gets
   carried over for each patch.
 - Updated patch descriptions as necessary.

Change Log v12:
 - Incorporated feedback from the community (Mimi Zohar and Baoquan He) on
   v11 of this series[13].
 - Add range to config IMA_KEXEC_EXTRA_MEMORY_KB 
 - Verified all the patches are bisect-safe by booting into each
   patch and verifying multiple kexec 'load' operations work,
   and also verifying kexec soft reboot works, and IMA log gets
   carried over for each patch.
 - Updated patch descriptions as necessary.

Change Log v11:
 - Incorporated feedback from the community (Mimi Zohar and Baoquan He) on
   v10 of this series[12].
 - [PATCH V10 2/8] was splited into two [PATCH V11 2/9] and [PATCH V11 7/9]. 
   Per Mimi comment on [PATCH V10 2/8].
 - Don't call ima_kexec_post_load() on KEXEC_FILE_ON_CRASH
 - Verified all the patches are bisect-safe by booting into each
   patch and verifying multiple kexec 'load' operations work,
   and also verifying kexec soft reboot works, and IMA log gets
   carried over for each patch.
 - Updated patch descriptions as necessary.

Change Log v10:
 - Incorporated feedback from the community (Mimi Zohar, Baoquan He, and 
   kernel test robot) on v9 of this series[11].
 - [PATCH V9 1/7] was splited into two [PATCH V10 1/8] and [PATCH V10 2/8]. 
   Per Mimi comment on [PATCH V9 1/7].
 - Verified all the patches are bisect-safe by booting into each
   patch and verifying multiple kexec 'load' operations work,
   and also verifying kexec soft reboot works, and IMA log gets
   carried over for each patch.

Change Log v9:
 - Incorporated feedback from the community (Stefan Berger, Mimi Zohar, 
   and kernel test robot) on v8 of this series[10].
 - Rebased the patch series to mainline 6.14.0-rc3.
 - Verified all the patches are bisect-safe by booting into each
   patch and verifying multiple kexec 'load' operations work,
   and also verifying kexec soft reboot works, and IMA log gets
   carried over for each patch.

Change Log v8:
 - Incorporated feedback from the community (Stefan Berger, Mimi Zohar) 
   on v7 of this series[9].
 - Rebased the patch series to mainline 6.14.0-rc1.
 - Verified all the patches are bisect-safe by booting into each
   patch and verifying multiple kexec 'load' operations work,
   and also verifying kexec soft reboot works, and IMA log gets
   carried over for each patch.

Change Log v7:
 - Incorporated feedback from the community (Stefan Berger, Tyler Hicks) 
   on v6 of this series[8].
 - Verified all the patches are bisect-safe by booting into each
   patch and verifying multiple kexec 'load' operations work,
   and also verifying kexec soft reboot works, and IMA log gets
   carried over for each patch.

Change Log v6:
 - Incorporated feedback from the community (Stefan Berger, Mimi Zohar,
   and Petr Tesařík) on v5 of this series[7].
 - Rebased the patch series to mainline 6.12.0.
 - Verified all the patches are bisect-safe by booting into each
   patch and verifying multiple kexec 'load' operations work,
   and also verifying kexec soft reboot works, and IMA log gets
   carried over for each patch.
 - Compared the memory size allocated with memory size of the entire 
   measurement record. If there is not enough memory, it will copy as many
   IMA measurement records as possible, and this situation will result
   in a failure of remote attestation.
 - [PATCH V5 6/8] was removed. Per petr comment on [PATCH V5 6/8], during
   the handover, other CPUs are taken offline (look for
   migrate_to_reboot_cpu() in kernel/kexec_core.c) and even the reboot CPU
   will be sufficiently shut down as not to be able to add any more
   measurements.

Change Log v5:
 - Incorporated feedback from the community (Stefan Berger and
   Mimi Zohar) on v4 of this series[6].
 - Rebased the patch series to mainline 6.8.0-rc1.
 - Verified all the patches are bisect-safe by booting into each
   patch and verifying multiple kexec 'load' operations work,
   and also verifying kexec soft reboot works, and IMA log gets
   carried over for each patch.
 - Divided the patch #4 in the v4 of the series[6] into two separate
   patches. One to setup the infrastructure/stub functions to prepare
   the IMA log copy from Kexec 'load' to 'execute', and another one
   to actually copy the log.
 - Updated the config description for IMA_KEXEC_EXTRA_MEMORY_KB
   to remove unnecessary references related to backwards compatibility.
 - Fixed a typo in log message/removed an extra line etc.
 - Updated patch descriptions as necessary.

Change Log v4:
 - Incorporated feedback from the community (Stefan Berger and
   Mimi Zohar) on v3 of this series[5].
 - Rearranged patches so that they remain bisect-safe i.e. the
   system can go through kexec soft reboot, and IMA log is carried
   over after each patch.
 - Verified all the patches are bisect-safe by booting into each
   patch and verifying kexec soft reboot works, and IMA log gets
   carried over.
 - Suspend-resume measurements is now a separate patch (patch #5)
   and all the relevant code is part of the same patch.
 - Excluding IMA segment from segment digest verification is now a
   separate patch. (patch #3).
 - Registering reboot notifier and functions related to move ima 
   log copy from kexec load to execute are now part of the same
   patch (patch #4) to protect bisect-safeness of the series.
 - Updated the title of patch #6 as per the feedback.
 - The default value of kexec extra memory for IMA measurements
   is set to half the PAGESIZE to maintain backwards compatibility.
 - Added number of IMA measurement records as part of 'kexec_load' 
   and 'kexec_execute' IMA critical data events.
 - Updated patch descriptions as necessary.

Change Log v3:
 - Incorporated feedback from the community (Stefan Berger and
   Mimi Zohar) on v2 of this series[4].
 - Renamed functions and removed extraneous checks and code comments.
 - Updated patch descriptions and titles as necessary.
 - Updated kexec_calculate_store_digests() in patch 2/7 to exclude ima
   segment from calculating and storing digest.
 - Updated patch 3/7 to use kmalloc_array instead of kmalloc and freed
   memory early to avoid potential memory leak.
 - Updated patch 6/7 to change Kconfig option IMA_KEXEC_EXTRA_PAGES to
   IMA_KEXEC_EXTRA_MEMORY_KB to allocate the memory in kb rather than
   in number of pages.
 - Optimized patch 7/7 not to free and alloc memory if the buffer size
   hasn't changed during multiple kexec 'load' operations.
 - Fixed a bug in patch 7/7 to measure multiple 'kexec_load' events even
   if buffer size hasn't changed.
 - Verified the patches are bisect-safe by compiling and booting into
   each patch individually.


Change Log v2:
 - Incorporated feedback from the community on v1 series.
 - Refactored the existing ima_dump_measurement_list to move buffer
   allocation functionality to ima_alloc_kexec_buf() function.
 - Introduced a new Kconfig option to configure the memory.
 - Updated the logic to copy the IMA log only in case of kexec soft 
   reboot, and not on kexec crash.
 - Updated the logic to copy as many IMA events as possible in case of
   memory constraint, rather than just bailing out.
 - Introduced two new events to be measured by IMA during kexec, to
   help diagnose if the IMA log was copied fully or partially from the
   current Kernel to the next.
 - Refactored patches to ensure no warnings during individual patch
   compilation.
 - Used virt_to_page instead of phys_to_page.
 - Updated patch descriptions as necessary.


Steven Chen (9):
  ima: rename variable the seq_file "file" to "ima_kexec_file"
  ima: define and call ima_alloc_kexec_file_buf()
  kexec: define functions to map and unmap segments
  ima: kexec: skip IMA segment validation after kexec soft reboot
  ima: kexec: define functions to copy IMA log at soft boot
  ima: kexec: move IMA log copy from kexec load to execute
  ima: verify if the segment size has changed
  ima: make the kexec extra memory configurable
  ima: measure kexec load and exec events as critical data

 include/linux/ima.h                |   3 +
 include/linux/kexec.h              |   9 ++
 kernel/kexec_core.c                |  54 ++++++++
 kernel/kexec_file.c                |  33 ++++-
 security/integrity/ima/Kconfig     |  11 ++
 security/integrity/ima/ima.h       |   6 +
 security/integrity/ima/ima_kexec.c | 193 ++++++++++++++++++++++++-----
 security/integrity/ima/ima_queue.c |   5 +
 8 files changed, 280 insertions(+), 34 deletions(-)

-- 
2.43.0



^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH v13 1/9] ima: rename variable the seq_file "file" to "ima_kexec_file"
  2025-04-21 22:25 [PATCH v13 0/9] ima: kexec: measure events between kexec load and execute steven chen
@ 2025-04-21 22:25 ` steven chen
  2025-04-21 22:25 ` [PATCH v13 2/9] ima: define and call ima_alloc_kexec_file_buf() steven chen
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 23+ messages in thread
From: steven chen @ 2025-04-21 22:25 UTC (permalink / raw)
  To: zohar, stefanb, roberto.sassu, roberto.sassu, eric.snowberg,
	ebiederm, paul, code, bauermann, linux-integrity, kexec,
	linux-security-module, linux-kernel
  Cc: madvenka, nramas, James.Bottomley, bhe, vgoyal, dyoung

From: Steven Chen <chenste@linux.microsoft.com>

Before making the function local seq_file "file" variable file static
global, rename it to "ima_kexec_file".

Signed-off-by: Steven Chen <chenste@linux.microsoft.com>
Acked-by: Baoquan He <bhe@redhat.com>
---
 security/integrity/ima/ima_kexec.c | 31 +++++++++++++++---------------
 1 file changed, 16 insertions(+), 15 deletions(-)

diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
index 9d45f4d26f73..650beb74346c 100644
--- a/security/integrity/ima/ima_kexec.c
+++ b/security/integrity/ima/ima_kexec.c
@@ -18,30 +18,30 @@
 static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
 				     unsigned long segment_size)
 {
+	struct seq_file ima_kexec_file;
 	struct ima_queue_entry *qe;
-	struct seq_file file;
 	struct ima_kexec_hdr khdr;
 	int ret = 0;
 
 	/* segment size can't change between kexec load and execute */
-	file.buf = vmalloc(segment_size);
-	if (!file.buf) {
+	ima_kexec_file.buf = vmalloc(segment_size);
+	if (!ima_kexec_file.buf) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
-	file.file = NULL;
-	file.size = segment_size;
-	file.read_pos = 0;
-	file.count = sizeof(khdr);	/* reserved space */
+	ima_kexec_file.file = NULL;
+	ima_kexec_file.size = segment_size;
+	ima_kexec_file.read_pos = 0;
+	ima_kexec_file.count = sizeof(khdr);	/* reserved space */
 
 	memset(&khdr, 0, sizeof(khdr));
 	khdr.version = 1;
 	/* This is an append-only list, no need to hold the RCU read lock */
 	list_for_each_entry_rcu(qe, &ima_measurements, later, true) {
-		if (file.count < file.size) {
+		if (ima_kexec_file.count < ima_kexec_file.size) {
 			khdr.count++;
-			ima_measurements_show(&file, qe);
+			ima_measurements_show(&ima_kexec_file, qe);
 		} else {
 			ret = -EINVAL;
 			break;
@@ -55,23 +55,24 @@ static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
 	 * fill in reserved space with some buffer details
 	 * (eg. version, buffer size, number of measurements)
 	 */
-	khdr.buffer_size = file.count;
+	khdr.buffer_size = ima_kexec_file.count;
 	if (ima_canonical_fmt) {
 		khdr.version = cpu_to_le16(khdr.version);
 		khdr.count = cpu_to_le64(khdr.count);
 		khdr.buffer_size = cpu_to_le64(khdr.buffer_size);
 	}
-	memcpy(file.buf, &khdr, sizeof(khdr));
+	memcpy(ima_kexec_file.buf, &khdr, sizeof(khdr));
 
 	print_hex_dump_debug("ima dump: ", DUMP_PREFIX_NONE, 16, 1,
-			     file.buf, file.count < 100 ? file.count : 100,
+			     ima_kexec_file.buf, ima_kexec_file.count < 100 ?
+			     ima_kexec_file.count : 100,
 			     true);
 
-	*buffer_size = file.count;
-	*buffer = file.buf;
+	*buffer_size = ima_kexec_file.count;
+	*buffer = ima_kexec_file.buf;
 out:
 	if (ret == -EINVAL)
-		vfree(file.buf);
+		vfree(ima_kexec_file.buf);
 	return ret;
 }
 
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v13 2/9] ima: define and call ima_alloc_kexec_file_buf()
  2025-04-21 22:25 [PATCH v13 0/9] ima: kexec: measure events between kexec load and execute steven chen
  2025-04-21 22:25 ` [PATCH v13 1/9] ima: rename variable the seq_file "file" to "ima_kexec_file" steven chen
@ 2025-04-21 22:25 ` steven chen
  2025-04-29 18:30   ` Stefan Berger
  2025-04-21 22:25 ` [PATCH v13 3/9] kexec: define functions to map and unmap segments steven chen
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 23+ messages in thread
From: steven chen @ 2025-04-21 22:25 UTC (permalink / raw)
  To: zohar, stefanb, roberto.sassu, roberto.sassu, eric.snowberg,
	ebiederm, paul, code, bauermann, linux-integrity, kexec,
	linux-security-module, linux-kernel
  Cc: madvenka, nramas, James.Bottomley, bhe, vgoyal, dyoung

From: Steven Chen <chenste@linux.microsoft.com>

In the current implementation, the ima_dump_measurement_list() API is 
called during the kexec "load" phase, where a buffer is allocated and 
the measurement records are copied. Due to this, new events added after
kexec load but before kexec execute are not carried over to the new kernel
during kexec operation

Carrying the IMA measurement list across kexec requires allocating a
buffer and copying the measurement records.  Separate allocating the
buffer and copying the measurement records into separate functions in
order to allocate the buffer at kexec 'load' and copy the measurements
at kexec 'execute'.

After moving the vfree() here at this stage in the patch set, the IMA
measurement list fails to verify when doing two consecutive "kexec -s -l"
with/without a "kexec -s -u" in between.  Only after "ima: kexec: move 
IMA log copy from kexec load to execute" the IMA measurement list verifies
properly with the vfree() here.

Co-developed-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
Signed-off-by: Steven Chen <chenste@linux.microsoft.com>
Acked-by: Baoquan He <bhe@redhat.com>
---
 security/integrity/ima/ima_kexec.c | 46 +++++++++++++++++++++++-------
 1 file changed, 35 insertions(+), 11 deletions(-)

diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
index 650beb74346c..b12ac3619b8f 100644
--- a/security/integrity/ima/ima_kexec.c
+++ b/security/integrity/ima/ima_kexec.c
@@ -15,26 +15,46 @@
 #include "ima.h"
 
 #ifdef CONFIG_IMA_KEXEC
+static struct seq_file ima_kexec_file;
+
+static void ima_free_kexec_file_buf(struct seq_file *sf)
+{
+	vfree(sf->buf);
+	sf->buf = NULL;
+	sf->size = 0;
+	sf->read_pos = 0;
+	sf->count = 0;
+}
+
+static int ima_alloc_kexec_file_buf(size_t segment_size)
+{
+	ima_free_kexec_file_buf(&ima_kexec_file);
+
+	/* segment size can't change between kexec load and execute */
+	ima_kexec_file.buf = vmalloc(segment_size);
+	if (!ima_kexec_file.buf)
+		return -ENOMEM;
+
+	ima_kexec_file.size = segment_size;
+	ima_kexec_file.read_pos = 0;
+	ima_kexec_file.count = sizeof(struct ima_kexec_hdr);	/* reserved space */
+
+	return 0;
+}
+
 static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
 				     unsigned long segment_size)
 {
-	struct seq_file ima_kexec_file;
 	struct ima_queue_entry *qe;
 	struct ima_kexec_hdr khdr;
 	int ret = 0;
 
 	/* segment size can't change between kexec load and execute */
-	ima_kexec_file.buf = vmalloc(segment_size);
 	if (!ima_kexec_file.buf) {
-		ret = -ENOMEM;
-		goto out;
+		pr_err("Kexec file buf not allocated\n");
+		return -EINVAL;
 	}
 
-	ima_kexec_file.file = NULL;
-	ima_kexec_file.size = segment_size;
-	ima_kexec_file.read_pos = 0;
-	ima_kexec_file.count = sizeof(khdr);	/* reserved space */
-
 	memset(&khdr, 0, sizeof(khdr));
 	khdr.version = 1;
 	/* This is an append-only list, no need to hold the RCU read lock */
@@ -71,8 +91,6 @@ static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
 	*buffer_size = ima_kexec_file.count;
 	*buffer = ima_kexec_file.buf;
 out:
-	if (ret == -EINVAL)
-		vfree(ima_kexec_file.buf);
 	return ret;
 }
 
@@ -111,6 +129,12 @@ void ima_add_kexec_buffer(struct kimage *image)
 		return;
 	}
 
+	ret = ima_alloc_kexec_file_buf(kexec_segment_size);
+	if (ret < 0) {
+		pr_err("Not enough memory for the kexec measurement buffer.\n");
+		return;
+	}
+
 	ima_dump_measurement_list(&kexec_buffer_size, &kexec_buffer,
 				  kexec_segment_size);
 	if (!kexec_buffer) {
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v13 3/9] kexec: define functions to map and unmap segments
  2025-04-21 22:25 [PATCH v13 0/9] ima: kexec: measure events between kexec load and execute steven chen
  2025-04-21 22:25 ` [PATCH v13 1/9] ima: rename variable the seq_file "file" to "ima_kexec_file" steven chen
  2025-04-21 22:25 ` [PATCH v13 2/9] ima: define and call ima_alloc_kexec_file_buf() steven chen
@ 2025-04-21 22:25 ` steven chen
  2025-04-23  0:29   ` Mimi Zohar
  2025-04-21 22:25 ` [PATCH v13 4/9] ima: kexec: skip IMA segment validation after kexec soft reboot steven chen
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 23+ messages in thread
From: steven chen @ 2025-04-21 22:25 UTC (permalink / raw)
  To: zohar, stefanb, roberto.sassu, roberto.sassu, eric.snowberg,
	ebiederm, paul, code, bauermann, linux-integrity, kexec,
	linux-security-module, linux-kernel
  Cc: madvenka, nramas, James.Bottomley, bhe, vgoyal, dyoung

From: Steven Chen <chenste@linux.microsoft.com>

Implement kimage_map_segment() to enable IMA to map the measurement log 
list to the kimage structure during the kexec 'load' stage. This function
gathers the source pages within the specified address range, and maps them
to a contiguous virtual address range.

This is a preparation for later usage.

Implement kimage_unmap_segment() for unmapping segments using vunmap().

Cc: Eric Biederman <ebiederm@xmission.com>
Cc: Baoquan He <bhe@redhat.com> 
Cc: Vivek Goyal <vgoyal@redhat.com>
Cc: Dave Young <dyoung@redhat.com>
Co-developed-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
Signed-off-by: steven chen <chenste@linux.microsoft.com>
Acked-by: Baoquan He <bhe@redhat.com>
---
 include/linux/kexec.h |  6 +++++
 kernel/kexec_core.c   | 54 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 60 insertions(+)

diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index f0e9f8eda7a3..7d6b12f8b8d0 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -467,13 +467,19 @@ extern bool kexec_file_dbg_print;
 #define kexec_dprintk(fmt, arg...) \
         do { if (kexec_file_dbg_print) pr_info(fmt, ##arg); } while (0)
 
+extern void *kimage_map_segment(struct kimage *image, unsigned long addr, unsigned long size);
+extern void kimage_unmap_segment(void *buffer);
 #else /* !CONFIG_KEXEC_CORE */
 struct pt_regs;
 struct task_struct;
+struct kimage;
 static inline void __crash_kexec(struct pt_regs *regs) { }
 static inline void crash_kexec(struct pt_regs *regs) { }
 static inline int kexec_should_crash(struct task_struct *p) { return 0; }
 static inline int kexec_crash_loaded(void) { return 0; }
+static inline void *kimage_map_segment(struct kimage *image, unsigned long addr, unsigned long size)
+{ return NULL; }
+static inline void kimage_unmap_segment(void *buffer) { }
 #define kexec_in_progress false
 #endif /* CONFIG_KEXEC_CORE */
 
diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
index c0bdc1686154..a5e378e1dc7f 100644
--- a/kernel/kexec_core.c
+++ b/kernel/kexec_core.c
@@ -867,6 +867,60 @@ int kimage_load_segment(struct kimage *image,
 	return result;
 }
 
+void *kimage_map_segment(struct kimage *image,
+			 unsigned long addr, unsigned long size)
+{
+	unsigned long src_page_addr, dest_page_addr = 0;
+	unsigned long eaddr = addr + size;
+	kimage_entry_t *ptr, entry;
+	struct page **src_pages;
+	unsigned int npages;
+	void *vaddr = NULL;
+	int i;
+
+	/*
+	 * Collect the source pages and map them in a contiguous VA range.
+	 */
+	npages = PFN_UP(eaddr) - PFN_DOWN(addr);
+	src_pages = kmalloc_array(npages, sizeof(*src_pages), GFP_KERNEL);
+	if (!src_pages) {
+		pr_err("Could not allocate ima pages array.\n");
+		return NULL;
+	}
+
+	i = 0;
+	for_each_kimage_entry(image, ptr, entry) {
+		if (entry & IND_DESTINATION) {
+			dest_page_addr = entry & PAGE_MASK;
+		} else if (entry & IND_SOURCE) {
+			if (dest_page_addr >= addr && dest_page_addr < eaddr) {
+				src_page_addr = entry & PAGE_MASK;
+				src_pages[i++] =
+					virt_to_page(__va(src_page_addr));
+				if (i == npages)
+					break;
+				dest_page_addr += PAGE_SIZE;
+			}
+		}
+	}
+
+	/* Sanity check. */
+	WARN_ON(i < npages);
+
+	vaddr = vmap(src_pages, npages, VM_MAP, PAGE_KERNEL);
+	kfree(src_pages);
+
+	if (!vaddr)
+		pr_err("Could not map ima buffer.\n");
+
+	return vaddr;
+}
+
+void kimage_unmap_segment(void *segment_buffer)
+{
+	vunmap(segment_buffer);
+}
+
 struct kexec_load_limit {
 	/* Mutex protects the limit count. */
 	struct mutex mutex;
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v13 4/9] ima: kexec: skip IMA segment validation after kexec soft reboot
  2025-04-21 22:25 [PATCH v13 0/9] ima: kexec: measure events between kexec load and execute steven chen
                   ` (2 preceding siblings ...)
  2025-04-21 22:25 ` [PATCH v13 3/9] kexec: define functions to map and unmap segments steven chen
@ 2025-04-21 22:25 ` steven chen
  2025-04-21 22:25 ` [PATCH v13 5/9] ima: kexec: define functions to copy IMA log at soft boot steven chen
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 23+ messages in thread
From: steven chen @ 2025-04-21 22:25 UTC (permalink / raw)
  To: zohar, stefanb, roberto.sassu, roberto.sassu, eric.snowberg,
	ebiederm, paul, code, bauermann, linux-integrity, kexec,
	linux-security-module, linux-kernel
  Cc: madvenka, nramas, James.Bottomley, bhe, vgoyal, dyoung

From: Steven Chen <chenste@linux.microsoft.com>

Currently, the function kexec_calculate_store_digests() calculates and
stores the digest of the segment during the kexec_file_load syscall,
where the  IMA segment is also allocated.

Later, the IMA segment will be updated with the measurement log at the
kexec execute stage when a kexec reboot is initiated. Therefore, the
digests should be updated for the IMA segment in the  normal case. The
problem is that the content of memory segments carried over to the new
kernel during the kexec systemcall can be changed at kexec 'execute'
stage, but the size and the location of the memory segments cannot be
changed at kexec 'execute' stage.

To address this, skip the calculation and storage of the digest for the
IMA segment in kexec_calculate_store_digests() so that it is not added 
to the purgatory_sha_regions.

With this change, the IMA segment is not included in the digest
calculation, storage, and verification.

Cc: Eric Biederman <ebiederm@xmission.com>
Cc: Baoquan He <bhe@redhat.com> 
Cc: Vivek Goyal <vgoyal@redhat.com>
Cc: Dave Young <dyoung@redhat.com>
Co-developed-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
Signed-off-by: Steven Chen <chenste@linux.microsoft.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
Acked-by: Baoquan He <bhe@redhat.com>
---
 include/linux/kexec.h              |  3 +++
 kernel/kexec_file.c                | 22 ++++++++++++++++++++++
 security/integrity/ima/ima_kexec.c |  3 +++
 3 files changed, 28 insertions(+)

diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index 7d6b12f8b8d0..107e726f2ef3 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -362,6 +362,9 @@ struct kimage {
 
 	phys_addr_t ima_buffer_addr;
 	size_t ima_buffer_size;
+
+	unsigned long ima_segment_index;
+	bool is_ima_segment_index_set;
 #endif
 
 	/* Core ELF header buffer */
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 3eedb8c226ad..606132253c79 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -38,6 +38,21 @@ void set_kexec_sig_enforced(void)
 }
 #endif
 
+#ifdef CONFIG_IMA_KEXEC
+static bool check_ima_segment_index(struct kimage *image, int i)
+{
+	if (image->is_ima_segment_index_set && i == image->ima_segment_index)
+		return true;
+	else
+		return false;
+}
+#else
+static bool check_ima_segment_index(struct kimage *image, int i)
+{
+	return false;
+}
+#endif
+
 static int kexec_calculate_store_digests(struct kimage *image);
 
 /* Maximum size in bytes for kernel/initrd files. */
@@ -764,6 +779,13 @@ static int kexec_calculate_store_digests(struct kimage *image)
 		if (ksegment->kbuf == pi->purgatory_buf)
 			continue;
 
+		/*
+		 * Skip the segment if ima_segment_index is set and matches
+		 * the current index
+		 */
+		if (check_ima_segment_index(image, i))
+			continue;
+
 		ret = crypto_shash_update(desc, ksegment->kbuf,
 					  ksegment->bufsz);
 		if (ret)
diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
index b12ac3619b8f..7e0a19c3483f 100644
--- a/security/integrity/ima/ima_kexec.c
+++ b/security/integrity/ima/ima_kexec.c
@@ -145,6 +145,7 @@ void ima_add_kexec_buffer(struct kimage *image)
 	kbuf.buffer = kexec_buffer;
 	kbuf.bufsz = kexec_buffer_size;
 	kbuf.memsz = kexec_segment_size;
+	image->is_ima_segment_index_set = false;
 	ret = kexec_add_buffer(&kbuf);
 	if (ret) {
 		pr_err("Error passing over kexec measurement buffer.\n");
@@ -155,6 +156,8 @@ void ima_add_kexec_buffer(struct kimage *image)
 	image->ima_buffer_addr = kbuf.mem;
 	image->ima_buffer_size = kexec_segment_size;
 	image->ima_buffer = kexec_buffer;
+	image->ima_segment_index = image->nr_segments - 1;
+	image->is_ima_segment_index_set = true;
 
 	kexec_dprintk("kexec measurement buffer for the loaded kernel at 0x%lx.\n",
 		      kbuf.mem);
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v13 5/9] ima: kexec: define functions to copy IMA log at soft boot
  2025-04-21 22:25 [PATCH v13 0/9] ima: kexec: measure events between kexec load and execute steven chen
                   ` (3 preceding siblings ...)
  2025-04-21 22:25 ` [PATCH v13 4/9] ima: kexec: skip IMA segment validation after kexec soft reboot steven chen
@ 2025-04-21 22:25 ` steven chen
  2025-04-29 16:50   ` Stefan Berger
  2025-04-21 22:25 ` [PATCH v13 6/9] ima: kexec: move IMA log copy from kexec load to execute steven chen
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 23+ messages in thread
From: steven chen @ 2025-04-21 22:25 UTC (permalink / raw)
  To: zohar, stefanb, roberto.sassu, roberto.sassu, eric.snowberg,
	ebiederm, paul, code, bauermann, linux-integrity, kexec,
	linux-security-module, linux-kernel
  Cc: madvenka, nramas, James.Bottomley, bhe, vgoyal, dyoung

From: Steven Chen <chenste@linux.microsoft.com>

The IMA log is currently copied to the new kernel during kexec 'load' 
using ima_dump_measurement_list(). However, the log copied at kexec 
'load' may result in loss of IMA measurements that only occurred after
kexec "load'. Setup the needed infrastructure to move the IMA log copy 
from kexec 'load' to 'execute'.

Define a new IMA hook ima_update_kexec_buffer() as a stub function.
It will be used to call ima_dump_measurement_list() during kexec 'execute'.

Implement ima_kexec_post_load() function to be invoked after the new 
Kernel image has been loaded for kexec. ima_kexec_post_load() maps the 
IMA buffer to a segment in the newly loaded Kernel.  It also registers 
the reboot notifier_block to trigger ima_update_kexec_buffer() at 
kexec 'execute'.

Set the priority of register_reboot_notifier to INT_MIN to ensure that the
IMA log copy operation will happen at the end of the operation chain, so 
that all the IMA measurement records extended into the TPM are copied

Co-developed-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
Cc: Eric Biederman <ebiederm@xmission.com>
Cc: Baoquan He <bhe@redhat.com> 
Cc: Vivek Goyal <vgoyal@redhat.com>
Cc: Dave Young <dyoung@redhat.com>
Signed-off-by: Steven Chen <chenste@linux.microsoft.com>
Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
Acked-by: Baoquan He <bhe@redhat.com>
---
 include/linux/ima.h                |  3 ++
 security/integrity/ima/ima_kexec.c | 47 ++++++++++++++++++++++++++++++
 2 files changed, 50 insertions(+)

diff --git a/include/linux/ima.h b/include/linux/ima.h
index 0bae61a15b60..8e29cb4e6a01 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -32,6 +32,9 @@ static inline void ima_appraise_parse_cmdline(void) {}
 
 #ifdef CONFIG_IMA_KEXEC
 extern void ima_add_kexec_buffer(struct kimage *image);
+extern void ima_kexec_post_load(struct kimage *image);
+#else
+static inline void ima_kexec_post_load(struct kimage *image) {}
 #endif
 
 #else
diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
index 7e0a19c3483f..e79f6caf895b 100644
--- a/security/integrity/ima/ima_kexec.c
+++ b/security/integrity/ima/ima_kexec.c
@@ -12,10 +12,14 @@
 #include <linux/kexec.h>
 #include <linux/of.h>
 #include <linux/ima.h>
+#include <linux/reboot.h>
+#include <asm/page.h>
 #include "ima.h"
 
 #ifdef CONFIG_IMA_KEXEC
+static bool ima_kexec_update_registered;
 static struct seq_file ima_kexec_file;
+static void *ima_kexec_buffer;
 
 static void ima_free_kexec_file_buf(struct seq_file *sf)
 {
@@ -162,6 +166,49 @@ void ima_add_kexec_buffer(struct kimage *image)
 	kexec_dprintk("kexec measurement buffer for the loaded kernel at 0x%lx.\n",
 		      kbuf.mem);
 }
+
+/*
+ * Called during kexec execute so that IMA can update the measurement list.
+ */
+static int ima_update_kexec_buffer(struct notifier_block *self,
+				   unsigned long action, void *data)
+{
+	return NOTIFY_OK;
+}
+
+static struct notifier_block update_buffer_nb = {
+	.notifier_call = ima_update_kexec_buffer,
+	.priority = INT_MIN
+};
+
+/*
+ * Create a mapping for the source pages that contain the IMA buffer
+ * so we can update it later.
+ */
+void ima_kexec_post_load(struct kimage *image)
+{
+	if (ima_kexec_buffer) {
+		kimage_unmap_segment(ima_kexec_buffer);
+		ima_kexec_buffer = NULL;
+	}
+
+	if (!image->ima_buffer_addr)
+		return;
+
+	ima_kexec_buffer = kimage_map_segment(image,
+					      image->ima_buffer_addr,
+					      image->ima_buffer_size);
+	if (!ima_kexec_buffer) {
+		pr_err("Could not map measurements buffer.\n");
+		return;
+	}
+
+	if (!ima_kexec_update_registered) {
+		register_reboot_notifier(&update_buffer_nb);
+		ima_kexec_update_registered = true;
+	}
+}
+
 #endif /* IMA_KEXEC */
 
 /*
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v13 6/9] ima: kexec: move IMA log copy from kexec load to execute
  2025-04-21 22:25 [PATCH v13 0/9] ima: kexec: measure events between kexec load and execute steven chen
                   ` (4 preceding siblings ...)
  2025-04-21 22:25 ` [PATCH v13 5/9] ima: kexec: define functions to copy IMA log at soft boot steven chen
@ 2025-04-21 22:25 ` steven chen
  2025-04-21 22:25 ` [PATCH v13 7/9] ima: verify if the segment size has changed steven chen
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 23+ messages in thread
From: steven chen @ 2025-04-21 22:25 UTC (permalink / raw)
  To: zohar, stefanb, roberto.sassu, roberto.sassu, eric.snowberg,
	ebiederm, paul, code, bauermann, linux-integrity, kexec,
	linux-security-module, linux-kernel
  Cc: madvenka, nramas, James.Bottomley, bhe, vgoyal, dyoung

From: Steven Chen <chenste@linux.microsoft.com>

The IMA log is currently copied to the new kernel during kexec 'load' using
ima_dump_measurement_list(). However, the IMA measurement list copied at 
kexec 'load' may result in loss of IMA measurements records that only 
occurred after the kexec 'load'. Move the IMA measurement list log copy 
from kexec 'load' to 'execute'

Make the kexec_segment_size variable a local static variable within the 
file, so it can be accessed during both kexec 'load' and 'execute'.
 
Define kexec_post_load() as a wrapper for calling ima_kexec_post_load() and
machine_kexec_post_load().  Replace the existing direct call to
machine_kexec_post_load() with kexec_post_load().
 
When there is insufficient memory to copy all the measurement logs, copy as
much of the measurement list as possible.

Co-developed-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
Cc: Eric Biederman <ebiederm@xmission.com>
Cc: Baoquan He <bhe@redhat.com> 
Cc: Vivek Goyal <vgoyal@redhat.com>
Cc: Dave Young <dyoung@redhat.com>
Signed-off-by: Steven Chen <chenste@linux.microsoft.com>
---
 kernel/kexec_file.c                | 11 +++++++-
 security/integrity/ima/ima_kexec.c | 43 ++++++++++++++++++++----------
 2 files changed, 39 insertions(+), 15 deletions(-)

diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 606132253c79..b3eb515ca051 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -201,6 +201,15 @@ kimage_validate_signature(struct kimage *image)
 }
 #endif
 
+static int kexec_post_load(struct kimage *image, unsigned long flags)
+{
+#ifdef CONFIG_IMA_KEXEC
+	if (!(flags & KEXEC_FILE_ON_CRASH))
+		ima_kexec_post_load(image);
+#endif
+	return machine_kexec_post_load(image);
+}
+
 /*
  * In file mode list of segments is prepared by kernel. Copy relevant
  * data from user space, do error checking, prepare segment list
@@ -428,7 +437,7 @@ SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd,
 
 	kimage_terminate(image);
 
-	ret = machine_kexec_post_load(image);
+	ret = kexec_post_load(image, flags);
 	if (ret)
 		goto out;
 
diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
index e79f6caf895b..5c3b3e0b2186 100644
--- a/security/integrity/ima/ima_kexec.c
+++ b/security/integrity/ima/ima_kexec.c
@@ -19,6 +19,7 @@
 #ifdef CONFIG_IMA_KEXEC
 static bool ima_kexec_update_registered;
 static struct seq_file ima_kexec_file;
+static size_t kexec_segment_size;
 static void *ima_kexec_buffer;
 
 static void ima_free_kexec_file_buf(struct seq_file *sf)
@@ -72,9 +73,6 @@ static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
 		}
 	}
 
-	if (ret < 0)
-		goto out;
-
 	/*
 	 * fill in reserved space with some buffer details
 	 * (eg. version, buffer size, number of measurements)
@@ -94,7 +92,7 @@ static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
 
 	*buffer_size = ima_kexec_file.count;
 	*buffer = ima_kexec_file.buf;
-out:
+
 	return ret;
 }
 
@@ -112,9 +110,8 @@ void ima_add_kexec_buffer(struct kimage *image)
 	unsigned long binary_runtime_size;
 
 	/* use more understandable variable names than defined in kbuf */
+	size_t kexec_buffer_size = 0;
 	void *kexec_buffer = NULL;
-	size_t kexec_buffer_size;
-	size_t kexec_segment_size;
 	int ret;
 
 	/*
@@ -139,13 +136,6 @@ void ima_add_kexec_buffer(struct kimage *image)
 		return;
 	}
 
-	ima_dump_measurement_list(&kexec_buffer_size, &kexec_buffer,
-				  kexec_segment_size);
-	if (!kexec_buffer) {
-		pr_err("Not enough memory for the kexec measurement buffer.\n");
-		return;
-	}
-
 	kbuf.buffer = kexec_buffer;
 	kbuf.bufsz = kexec_buffer_size;
 	kbuf.memsz = kexec_segment_size;
@@ -173,7 +163,32 @@ void ima_add_kexec_buffer(struct kimage *image)
 static int ima_update_kexec_buffer(struct notifier_block *self,
 				   unsigned long action, void *data)
 {
-	return NOTIFY_OK;
+	size_t buf_size = 0;
+	int ret = NOTIFY_OK;
+	void *buf = NULL;
+
+	if (!kexec_in_progress) {
+		pr_info("No kexec in progress.\n");
+		return ret;
+	}
+
+	if (!ima_kexec_buffer) {
+		pr_err("Kexec buffer not set.\n");
+		return ret;
+	}
+
+	ret = ima_dump_measurement_list(&buf_size, &buf, kexec_segment_size);
+
+	if (ret)
+		pr_err("Dump measurements failed. Error:%d\n", ret);
+
+	if (buf_size != 0)
+		memcpy(ima_kexec_buffer, buf, buf_size);
+
+	kimage_unmap_segment(ima_kexec_buffer);
+	ima_kexec_buffer = NULL;
+
+	return ret;
 }
 
 static struct notifier_block update_buffer_nb = {
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v13 7/9] ima: verify if the segment size has changed
  2025-04-21 22:25 [PATCH v13 0/9] ima: kexec: measure events between kexec load and execute steven chen
                   ` (5 preceding siblings ...)
  2025-04-21 22:25 ` [PATCH v13 6/9] ima: kexec: move IMA log copy from kexec load to execute steven chen
@ 2025-04-21 22:25 ` steven chen
  2025-04-29 18:19   ` Stefan Berger
  2025-04-21 22:25 ` [PATCH v13 8/9] ima: make the kexec extra memory configurable steven chen
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 23+ messages in thread
From: steven chen @ 2025-04-21 22:25 UTC (permalink / raw)
  To: zohar, stefanb, roberto.sassu, roberto.sassu, eric.snowberg,
	ebiederm, paul, code, bauermann, linux-integrity, kexec,
	linux-security-module, linux-kernel
  Cc: madvenka, nramas, James.Bottomley, bhe, vgoyal, dyoung

From: Steven Chen <chenste@linux.microsoft.com>

kexec 'load' may be called multiple times. Free and realloc the buffer
only if the segment_size is changed from the previous kexec 'load' call.

Signed-off-by: Steven Chen <chenste@linux.microsoft.com>
Acked-by: Baoquan He <bhe@redhat.com>
Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
---
 security/integrity/ima/ima_kexec.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
index 5c3b3e0b2186..ed867734ee70 100644
--- a/security/integrity/ima/ima_kexec.c
+++ b/security/integrity/ima/ima_kexec.c
@@ -33,6 +33,14 @@ static void ima_free_kexec_file_buf(struct seq_file *sf)
 
 static int ima_alloc_kexec_file_buf(size_t segment_size)
 {
+	/*
+	 * kexec 'load' may be called multiple times.
+	 * Free and realloc the buffer only if the segment_size is
+	 * changed from the previous kexec 'load' call.
+	 */
+	if (ima_kexec_file.buf && ima_kexec_file.size == segment_size)
+		goto out;
+
 	ima_free_kexec_file_buf(&ima_kexec_file);
 
 	/* segment size can't change between kexec load and execute */
@@ -41,6 +49,8 @@ static int ima_alloc_kexec_file_buf(size_t segment_size)
 		return -ENOMEM;
 
 	ima_kexec_file.size = segment_size;
+
+out:
 	ima_kexec_file.read_pos = 0;
 	ima_kexec_file.count = sizeof(struct ima_kexec_hdr);	/* reserved space */
 
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v13 8/9] ima: make the kexec extra memory configurable
  2025-04-21 22:25 [PATCH v13 0/9] ima: kexec: measure events between kexec load and execute steven chen
                   ` (6 preceding siblings ...)
  2025-04-21 22:25 ` [PATCH v13 7/9] ima: verify if the segment size has changed steven chen
@ 2025-04-21 22:25 ` steven chen
  2025-04-29 19:06   ` Stefan Berger
  2025-04-21 22:25 ` [PATCH v13 9/9] ima: measure kexec load and exec events as critical data steven chen
  2025-04-24 14:37 ` [PATCH v13 0/9] ima: kexec: measure events between kexec load and execute Baoquan He
  9 siblings, 1 reply; 23+ messages in thread
From: steven chen @ 2025-04-21 22:25 UTC (permalink / raw)
  To: zohar, stefanb, roberto.sassu, roberto.sassu, eric.snowberg,
	ebiederm, paul, code, bauermann, linux-integrity, kexec,
	linux-security-module, linux-kernel
  Cc: madvenka, nramas, James.Bottomley, bhe, vgoyal, dyoung

From: Steven Chen <chenste@linux.microsoft.com>

The extra memory allocated for carrying the IMA measurement list across
kexec is hard-coded as half a PAGE.  Make it configurable.

Define a Kconfig option, IMA_KEXEC_EXTRA_MEMORY_KB, to configure the
extra memory (in kb) to be allocated for IMA measurements added during
kexec soft reboot.  Ensure the default value of the option is set such
that extra half a page of memory for additional measurements is allocated
for the additional measurements.

Update ima_add_kexec_buffer() function to allocate memory based on the
Kconfig option value, rather than the currently hard-coded one.

Suggested-by: Stefan Berger <stefanb@linux.ibm.com>
Co-developed-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
Signed-off-by: Steven Chen <chenste@linux.microsoft.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
Acked-by: Baoquan He <bhe@redhat.com>
---
 security/integrity/ima/Kconfig     | 11 +++++++++++
 security/integrity/ima/ima_kexec.c | 16 +++++++++++-----
 2 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index 475c32615006..976e75f9b9ba 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -321,4 +321,15 @@ config IMA_DISABLE_HTABLE
 	help
 	   This option disables htable to allow measurement of duplicate records.
 
+config IMA_KEXEC_EXTRA_MEMORY_KB
+	int "Extra memory for IMA measurements added during kexec soft reboot"
+	range 0 40
+	depends on IMA_KEXEC
+	default 0
+	help
+	  IMA_KEXEC_EXTRA_MEMORY_KB determines the extra memory to be
+	  allocated (in kb) for IMA measurements added during kexec soft reboot.
+	  If set to the default value of 0, an extra half page of memory for those
+	  additional measurements will be allocated.
+
 endif
diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
index ed867734ee70..d1c9d369ba08 100644
--- a/security/integrity/ima/ima_kexec.c
+++ b/security/integrity/ima/ima_kexec.c
@@ -118,6 +118,7 @@ void ima_add_kexec_buffer(struct kimage *image)
 				  .buf_min = 0, .buf_max = ULONG_MAX,
 				  .top_down = true };
 	unsigned long binary_runtime_size;
+	unsigned long extra_memory;
 
 	/* use more understandable variable names than defined in kbuf */
 	size_t kexec_buffer_size = 0;
@@ -125,15 +126,20 @@ void ima_add_kexec_buffer(struct kimage *image)
 	int ret;
 
 	/*
-	 * Reserve an extra half page of memory for additional measurements
-	 * added during the kexec load.
+	 * Reserve extra memory for measurements added during kexec.
 	 */
-	binary_runtime_size = ima_get_binary_runtime_size();
+	if (CONFIG_IMA_KEXEC_EXTRA_MEMORY_KB <= 0)
+		extra_memory = PAGE_SIZE / 2;
+	else
+		extra_memory = CONFIG_IMA_KEXEC_EXTRA_MEMORY_KB * 1024;
+
+	binary_runtime_size = ima_get_binary_runtime_size() + extra_memory;
+
 	if (binary_runtime_size >= ULONG_MAX - PAGE_SIZE)
 		kexec_segment_size = ULONG_MAX;
 	else
-		kexec_segment_size = ALIGN(ima_get_binary_runtime_size() +
-					   PAGE_SIZE / 2, PAGE_SIZE);
+		kexec_segment_size = ALIGN(binary_runtime_size, PAGE_SIZE);
+
 	if ((kexec_segment_size == ULONG_MAX) ||
 	    ((kexec_segment_size >> PAGE_SHIFT) > totalram_pages() / 2)) {
 		pr_err("Binary measurement list too large.\n");
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH v13 9/9] ima: measure kexec load and exec events as critical data
  2025-04-21 22:25 [PATCH v13 0/9] ima: kexec: measure events between kexec load and execute steven chen
                   ` (7 preceding siblings ...)
  2025-04-21 22:25 ` [PATCH v13 8/9] ima: make the kexec extra memory configurable steven chen
@ 2025-04-21 22:25 ` steven chen
  2025-04-29 18:18   ` Stefan Berger
  2025-04-24 14:37 ` [PATCH v13 0/9] ima: kexec: measure events between kexec load and execute Baoquan He
  9 siblings, 1 reply; 23+ messages in thread
From: steven chen @ 2025-04-21 22:25 UTC (permalink / raw)
  To: zohar, stefanb, roberto.sassu, roberto.sassu, eric.snowberg,
	ebiederm, paul, code, bauermann, linux-integrity, kexec,
	linux-security-module, linux-kernel
  Cc: madvenka, nramas, James.Bottomley, bhe, vgoyal, dyoung

From: Steven Chen <chenste@linux.microsoft.com>

The amount of memory allocated at kexec load, even with the extra memory
allocated, might not be large enough for the entire measurement list.  The
indeterminate interval between kexec 'load' and 'execute' could exacerbate
this problem.

Define two new IMA events, 'kexec_load' and 'kexec_execute', to be 
measured as critical data at kexec 'load' and 'execute' respectively.
Report the allocated kexec segment size, IMA binary log size and the
runtime measurements count as part of those events.

These events, and the values reported through them, serve as markers in
the IMA log to verify the IMA events are captured during kexec soft
reboot.  The presence of a 'kexec_load' event in between the last two
'boot_aggregate' events in the IMA log implies this is a kexec soft
reboot, and not a cold-boot. And the absence of 'kexec_execute' event
after kexec soft reboot implies missing events in that window which
results in inconsistency with TPM PCR quotes, necessitating a cold boot
for a successful remote attestation.

These critical data events are displayed as hex encoded ascii in the
ascii_runtime_measurement_list.  Verifying the critical data hash requires 
calculating the hash of the decoded ascii string.  

For example, to verify the 'kexec_load' data hash:

sudo cat /sys/kernel/security/integrity/ima/ascii_runtime_measurements 
| grep  kexec_load | cut -d' ' -f 6 | xxd -r -p | sha256sum


To verify the 'kexec_execute' data hash:

sudo cat /sys/kernel/security/integrity/ima/ascii_runtime_measurements 
| grep kexec_execute | cut -d' ' -f 6 | xxd -r -p | sha256sum

Co-developed-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
Signed-off-by: Steven Chen <chenste@linux.microsoft.com>
Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
Acked-by: Baoquan He <bhe@redhat.com>
---
 security/integrity/ima/ima.h       |  6 ++++++
 security/integrity/ima/ima_kexec.c | 21 +++++++++++++++++++++
 security/integrity/ima/ima_queue.c |  5 +++++
 3 files changed, 32 insertions(+)

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 24d09ea91b87..34815baf5e21 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -240,6 +240,12 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key,
 				   unsigned long flags, bool create);
 #endif
 
+#ifdef CONFIG_IMA_KEXEC
+void ima_measure_kexec_event(const char *event_name);
+#else
+static inline void ima_measure_kexec_event(const char *event_name) {}
+#endif
+
 /*
  * The default binary_runtime_measurements list format is defined as the
  * platform native format.  The canonical format is defined as little-endian.
diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
index d1c9d369ba08..38cb2500f4c3 100644
--- a/security/integrity/ima/ima_kexec.c
+++ b/security/integrity/ima/ima_kexec.c
@@ -17,6 +17,8 @@
 #include "ima.h"
 
 #ifdef CONFIG_IMA_KEXEC
+#define IMA_KEXEC_EVENT_LEN 256
+
 static bool ima_kexec_update_registered;
 static struct seq_file ima_kexec_file;
 static size_t kexec_segment_size;
@@ -31,6 +33,24 @@ static void ima_free_kexec_file_buf(struct seq_file *sf)
 	sf->count = 0;
 }
 
+void ima_measure_kexec_event(const char *event_name)
+{
+	char ima_kexec_event[IMA_KEXEC_EVENT_LEN];
+	size_t buf_size = 0;
+	long len;
+	int n;
+
+	buf_size = ima_get_binary_runtime_size();
+	len = atomic_long_read(&ima_htable.len);
+
+	n = scnprintf(ima_kexec_event, IMA_KEXEC_EVENT_LEN,
+		      "kexec_segment_size=%lu;ima_binary_runtime_size=%lu;"
+		      "ima_runtime_measurements_count=%ld;",
+		      kexec_segment_size, buf_size, len);
+
+	ima_measure_critical_data("ima_kexec", event_name, ima_kexec_event, n, false, NULL, 0);
+}
+
 static int ima_alloc_kexec_file_buf(size_t segment_size)
 {
 	/*
@@ -53,6 +73,7 @@ static int ima_alloc_kexec_file_buf(size_t segment_size)
 out:
 	ima_kexec_file.read_pos = 0;
 	ima_kexec_file.count = sizeof(struct ima_kexec_hdr);	/* reserved space */
+	ima_measure_kexec_event("kexec_load");
 
 	return 0;
 }
diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
index 83d53824aa98..590637e81ad1 100644
--- a/security/integrity/ima/ima_queue.c
+++ b/security/integrity/ima/ima_queue.c
@@ -241,6 +241,11 @@ static int ima_reboot_notifier(struct notifier_block *nb,
 			       unsigned long action,
 			       void *data)
 {
+#ifdef CONFIG_IMA_KEXEC
+	if (action == SYS_RESTART && data && !strcmp(data, "kexec reboot"))
+		ima_measure_kexec_event("kexec_execute");
+#endif
+
 	ima_measurements_suspend();
 
 	return NOTIFY_DONE;
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH v13 3/9] kexec: define functions to map and unmap segments
  2025-04-21 22:25 ` [PATCH v13 3/9] kexec: define functions to map and unmap segments steven chen
@ 2025-04-23  0:29   ` Mimi Zohar
  2025-04-23 15:29     ` steven chen
  0 siblings, 1 reply; 23+ messages in thread
From: Mimi Zohar @ 2025-04-23  0:29 UTC (permalink / raw)
  To: steven chen, stefanb, roberto.sassu, roberto.sassu, eric.snowberg,
	ebiederm, paul, code, bauermann, linux-integrity, kexec,
	linux-security-module, linux-kernel
  Cc: madvenka, nramas, James.Bottomley, bhe, vgoyal, dyoung

On Mon, 2025-04-21 at 15:25 -0700, steven chen wrote:
> From: Steven Chen <chenste@linux.microsoft.com>
> 
> Implement kimage_map_segment() to enable IMA to map the measurement log 
> list to the kimage structure during the kexec 'load' stage. This function
> gathers the source pages within the specified address range, and maps them
> to a contiguous virtual address range.
> 
> This is a preparation for later usage.
> 
> Implement kimage_unmap_segment() for unmapping segments using vunmap().
> 
> Cc: Eric Biederman <ebiederm@xmission.com>
> Cc: Baoquan He <bhe@redhat.com> 
> Cc: Vivek Goyal <vgoyal@redhat.com>
> Cc: Dave Young <dyoung@redhat.com>
> Co-developed-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
> Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
> Signed-off-by: steven chen <chenste@linux.microsoft.com>

Checkpatch.pl is complaining that the Signed-off-by tag does not matches the
"From:" line only on this patch.  I've updated your Signed-off-by tag to match
the "From:" line above.

> Acked-by: Baoquan He <bhe@redhat.com>

Missing from v13 is Stefan's Tested-by tag.  As the code hasn't changed, I've
added it.  In the future, please don't forget to add the tags.

Stefen Berger spent quite a bit of time reviewing this patch set, but with v13
most of his Reviewed-by tags are missing. Stefan?

For now the patch set is staged in the next-integrity-testing branch.

thanks,

Mimi


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v13 3/9] kexec: define functions to map and unmap segments
  2025-04-23  0:29   ` Mimi Zohar
@ 2025-04-23 15:29     ` steven chen
  2025-04-23 18:21       ` Mimi Zohar
  0 siblings, 1 reply; 23+ messages in thread
From: steven chen @ 2025-04-23 15:29 UTC (permalink / raw)
  To: Mimi Zohar, stefanb, roberto.sassu, roberto.sassu, eric.snowberg,
	ebiederm, paul, code, bauermann, linux-integrity, kexec,
	linux-security-module, linux-kernel
  Cc: madvenka, nramas, James.Bottomley, bhe, vgoyal, dyoung

On 4/22/2025 5:29 PM, Mimi Zohar wrote:
> On Mon, 2025-04-21 at 15:25 -0700, steven chen wrote:
>> From: Steven Chen <chenste@linux.microsoft.com>
>>
>> Implement kimage_map_segment() to enable IMA to map the measurement log
>> list to the kimage structure during the kexec 'load' stage. This function
>> gathers the source pages within the specified address range, and maps them
>> to a contiguous virtual address range.
>>
>> This is a preparation for later usage.
>>
>> Implement kimage_unmap_segment() for unmapping segments using vunmap().
>>
>> Cc: Eric Biederman <ebiederm@xmission.com>
>> Cc: Baoquan He <bhe@redhat.com>
>> Cc: Vivek Goyal <vgoyal@redhat.com>
>> Cc: Dave Young <dyoung@redhat.com>
>> Co-developed-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
>> Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
>> Signed-off-by: steven chen <chenste@linux.microsoft.com>
> Checkpatch.pl is complaining that the Signed-off-by tag does not matches the
> "From:" line only on this patch.  I've updated your Signed-off-by tag to match
> the "From:" line above.
>
>> Acked-by: Baoquan He <bhe@redhat.com>
> Missing from v13 is Stefan's Tested-by tag.  As the code hasn't changed, I've
> added it.  In the future, please don't forget to add the tags.
>
> Stefen Berger spent quite a bit of time reviewing this patch set, but with v13
> most of his Reviewed-by tags are missing. Stefan?
>
> For now the patch set is staged in the next-integrity-testing branch.
>
> thanks,
>
> Mimi

Hi Mimi,

Could you help to add
Tested-by tag for this patch set: "Tested-by: Stefan Berger 
<stefanb@linux.ibm.com> # ppc64/kvm"
Reviewed-by tags "Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>" to 
patch 1, 5, 6, 9.

Thanks a lot.

Hi Stefen,

Thanks for your help all the time and sorry missing tags to show your work.

Sorry again,

Steven



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v13 3/9] kexec: define functions to map and unmap segments
  2025-04-23 15:29     ` steven chen
@ 2025-04-23 18:21       ` Mimi Zohar
  0 siblings, 0 replies; 23+ messages in thread
From: Mimi Zohar @ 2025-04-23 18:21 UTC (permalink / raw)
  To: steven chen, stefanb, roberto.sassu, roberto.sassu, eric.snowberg,
	ebiederm, paul, code, bauermann, linux-integrity, kexec,
	linux-security-module, linux-kernel
  Cc: madvenka, nramas, James.Bottomley, bhe, vgoyal, dyoung

On Wed, 2025-04-23 at 08:29 -0700, steven chen wrote:
[ ... ] 
> 
> Hi Mimi,
> 
> Could you help to add
> Tested-by tag for this patch set: "Tested-by: Stefan Berger 
> <stefanb@linux.ibm.com> # ppc64/kvm"

Already done.

> Reviewed-by tags "Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>" to 
> patch 1, 5, 6, 9.

I'm pretty sure that Stefan added his Reviewed-by tags to the entire patch set.
As soon as we hear back from him, I'll add his tags.

Mimi

> 
> Thanks a lot.
> 
> Hi Stefen,
> 
> Thanks for your help all the time and sorry missing tags to show your work.
> 
> Sorry again,
> 
> Steven
> 
> 



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v13 0/9] ima: kexec: measure events between kexec load and execute
  2025-04-21 22:25 [PATCH v13 0/9] ima: kexec: measure events between kexec load and execute steven chen
                   ` (8 preceding siblings ...)
  2025-04-21 22:25 ` [PATCH v13 9/9] ima: measure kexec load and exec events as critical data steven chen
@ 2025-04-24 14:37 ` Baoquan He
  2025-04-24 19:26   ` steven chen
  2025-05-02 16:25   ` steven chen
  9 siblings, 2 replies; 23+ messages in thread
From: Baoquan He @ 2025-04-24 14:37 UTC (permalink / raw)
  To: steven chen
  Cc: zohar, stefanb, roberto.sassu, roberto.sassu, eric.snowberg,
	ebiederm, paul, code, bauermann, linux-integrity, kexec,
	linux-security-module, linux-kernel, madvenka, nramas,
	James.Bottomley, vgoyal, dyoung

Hi Steven,

Could you test below code and post a formal patch to not copy
measurement list buffer to kdump kernel? Below log is just for your
reference, please feel free to modify or rephrase. 

===
Kdump kernel doesn't need IMA to do integrity measurement.
Hence the measurement list in 1st kernel doesn't need to be copied to
kdump kenrel.

Here skip allocating buffer for measurement list copying if loading
kdump kernel. Then there won't be the later handling related to
ima_kexec_buffer.
===

diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
index 38cb2500f4c3..7362f68f2d8b 100644
--- a/security/integrity/ima/ima_kexec.c
+++ b/security/integrity/ima/ima_kexec.c
@@ -146,6 +146,9 @@ void ima_add_kexec_buffer(struct kimage *image)
 	void *kexec_buffer = NULL;
 	int ret;
 
+	if (image->type == KEXEC_TYPE_CRASH)
+		return;
+
 	/*
 	 * Reserve extra memory for measurements added during kexec.
 	 */



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH v13 0/9] ima: kexec: measure events between kexec load and execute
  2025-04-24 14:37 ` [PATCH v13 0/9] ima: kexec: measure events between kexec load and execute Baoquan He
@ 2025-04-24 19:26   ` steven chen
  2025-05-02 16:25   ` steven chen
  1 sibling, 0 replies; 23+ messages in thread
From: steven chen @ 2025-04-24 19:26 UTC (permalink / raw)
  To: Baoquan He
  Cc: zohar, stefanb, roberto.sassu, roberto.sassu, eric.snowberg,
	ebiederm, paul, code, bauermann, linux-integrity, kexec,
	linux-security-module, linux-kernel, madvenka, nramas,
	James.Bottomley, vgoyal, dyoung

On 4/24/2025 7:37 AM, Baoquan He wrote:
> Hi Steven,
>
> Could you test below code and post a formal patch to not copy
> measurement list buffer to kdump kernel? Below log is just for your
> reference, please feel free to modify or rephrase.
>
> ===
> Kdump kernel doesn't need IMA to do integrity measurement.
> Hence the measurement list in 1st kernel doesn't need to be copied to
> kdump kenrel.
>
> Here skip allocating buffer for measurement list copying if loading
> kdump kernel. Then there won't be the later handling related to
> ima_kexec_buffer.
> ===
>
> diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
> index 38cb2500f4c3..7362f68f2d8b 100644
> --- a/security/integrity/ima/ima_kexec.c
> +++ b/security/integrity/ima/ima_kexec.c
> @@ -146,6 +146,9 @@ void ima_add_kexec_buffer(struct kimage *image)
>   	void *kexec_buffer = NULL;
>   	int ret;
>   
> +	if (image->type == KEXEC_TYPE_CRASH)
> +		return;
> +
>   	/*
>   	 * Reserve extra memory for measurements added during kexec.
>   	 */

Hi Baoquan,

I will work on it and I will post a patch after this patch set merged.

Thanks,

Steven



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v13 5/9] ima: kexec: define functions to copy IMA log at soft boot
  2025-04-21 22:25 ` [PATCH v13 5/9] ima: kexec: define functions to copy IMA log at soft boot steven chen
@ 2025-04-29 16:50   ` Stefan Berger
  0 siblings, 0 replies; 23+ messages in thread
From: Stefan Berger @ 2025-04-29 16:50 UTC (permalink / raw)
  To: steven chen, zohar, roberto.sassu, roberto.sassu, eric.snowberg,
	ebiederm, paul, code, bauermann, linux-integrity, kexec,
	linux-security-module, linux-kernel
  Cc: madvenka, nramas, James.Bottomley, bhe, vgoyal, dyoung



On 4/21/25 6:25 PM, steven chen wrote:
> From: Steven Chen <chenste@linux.microsoft.com>
> 
> The IMA log is currently copied to the new kernel during kexec 'load'
> using ima_dump_measurement_list(). However, the log copied at kexec
> 'load' may result in loss of IMA measurements that only occurred after
> kexec "load'. Setup the needed infrastructure to move the IMA log copy
> from kexec 'load' to 'execute'.
> 
> Define a new IMA hook ima_update_kexec_buffer() as a stub function.
> It will be used to call ima_dump_measurement_list() during kexec 'execute'.
> 
> Implement ima_kexec_post_load() function to be invoked after the new
> Kernel image has been loaded for kexec. ima_kexec_post_load() maps the
> IMA buffer to a segment in the newly loaded Kernel.  It also registers
> the reboot notifier_block to trigger ima_update_kexec_buffer() at
> kexec 'execute'.
> 
> Set the priority of register_reboot_notifier to INT_MIN to ensure that the
> IMA log copy operation will happen at the end of the operation chain, so
> that all the IMA measurement records extended into the TPM are copied
> 
> Co-developed-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
> Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
> Cc: Eric Biederman <ebiederm@xmission.com>
> Cc: Baoquan He <bhe@redhat.com>
> Cc: Vivek Goyal <vgoyal@redhat.com>
> Cc: Dave Young <dyoung@redhat.com>
> Signed-off-by: Steven Chen <chenste@linux.microsoft.com>
> Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
> Acked-by: Baoquan He <bhe@redhat.com>

Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>

> ---
>   include/linux/ima.h                |  3 ++
>   security/integrity/ima/ima_kexec.c | 47 ++++++++++++++++++++++++++++++
>   2 files changed, 50 insertions(+)
> 
> diff --git a/include/linux/ima.h b/include/linux/ima.h
> index 0bae61a15b60..8e29cb4e6a01 100644
> --- a/include/linux/ima.h
> +++ b/include/linux/ima.h
> @@ -32,6 +32,9 @@ static inline void ima_appraise_parse_cmdline(void) {}
>   
>   #ifdef CONFIG_IMA_KEXEC
>   extern void ima_add_kexec_buffer(struct kimage *image);
> +extern void ima_kexec_post_load(struct kimage *image);
> +#else
> +static inline void ima_kexec_post_load(struct kimage *image) {}
>   #endif
>   
>   #else
> diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
> index 7e0a19c3483f..e79f6caf895b 100644
> --- a/security/integrity/ima/ima_kexec.c
> +++ b/security/integrity/ima/ima_kexec.c
> @@ -12,10 +12,14 @@
>   #include <linux/kexec.h>
>   #include <linux/of.h>
>   #include <linux/ima.h>
> +#include <linux/reboot.h>
> +#include <asm/page.h>
>   #include "ima.h"
>   
>   #ifdef CONFIG_IMA_KEXEC
> +static bool ima_kexec_update_registered;
>   static struct seq_file ima_kexec_file;
> +static void *ima_kexec_buffer;
>   
>   static void ima_free_kexec_file_buf(struct seq_file *sf)
>   {
> @@ -162,6 +166,49 @@ void ima_add_kexec_buffer(struct kimage *image)
>   	kexec_dprintk("kexec measurement buffer for the loaded kernel at 0x%lx.\n",
>   		      kbuf.mem);
>   }
> +
> +/*
> + * Called during kexec execute so that IMA can update the measurement list.
> + */
> +static int ima_update_kexec_buffer(struct notifier_block *self,
> +				   unsigned long action, void *data)
> +{
> +	return NOTIFY_OK;
> +}
> +
> +static struct notifier_block update_buffer_nb = {
> +	.notifier_call = ima_update_kexec_buffer,
> +	.priority = INT_MIN
> +};
> +
> +/*
> + * Create a mapping for the source pages that contain the IMA buffer
> + * so we can update it later.
> + */
> +void ima_kexec_post_load(struct kimage *image)
> +{
> +	if (ima_kexec_buffer) {
> +		kimage_unmap_segment(ima_kexec_buffer);
> +		ima_kexec_buffer = NULL;
> +	}
> +
> +	if (!image->ima_buffer_addr)
> +		return;
> +
> +	ima_kexec_buffer = kimage_map_segment(image,
> +					      image->ima_buffer_addr,
> +					      image->ima_buffer_size);
> +	if (!ima_kexec_buffer) {
> +		pr_err("Could not map measurements buffer.\n");
> +		return;
> +	}
> +
> +	if (!ima_kexec_update_registered) {
> +		register_reboot_notifier(&update_buffer_nb);
> +		ima_kexec_update_registered = true;
> +	}
> +}
> +
>   #endif /* IMA_KEXEC */
>   
>   /*



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v13 9/9] ima: measure kexec load and exec events as critical data
  2025-04-21 22:25 ` [PATCH v13 9/9] ima: measure kexec load and exec events as critical data steven chen
@ 2025-04-29 18:18   ` Stefan Berger
  0 siblings, 0 replies; 23+ messages in thread
From: Stefan Berger @ 2025-04-29 18:18 UTC (permalink / raw)
  To: steven chen, zohar, roberto.sassu, roberto.sassu, eric.snowberg,
	ebiederm, paul, code, bauermann, linux-integrity, kexec,
	linux-security-module, linux-kernel
  Cc: madvenka, nramas, James.Bottomley, bhe, vgoyal, dyoung



On 4/21/25 6:25 PM, steven chen wrote:
> From: Steven Chen <chenste@linux.microsoft.com>
> 
> The amount of memory allocated at kexec load, even with the extra memory
> allocated, might not be large enough for the entire measurement list.  The
> indeterminate interval between kexec 'load' and 'execute' could exacerbate
> this problem.
> 
> Define two new IMA events, 'kexec_load' and 'kexec_execute', to be
> measured as critical data at kexec 'load' and 'execute' respectively.
> Report the allocated kexec segment size, IMA binary log size and the
> runtime measurements count as part of those events.
> 
> These events, and the values reported through them, serve as markers in
> the IMA log to verify the IMA events are captured during kexec soft
> reboot.  The presence of a 'kexec_load' event in between the last two
> 'boot_aggregate' events in the IMA log implies this is a kexec soft
> reboot, and not a cold-boot. And the absence of 'kexec_execute' event
> after kexec soft reboot implies missing events in that window which
> results in inconsistency with TPM PCR quotes, necessitating a cold boot
> for a successful remote attestation.
> 
> These critical data events are displayed as hex encoded ascii in the
> ascii_runtime_measurement_list.  Verifying the critical data hash requires
> calculating the hash of the decoded ascii string.
> 
> For example, to verify the 'kexec_load' data hash:
> 
> sudo cat /sys/kernel/security/integrity/ima/ascii_runtime_measurements
> | grep  kexec_load | cut -d' ' -f 6 | xxd -r -p | sha256sum
> 
> 
> To verify the 'kexec_execute' data hash:
> 
> sudo cat /sys/kernel/security/integrity/ima/ascii_runtime_measurements
> | grep kexec_execute | cut -d' ' -f 6 | xxd -r -p | sha256sum
> 
> Co-developed-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
> Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
> Signed-off-by: Steven Chen <chenste@linux.microsoft.com>
> Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
> Acked-by: Baoquan He <bhe@redhat.com>
 > --->   security/integrity/ima/ima.h       |  6 ++++++
>   security/integrity/ima/ima_kexec.c | 21 +++++++++++++++++++++
>   security/integrity/ima/ima_queue.c |  5 +++++
>   3 files changed, 32 insertions(+)
> 
> diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
> index 24d09ea91b87..34815baf5e21 100644
> --- a/security/integrity/ima/ima.h
> +++ b/security/integrity/ima/ima.h
> @@ -240,6 +240,12 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key,
>   				   unsigned long flags, bool create);
>   #endif
>   
> +#ifdef CONFIG_IMA_KEXEC
> +void ima_measure_kexec_event(const char *event_name);
> +#else
> +static inline void ima_measure_kexec_event(const char *event_name) {}
> +#endif
> +
>   /*
>    * The default binary_runtime_measurements list format is defined as the
>    * platform native format.  The canonical format is defined as little-endian.
> diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
> index d1c9d369ba08..38cb2500f4c3 100644
> --- a/security/integrity/ima/ima_kexec.c
> +++ b/security/integrity/ima/ima_kexec.c
> @@ -17,6 +17,8 @@
>   #include "ima.h"
>   
>   #ifdef CONFIG_IMA_KEXEC
> +#define IMA_KEXEC_EVENT_LEN 256
> +
>   static bool ima_kexec_update_registered;
>   static struct seq_file ima_kexec_file;
>   static size_t kexec_segment_size;
> @@ -31,6 +33,24 @@ static void ima_free_kexec_file_buf(struct seq_file *sf)
>   	sf->count = 0;
>   }
>   
> +void ima_measure_kexec_event(const char *event_name)
> +{
> +	char ima_kexec_event[IMA_KEXEC_EVENT_LEN];
> +	size_t buf_size = 0;
> +	long len;
> +	int n;
> +
> +	buf_size = ima_get_binary_runtime_size();
> +	len = atomic_long_read(&ima_htable.len);
> +
> +	n = scnprintf(ima_kexec_event, IMA_KEXEC_EVENT_LEN,
> +		      "kexec_segment_size=%lu;ima_binary_runtime_size=%lu;"
> +		      "ima_runtime_measurements_count=%ld;",
> +		      kexec_segment_size, buf_size, len);
> +
> +	ima_measure_critical_data("ima_kexec", event_name, ima_kexec_event, n, false, NULL, 0);
> +}
> +
>   static int ima_alloc_kexec_file_buf(size_t segment_size)
>   {
>   	/*
> @@ -53,6 +73,7 @@ static int ima_alloc_kexec_file_buf(size_t segment_size)
>   out:
>   	ima_kexec_file.read_pos = 0;
>   	ima_kexec_file.count = sizeof(struct ima_kexec_hdr);	/* reserved space */
> +	ima_measure_kexec_event("kexec_load");
>   
>   	return 0;
>   }
> diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
> index 83d53824aa98..590637e81ad1 100644
> --- a/security/integrity/ima/ima_queue.c
> +++ b/security/integrity/ima/ima_queue.c
> @@ -241,6 +241,11 @@ static int ima_reboot_notifier(struct notifier_block *nb,
>   			       unsigned long action,
>   			       void *data)
>   {
> +#ifdef CONFIG_IMA_KEXEC
> +	if (action == SYS_RESTART && data && !strcmp(data, "kexec reboot"))
> +		ima_measure_kexec_event("kexec_execute");
> +#endif
> +
>   	ima_measurements_suspend();
>   
>   	return NOTIFY_DONE;

Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v13 7/9] ima: verify if the segment size has changed
  2025-04-21 22:25 ` [PATCH v13 7/9] ima: verify if the segment size has changed steven chen
@ 2025-04-29 18:19   ` Stefan Berger
  0 siblings, 0 replies; 23+ messages in thread
From: Stefan Berger @ 2025-04-29 18:19 UTC (permalink / raw)
  To: steven chen, zohar, roberto.sassu, roberto.sassu, eric.snowberg,
	ebiederm, paul, code, bauermann, linux-integrity, kexec,
	linux-security-module, linux-kernel
  Cc: madvenka, nramas, James.Bottomley, bhe, vgoyal, dyoung



On 4/21/25 6:25 PM, steven chen wrote:
> From: Steven Chen <chenste@linux.microsoft.com>
> 
> kexec 'load' may be called multiple times. Free and realloc the buffer
> only if the segment_size is changed from the previous kexec 'load' call.
> 
> Signed-off-by: Steven Chen <chenste@linux.microsoft.com>
> Acked-by: Baoquan He <bhe@redhat.com>
> Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
> ---
>   security/integrity/ima/ima_kexec.c | 10 ++++++++++
>   1 file changed, 10 insertions(+)
> 
> diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
> index 5c3b3e0b2186..ed867734ee70 100644
> --- a/security/integrity/ima/ima_kexec.c
> +++ b/security/integrity/ima/ima_kexec.c
> @@ -33,6 +33,14 @@ static void ima_free_kexec_file_buf(struct seq_file *sf)
>   
>   static int ima_alloc_kexec_file_buf(size_t segment_size)
>   {
> +	/*
> +	 * kexec 'load' may be called multiple times.
> +	 * Free and realloc the buffer only if the segment_size is
> +	 * changed from the previous kexec 'load' call.
> +	 */
> +	if (ima_kexec_file.buf && ima_kexec_file.size == segment_size)
> +		goto out;
> +
>   	ima_free_kexec_file_buf(&ima_kexec_file);
>   
>   	/* segment size can't change between kexec load and execute */
> @@ -41,6 +49,8 @@ static int ima_alloc_kexec_file_buf(size_t segment_size)
>   		return -ENOMEM;
>   
>   	ima_kexec_file.size = segment_size;
> +
> +out:
>   	ima_kexec_file.read_pos = 0;
>   	ima_kexec_file.count = sizeof(struct ima_kexec_hdr);	/* reserved space */
>   

Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v13 2/9] ima: define and call ima_alloc_kexec_file_buf()
  2025-04-21 22:25 ` [PATCH v13 2/9] ima: define and call ima_alloc_kexec_file_buf() steven chen
@ 2025-04-29 18:30   ` Stefan Berger
  0 siblings, 0 replies; 23+ messages in thread
From: Stefan Berger @ 2025-04-29 18:30 UTC (permalink / raw)
  To: steven chen, zohar, roberto.sassu, roberto.sassu, eric.snowberg,
	ebiederm, paul, code, bauermann, linux-integrity, kexec,
	linux-security-module, linux-kernel
  Cc: madvenka, nramas, James.Bottomley, bhe, vgoyal, dyoung



On 4/21/25 6:25 PM, steven chen wrote:
> From: Steven Chen <chenste@linux.microsoft.com>
> 
> In the current implementation, the ima_dump_measurement_list() API is
> called during the kexec "load" phase, where a buffer is allocated and
> the measurement records are copied. Due to this, new events added after
> kexec load but before kexec execute are not carried over to the new kernel
> during kexec operation
> 
> Carrying the IMA measurement list across kexec requires allocating a
> buffer and copying the measurement records.  Separate allocating the
> buffer and copying the measurement records into separate functions in
> order to allocate the buffer at kexec 'load' and copy the measurements
> at kexec 'execute'.
> 
> After moving the vfree() here at this stage in the patch set, the IMA
> measurement list fails to verify when doing two consecutive "kexec -s -l"
> with/without a "kexec -s -u" in between.  Only after "ima: kexec: move
> IMA log copy from kexec load to execute" the IMA measurement list verifies
> properly with the vfree() here.
> 
> Co-developed-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
> Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
> Signed-off-by: Steven Chen <chenste@linux.microsoft.com>
> Acked-by: Baoquan He <bhe@redhat.com>
> ---
>   security/integrity/ima/ima_kexec.c | 46 +++++++++++++++++++++++-------
>   1 file changed, 35 insertions(+), 11 deletions(-)
> 
> diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
> index 650beb74346c..b12ac3619b8f 100644
> --- a/security/integrity/ima/ima_kexec.c
> +++ b/security/integrity/ima/ima_kexec.c
> @@ -15,26 +15,46 @@
>   #include "ima.h"
>   
>   #ifdef CONFIG_IMA_KEXEC
> +static struct seq_file ima_kexec_file;
> +
> +static void ima_free_kexec_file_buf(struct seq_file *sf)
> +{
> +	vfree(sf->buf);
> +	sf->buf = NULL;
> +	sf->size = 0;
> +	sf->read_pos = 0;
> +	sf->count = 0;
> +}
> +
> +static int ima_alloc_kexec_file_buf(size_t segment_size)
> +{
> +	ima_free_kexec_file_buf(&ima_kexec_file);
> +
> +	/* segment size can't change between kexec load and execute */
> +	ima_kexec_file.buf = vmalloc(segment_size);
> +	if (!ima_kexec_file.buf)
> +		return -ENOMEM;
> +
> +	ima_kexec_file.size = segment_size;
> +	ima_kexec_file.read_pos = 0;
> +	ima_kexec_file.count = sizeof(struct ima_kexec_hdr);	/* reserved space */
> +
> +	return 0;
> +}
> +
>   static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
>   				     unsigned long segment_size)
>   {
> -	struct seq_file ima_kexec_file;
>   	struct ima_queue_entry *qe;
>   	struct ima_kexec_hdr khdr;
>   	int ret = 0;
>   
>   	/* segment size can't change between kexec load and execute */
> -	ima_kexec_file.buf = vmalloc(segment_size);
>   	if (!ima_kexec_file.buf) {
> -		ret = -ENOMEM;
> -		goto out;
> +		pr_err("Kexec file buf not allocated\n");
> +		return -EINVAL;
>   	}
>   
> -	ima_kexec_file.file = NULL;
> -	ima_kexec_file.size = segment_size;
> -	ima_kexec_file.read_pos = 0;
> -	ima_kexec_file.count = sizeof(khdr);	/* reserved space */
> -
>   	memset(&khdr, 0, sizeof(khdr));
>   	khdr.version = 1;
>   	/* This is an append-only list, no need to hold the RCU read lock */
> @@ -71,8 +91,6 @@ static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
>   	*buffer_size = ima_kexec_file.count;
>   	*buffer = ima_kexec_file.buf;
>   out:
> -	if (ret == -EINVAL)
> -		vfree(ima_kexec_file.buf);
>   	return ret;
>   }
>   
> @@ -111,6 +129,12 @@ void ima_add_kexec_buffer(struct kimage *image)
>   		return;
>   	}
>   
> +	ret = ima_alloc_kexec_file_buf(kexec_segment_size);
> +	if (ret < 0) {
> +		pr_err("Not enough memory for the kexec measurement buffer.\n");
> +		return;
> +	}
> +
>   	ima_dump_measurement_list(&kexec_buffer_size, &kexec_buffer,
>   				  kexec_segment_size);
>   	if (!kexec_buffer) {

Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v13 8/9] ima: make the kexec extra memory configurable
  2025-04-21 22:25 ` [PATCH v13 8/9] ima: make the kexec extra memory configurable steven chen
@ 2025-04-29 19:06   ` Stefan Berger
  2025-04-29 22:00     ` steven chen
  0 siblings, 1 reply; 23+ messages in thread
From: Stefan Berger @ 2025-04-29 19:06 UTC (permalink / raw)
  To: steven chen, zohar, roberto.sassu, roberto.sassu, eric.snowberg,
	ebiederm, paul, code, bauermann, linux-integrity, kexec,
	linux-security-module, linux-kernel
  Cc: madvenka, nramas, James.Bottomley, bhe, vgoyal, dyoung



On 4/21/25 6:25 PM, steven chen wrote:
> From: Steven Chen <chenste@linux.microsoft.com>
> 
> The extra memory allocated for carrying the IMA measurement list across
> kexec is hard-coded as half a PAGE.  Make it configurable.
> 
> Define a Kconfig option, IMA_KEXEC_EXTRA_MEMORY_KB, to configure the
> extra memory (in kb) to be allocated for IMA measurements added during
> kexec soft reboot.  Ensure the default value of the option is set such
> that extra half a page of memory for additional measurements is allocated
> for the additional measurements.
> 
> Update ima_add_kexec_buffer() function to allocate memory based on the
> Kconfig option value, rather than the currently hard-coded one.
> 
> Suggested-by: Stefan Berger <stefanb@linux.ibm.com>
> Co-developed-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
> Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
> Signed-off-by: Steven Chen <chenste@linux.microsoft.com>
> Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
> Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
> Acked-by: Baoquan He <bhe@redhat.com>
> ---
>   security/integrity/ima/Kconfig     | 11 +++++++++++
>   security/integrity/ima/ima_kexec.c | 16 +++++++++++-----
>   2 files changed, 22 insertions(+), 5 deletions(-)
> 
> diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
> index 475c32615006..976e75f9b9ba 100644
> --- a/security/integrity/ima/Kconfig
> +++ b/security/integrity/ima/Kconfig
> @@ -321,4 +321,15 @@ config IMA_DISABLE_HTABLE
>   	help
>   	   This option disables htable to allow measurement of duplicate records.
>   
> +config IMA_KEXEC_EXTRA_MEMORY_KB
> +	int "Extra memory for IMA measurements added during kexec soft reboot"
> +	range 0 40
> +	depends on IMA_KEXEC
> +	default 0
> +	help
> +	  IMA_KEXEC_EXTRA_MEMORY_KB determines the extra memory to be
> +	  allocated (in kb) for IMA measurements added during kexec soft reboot.
> +	  If set to the default value of 0, an extra half page of memory for those
> +	  additional measurements will be allocated.

If you have an IMA policy taking quite a few measurements and you are 
fast after reboot to log in to initiate the 'kexec load' (While system 
is still starting up), the system may end up with loss of measurements 
very easily if the default is 0 and pages are small. -> Set the default 
to the max? Also, would we expect distros to all go through the new 
config option and choose 40 or will they likely leave it at 0?

> +
>   endif
> diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
> index ed867734ee70..d1c9d369ba08 100644
> --- a/security/integrity/ima/ima_kexec.c
> +++ b/security/integrity/ima/ima_kexec.c
> @@ -118,6 +118,7 @@ void ima_add_kexec_buffer(struct kimage *image)
>   				  .buf_min = 0, .buf_max = ULONG_MAX,
>   				  .top_down = true };
>   	unsigned long binary_runtime_size;
> +	unsigned long extra_memory;
>   
>   	/* use more understandable variable names than defined in kbuf */
>   	size_t kexec_buffer_size = 0;
> @@ -125,15 +126,20 @@ void ima_add_kexec_buffer(struct kimage *image)
>   	int ret;
>   
>   	/*
> -	 * Reserve an extra half page of memory for additional measurements
> -	 * added during the kexec load.
> +	 * Reserve extra memory for measurements added during kexec.
>   	 */
> -	binary_runtime_size = ima_get_binary_runtime_size();
> +	if (CONFIG_IMA_KEXEC_EXTRA_MEMORY_KB <= 0)
> +		extra_memory = PAGE_SIZE / 2;
> +	else
> +		extra_memory = CONFIG_IMA_KEXEC_EXTRA_MEMORY_KB * 1024;
> +
> +	binary_runtime_size = ima_get_binary_runtime_size() + extra_memory;
> +
>   	if (binary_runtime_size >= ULONG_MAX - PAGE_SIZE)
>   		kexec_segment_size = ULONG_MAX;
>   	else
> -		kexec_segment_size = ALIGN(ima_get_binary_runtime_size() +
> -					   PAGE_SIZE / 2, PAGE_SIZE);
> +		kexec_segment_size = ALIGN(binary_runtime_size, PAGE_SIZE);
> +
>   	if ((kexec_segment_size == ULONG_MAX) ||
>   	    ((kexec_segment_size >> PAGE_SHIFT) > totalram_pages() / 2)) {
>   		pr_err("Binary measurement list too large.\n");



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v13 8/9] ima: make the kexec extra memory configurable
  2025-04-29 19:06   ` Stefan Berger
@ 2025-04-29 22:00     ` steven chen
  0 siblings, 0 replies; 23+ messages in thread
From: steven chen @ 2025-04-29 22:00 UTC (permalink / raw)
  To: Stefan Berger, zohar, roberto.sassu, roberto.sassu, eric.snowberg,
	ebiederm, paul, code, bauermann, linux-integrity, kexec,
	linux-security-module, linux-kernel
  Cc: madvenka, nramas, James.Bottomley, bhe, vgoyal, dyoung

On 4/29/2025 12:06 PM, Stefan Berger wrote:
>
>
> On 4/21/25 6:25 PM, steven chen wrote:
>> From: Steven Chen <chenste@linux.microsoft.com>
>>
>> The extra memory allocated for carrying the IMA measurement list across
>> kexec is hard-coded as half a PAGE.  Make it configurable.
>>
>> Define a Kconfig option, IMA_KEXEC_EXTRA_MEMORY_KB, to configure the
>> extra memory (in kb) to be allocated for IMA measurements added during
>> kexec soft reboot.  Ensure the default value of the option is set such
>> that extra half a page of memory for additional measurements is 
>> allocated
>> for the additional measurements.
>>
>> Update ima_add_kexec_buffer() function to allocate memory based on the
>> Kconfig option value, rather than the currently hard-coded one.
>>
>> Suggested-by: Stefan Berger <stefanb@linux.ibm.com>
>> Co-developed-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
>> Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
>> Signed-off-by: Steven Chen <chenste@linux.microsoft.com>
>> Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
>> Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
>> Acked-by: Baoquan He <bhe@redhat.com>
>> ---
>>   security/integrity/ima/Kconfig     | 11 +++++++++++
>>   security/integrity/ima/ima_kexec.c | 16 +++++++++++-----
>>   2 files changed, 22 insertions(+), 5 deletions(-)
>>
>> diff --git a/security/integrity/ima/Kconfig 
>> b/security/integrity/ima/Kconfig
>> index 475c32615006..976e75f9b9ba 100644
>> --- a/security/integrity/ima/Kconfig
>> +++ b/security/integrity/ima/Kconfig
>> @@ -321,4 +321,15 @@ config IMA_DISABLE_HTABLE
>>       help
>>          This option disables htable to allow measurement of 
>> duplicate records.
>>   +config IMA_KEXEC_EXTRA_MEMORY_KB
>> +    int "Extra memory for IMA measurements added during kexec soft 
>> reboot"
>> +    range 0 40
>> +    depends on IMA_KEXEC
>> +    default 0
>> +    help
>> +      IMA_KEXEC_EXTRA_MEMORY_KB determines the extra memory to be
>> +      allocated (in kb) for IMA measurements added during kexec soft 
>> reboot.
>> +      If set to the default value of 0, an extra half page of memory 
>> for those
>> +      additional measurements will be allocated.
>
> If you have an IMA policy taking quite a few measurements and you are 
> fast after reboot to log in to initiate the 'kexec load' (While system 
> is still starting up), the system may end up with loss of measurements 
> very easily if the default is 0 and pages are small. -> Set the 
> default to the max? Also, would we expect distros to all go through 
> the new config option and choose 40 or will they likely leave it at 0?
>
Hi Stefan,

Could you please check the comments of version V11 on this default value?

https://lore.kernel.org/all/20250402124725.5601-1-chenste@linux.microsoft.com/

Thanks,

Steven

>> +
>>   endif
>> diff --git a/security/integrity/ima/ima_kexec.c 
>> b/security/integrity/ima/ima_kexec.c
>> index ed867734ee70..d1c9d369ba08 100644
>> --- a/security/integrity/ima/ima_kexec.c
>> +++ b/security/integrity/ima/ima_kexec.c
>> @@ -118,6 +118,7 @@ void ima_add_kexec_buffer(struct kimage *image)
>>                     .buf_min = 0, .buf_max = ULONG_MAX,
>>                     .top_down = true };
>>       unsigned long binary_runtime_size;
>> +    unsigned long extra_memory;
>>         /* use more understandable variable names than defined in 
>> kbuf */
>>       size_t kexec_buffer_size = 0;
>> @@ -125,15 +126,20 @@ void ima_add_kexec_buffer(struct kimage *image)
>>       int ret;
>>         /*
>> -     * Reserve an extra half page of memory for additional measurements
>> -     * added during the kexec load.
>> +     * Reserve extra memory for measurements added during kexec.
>>        */
>> -    binary_runtime_size = ima_get_binary_runtime_size();
>> +    if (CONFIG_IMA_KEXEC_EXTRA_MEMORY_KB <= 0)
>> +        extra_memory = PAGE_SIZE / 2;
>> +    else
>> +        extra_memory = CONFIG_IMA_KEXEC_EXTRA_MEMORY_KB * 1024;
>> +
>> +    binary_runtime_size = ima_get_binary_runtime_size() + extra_memory;
>> +
>>       if (binary_runtime_size >= ULONG_MAX - PAGE_SIZE)
>>           kexec_segment_size = ULONG_MAX;
>>       else
>> -        kexec_segment_size = ALIGN(ima_get_binary_runtime_size() +
>> -                       PAGE_SIZE / 2, PAGE_SIZE);
>> +        kexec_segment_size = ALIGN(binary_runtime_size, PAGE_SIZE);
>> +
>>       if ((kexec_segment_size == ULONG_MAX) ||
>>           ((kexec_segment_size >> PAGE_SHIFT) > totalram_pages() / 2)) {
>>           pr_err("Binary measurement list too large.\n");




^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v13 0/9] ima: kexec: measure events between kexec load and execute
  2025-04-24 14:37 ` [PATCH v13 0/9] ima: kexec: measure events between kexec load and execute Baoquan He
  2025-04-24 19:26   ` steven chen
@ 2025-05-02 16:25   ` steven chen
  2025-05-06  5:49     ` Baoquan He
  1 sibling, 1 reply; 23+ messages in thread
From: steven chen @ 2025-05-02 16:25 UTC (permalink / raw)
  To: Baoquan He
  Cc: zohar, stefanb, roberto.sassu, roberto.sassu, eric.snowberg,
	ebiederm, paul, code, bauermann, linux-integrity, kexec,
	linux-security-module, linux-kernel, madvenka, nramas,
	James.Bottomley, vgoyal, dyoung

On 4/24/2025 7:37 AM, Baoquan He wrote:
> Hi Steven,
>
> Could you test below code and post a formal patch to not copy
> measurement list buffer to kdump kernel? Below log is just for your
> reference, please feel free to modify or rephrase.
>
> ===
> Kdump kernel doesn't need IMA to do integrity measurement.
> Hence the measurement list in 1st kernel doesn't need to be copied to
> kdump kenrel.
>
> Here skip allocating buffer for measurement list copying if loading
> kdump kernel. Then there won't be the later handling related to
> ima_kexec_buffer.
> ===
>
> diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
> index 38cb2500f4c3..7362f68f2d8b 100644
> --- a/security/integrity/ima/ima_kexec.c
> +++ b/security/integrity/ima/ima_kexec.c
> @@ -146,6 +146,9 @@ void ima_add_kexec_buffer(struct kimage *image)
>   	void *kexec_buffer = NULL;
>   	int ret;
>   
> +	if (image->type == KEXEC_TYPE_CRASH)
> +		return;
> +
>   	/*
>   	 * Reserve extra memory for measurements added during kexec.
>   	 */
>
Hi Baoquan,

I tested the kernel with above change. Normal soft reboot works fine.

I will post the patch for review.

Please make sure to test KDump scenario.

Thanks,

Steven



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v13 0/9] ima: kexec: measure events between kexec load and execute
  2025-05-02 16:25   ` steven chen
@ 2025-05-06  5:49     ` Baoquan He
  0 siblings, 0 replies; 23+ messages in thread
From: Baoquan He @ 2025-05-06  5:49 UTC (permalink / raw)
  To: steven chen
  Cc: zohar, stefanb, roberto.sassu, roberto.sassu, eric.snowberg,
	ebiederm, paul, code, bauermann, linux-integrity, kexec,
	linux-security-module, linux-kernel, madvenka, nramas,
	James.Bottomley, vgoyal, dyoung

On 05/02/25 at 09:25am, steven chen wrote:
> On 4/24/2025 7:37 AM, Baoquan He wrote:
> > Hi Steven,
> > 
> > Could you test below code and post a formal patch to not copy
> > measurement list buffer to kdump kernel? Below log is just for your
> > reference, please feel free to modify or rephrase.
> > 
> > ===
> > Kdump kernel doesn't need IMA to do integrity measurement.
> > Hence the measurement list in 1st kernel doesn't need to be copied to
> > kdump kenrel.
> > 
> > Here skip allocating buffer for measurement list copying if loading
> > kdump kernel. Then there won't be the later handling related to
> > ima_kexec_buffer.
> > ===
> > 
> > diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
> > index 38cb2500f4c3..7362f68f2d8b 100644
> > --- a/security/integrity/ima/ima_kexec.c
> > +++ b/security/integrity/ima/ima_kexec.c
> > @@ -146,6 +146,9 @@ void ima_add_kexec_buffer(struct kimage *image)
> >   	void *kexec_buffer = NULL;
> >   	int ret;
> > +	if (image->type == KEXEC_TYPE_CRASH)
> > +		return;
> > +
> >   	/*
> >   	 * Reserve extra memory for measurements added during kexec.
> >   	 */
> > 
> Hi Baoquan,
> 
> I tested the kernel with above change. Normal soft reboot works fine.
> 
> I will post the patch for review.

Just come back from Labor Day public holiday. I went through the code
flow, the code should be fine. I will test it by checking the setup_data
if IMA data is excluded in kdump case.



^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2025-05-06  6:31 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-21 22:25 [PATCH v13 0/9] ima: kexec: measure events between kexec load and execute steven chen
2025-04-21 22:25 ` [PATCH v13 1/9] ima: rename variable the seq_file "file" to "ima_kexec_file" steven chen
2025-04-21 22:25 ` [PATCH v13 2/9] ima: define and call ima_alloc_kexec_file_buf() steven chen
2025-04-29 18:30   ` Stefan Berger
2025-04-21 22:25 ` [PATCH v13 3/9] kexec: define functions to map and unmap segments steven chen
2025-04-23  0:29   ` Mimi Zohar
2025-04-23 15:29     ` steven chen
2025-04-23 18:21       ` Mimi Zohar
2025-04-21 22:25 ` [PATCH v13 4/9] ima: kexec: skip IMA segment validation after kexec soft reboot steven chen
2025-04-21 22:25 ` [PATCH v13 5/9] ima: kexec: define functions to copy IMA log at soft boot steven chen
2025-04-29 16:50   ` Stefan Berger
2025-04-21 22:25 ` [PATCH v13 6/9] ima: kexec: move IMA log copy from kexec load to execute steven chen
2025-04-21 22:25 ` [PATCH v13 7/9] ima: verify if the segment size has changed steven chen
2025-04-29 18:19   ` Stefan Berger
2025-04-21 22:25 ` [PATCH v13 8/9] ima: make the kexec extra memory configurable steven chen
2025-04-29 19:06   ` Stefan Berger
2025-04-29 22:00     ` steven chen
2025-04-21 22:25 ` [PATCH v13 9/9] ima: measure kexec load and exec events as critical data steven chen
2025-04-29 18:18   ` Stefan Berger
2025-04-24 14:37 ` [PATCH v13 0/9] ima: kexec: measure events between kexec load and execute Baoquan He
2025-04-24 19:26   ` steven chen
2025-05-02 16:25   ` steven chen
2025-05-06  5:49     ` Baoquan He

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).