Skip to contentSkip to conversation

ima: measure events between kexec load and execute

PATCH Superseded Tushar Sugandhi 5 participants 41 messages Jul 3, 2023 – Sep 22, 2023

Subsystems (7)

v1 of 5 Superseded Latest is v5 →

lore
Share & tools
lore
#0 lore raw

cover ima: measure events between kexec load and execute

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'.

Some devices can be configured to call kexec 'load' first, and followed by kexec 'execute' after some time. (as opposed to calling 'load' and 'execute' in one single kexec command). In such scenario, if new IMA measurements are added between kexec 'load' and kexec 'execute', the TPM PCRs are extended with the IMA events between 'load' and 'execute'; but those IMA events are not carried over to the new kernel after kexec soft reboot. This results in mismatch between TPM PCR quotes and the actual IMA measurements list after the device boots into the new kexec image. This mismatch results in the remote attestation failing for that device.

This patch series proposes a solution to solve this problem by allocating the necessary buffer at kexec 'load' time, and populating the buffer with the IMA measurements at kexec 'execute' time.

The solution includes:
- addition of new functionality to allocate a buffer to hold IMA measurements at kexec 'load',

- ima functionality to suspend and resume measurements as needed during buffer copy at kexec 'execute',

- ima functionality for mapping the measurement list 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',

- and removal of deprecated functions.

The modifications 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.

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

[1] [PATHC v2 5/9] ima: on soft reboot, save the measurement list
https://lore.kernel.org/lkml/[email protected]/

[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/[email protected]/T/

Tushar Sugandhi (10):
ima: implement function to allocate buffer at kexec load
ima: implement function to populate buffer at kexec execute
ima: allocate buffer at kexec load to hold ima measurements
ima: implement functions to suspend and resume measurements
kexec: implement functions to map and unmap segment to kimage
ima: update buffer at kexec execute with ima measurements
ima: remove function ima_dump_measurement_list
ima: implement and register a reboot notifier function to update kexec
buffer
ima: suspend measurements while the kexec buffer is being copied
kexec: update kexec_file_load syscall to call ima_kexec_post_load

 include/linux/ima.h                |   3 +
 include/linux/kexec.h              |  13 ++
 kernel/kexec_core.c                |  72 +++++++++-
 kernel/kexec_file.c                |   7 +
 kernel/kexec_internal.h            |   1 +
 security/integrity/ima/ima.h       |   4 +
 security/integrity/ima/ima_kexec.c | 211 +++++++++++++++++++++++------
 security/integrity/ima/ima_queue.c |  32 +++++
 8 files changed, 295 insertions(+), 48 deletions(-)
Signature · 1 line
2.25.1
#1 lore raw

PATCH 1/10 ima: implement function to allocate buffer at kexec load

IMA does not provide a mechanism to allocate memory for IMA log storage during kexec operation. The function should handle the scenario where the kexec load is called multiple times.

Implement a function to allocate buffer of size kexec_segment_size at kexec load. If the buffer was already allocated, free that buffer and reallocate. Finally, initialize ima_khdr struct.

The patch operates under the assumption that the segment size does not change between kexec load and execute.

---
 security/integrity/ima/ima_kexec.c | 47 ++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)
security/integrity/ima/ima_kexec.c +47 -0
index 419dc405c831..48a683874044 100644
@@ -15,6 +15,53 @@
 #include "ima.h"
 
 #ifdef CONFIG_IMA_KEXEC
+struct seq_file ima_kexec_file;
+struct ima_kexec_hdr ima_khdr;
+static size_t kexec_segment_size;
+
+void ima_clear_kexec_file(void)
+{
+	vfree(ima_kexec_file.buf);
+	ima_kexec_file.buf = NULL;
+	ima_kexec_file.size = 0;
+	ima_kexec_file.read_pos = 0;
+	ima_kexec_file.count = 0;
+}
+
+static int ima_allocate_buf_at_kexec_load(void)
+{
+	if ((kexec_segment_size == 0) ||
+	    (kexec_segment_size == ULONG_MAX) ||
+	    ((kexec_segment_size >> PAGE_SHIFT) > totalram_pages() / 2)) {
+		pr_err("%s: Invalid segment size for kexec: %zu\n",
+			__func__, kexec_segment_size);
+		return -EINVAL;
+	}
+
+	/* if kexec load was called before, clear the existing buffer
+	 *  before allocating a new one
+	 */
+	if (ima_kexec_file.buf)
+		ima_clear_kexec_file();
+
+	/* segment size can't change between kexec load and execute */
+	ima_kexec_file.buf = vmalloc(kexec_segment_size);
+	if (!ima_kexec_file.buf) {
+		pr_err("%s: No memory for ima kexec measurement buffer\n",
+			__func__);
+		return -ENOMEM;
+	}
+
+	ima_kexec_file.size = kexec_segment_size;
+	ima_kexec_file.read_pos = 0;
+	ima_kexec_file.count = sizeof(ima_khdr);	/* reserved space */
+
+	memset(&ima_khdr, 0, sizeof(ima_khdr));
+	ima_khdr.version = 1;
+
+	return 0;
+}
+
 static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
 				     unsigned long segment_size)
 {
Signature · 1 line
2.25.1
maintainer
#2 lore raw

Re: [PATCH 01/10] ima: implement function to allocate buffer at kexec load

Hi Tushar,

Quoted 2 lines · Tushar Sugandhi

IMA does not provide a mechanism to allocate memory for IMA log storage during kexec operation.

The IMA measurement list is currently being carried across kexec, so obviously a buffer is being allocated for it. IMA not allocating memory for the measurment list is not the problem statement. Please concisely provide the problem statement, explaining why IMA needs to allocate the buffer.

Quoted 2 lines

The function should handle the scenario where
the kexec load is called multiple times.

Currently the buffer is being freed with the kexec 'unload'. With this patch IMA is allocating a buffer for the measurement list, which needs to be freed independently of the kexec 'unload'.

Quoted 8 lines

Implement a function to allocate buffer of size kexec_segment_size at kexec load. If the buffer was already allocated, free that buffer and reallocate. Finally, initialihze ima_khdr struct.

The patch operates under the assumption that the segment size does not change between kexec load and execute.

Signature · 12 lines
thanks,

Mimib





_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
#3 lore raw

Re: [PATCH 01/10] ima: implement function to allocate buffer at kexec load

Adding Eric to cc.

Quoted 11 lines · Mimi Zohar

Hi Tushar,

Quoted 2 lines · Tushar Sugandhi

IMA does not provide a mechanism to allocate memory for IMA log storage during kexec operation.

The IMA measurement list is currently being carried across kexec, so obviously a buffer is being allocated for it. IMA not allocating memory for the measurment list is not the problem statement. Please concisely provide the problem statement, explaining why IMA needs to allocate the buffer.

I meant IMA does not provide separate functions to allocate buffer and populate measurements.  Both operations are wrapped in an atomic ima_dump_measurement_list().

As I mentioned in the comment in the cover letter, if there is no such technical limitation to allocate the buffer and copy the measurements at kexec ‘execute’ – I will make the necessary code changes and update the above line in the patch description accordingly.

Quoted 5 lines
Quoted 2 lines

The function should handle the scenario where
the kexec load is called multiple times.

Currently the buffer is being freed with the kexec 'unload'. With this patch IMA is allocating a buffer for the measurement list, which needs to be freed independently of the kexec 'unload'.

If we end up allocating the buffer at kexec ‘execute’ (which results in soft boot to next Kernel) – is it technically possible that kexec ‘unload’ being called after calling kexec ‘execute’?

If not, should I still free the buffer at kexec ‘unload’ in this scenario?

~Tushar

Quoted 8 lines
Quoted 8 lines

Implement a function to allocate buffer of size kexec_segment_size at kexec load. If the buffer was already allocated, free that buffer and reallocate. Finally, initialihze ima_khdr struct.

The patch operates under the assumption that the segment size does not change between kexec load and execute.

maintainer
#4 lore raw

Re: [PATCH 01/10] ima: implement function to allocate buffer at kexec load

Quoted 14 lines · Tushar Sugandhi

Adding Eric to cc.

Quoted 11 lines · Mimi Zohar

Hi Tushar,

Quoted 2 lines · Tushar Sugandhi

IMA does not provide a mechanism to allocate memory for IMA log storage during kexec operation.

The IMA measurement list is currently being carried across kexec, so obviously a buffer is being allocated for it. IMA not allocating memory for the measurment list is not the problem statement. Please concisely provide the problem statement, explaining why IMA needs to allocate the buffer.

Quoted 3 lines

I meant IMA does not provide separate functions to allocate buffer and populate measurements. Both operations are wrapped in an atomic ima_dump_measurement_list().

Ok.

Quoted 4 lines

As I mentioned in the comment in the cover letter, if there is no such technical limitation to allocate the buffer and copy the measurements at kexec ‘execute’ – I will make the necessary code changes and update the above line in the patch description accordingly.

The "normal" way of making this type of change would be to split the existing ima_dump_measurement_list() function. Copying the measurement list would still be named ima_dump_measurement_list(). The other could be named ima_alloc_kexec_buf(). Both functions initially would be called.

Eric, besides updating the buffer at kexec execute, is there anything else that needs to be done (e.g. updating digests)?

Quoted 6 lines
Quoted 5 lines
Quoted 2 lines

The function should handle the scenario where
the kexec load is called multiple times.

Currently the buffer is being freed with the kexec 'unload'. With this patch IMA is allocating a buffer for the measurement list, which needs to be freed independently of the kexec 'unload'.

Quoted 6 lines

If we end up allocating the buffer at kexec ‘execute’ (which results in soft boot to next Kernel) – is it technically possible that kexec ‘unload’ being called after calling kexec ‘execute’?

If not, should I still free the buffer at kexec ‘unload’ in this scenario?

The question is how to access the buffer once kexec_add_buffer() is called.

Mimi

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#5 lore raw

Re: [PATCH 01/10] ima: implement function to allocate buffer at kexec load

Quoted 24 lines · Mimi Zohar
Quoted 14 lines · Tushar Sugandhi

Adding Eric to cc.

Quoted 11 lines · Mimi Zohar

Hi Tushar,

Quoted 2 lines · Tushar Sugandhi

IMA does not provide a mechanism to allocate memory for IMA log storage during kexec operation.

The IMA measurement list is currently being carried across kexec, so obviously a buffer is being allocated for it. IMA not allocating memory for the measurment list is not the problem statement. Please concisely provide the problem statement, explaining why IMA needs to allocate the buffer.

Quoted 3 lines

I meant IMA does not provide separate functions to allocate buffer and populate measurements. Both operations are wrapped in an atomic ima_dump_measurement_list().

Ok.

Quoted 4 lines

As I mentioned in the comment in the cover letter, if there is no such technical limitation to allocate the buffer and copy the measurements at kexec ‘execute’ – I will make the necessary code changes and update the above line in the patch description accordingly.

Quoted 6 lines

The "normal" way of making this type of change would be to split the existing ima_dump_measurement_list() function. Copying the measurement list would still be named ima_dump_measurement_list(). The other could be named ima_alloc_kexec_buf(). Both functions initially would be called.

Sounds good.  I will make that change.
I will define ima_alloc_kexec_buf() to allocate memory at kexec 'load'. And update ima_dump_measurement_list() to only copy the measurements.

Both the functions will be called during kexec 'load'.

And only the updated ima_dump_measurement_list() will be called during kexec 'execute'.

Please correct me if I misunderstood.

BTW, as discussed elsewhere I am hoping to get clarity on if we can move everything (memory allocation and copying measurements) to kexec 'execute'.

My current understanding is segment mapping must happen at kexec 'load'. Hopefully someone on this thread can validate if its true or not.

Quoted 3 lines

Eric, besides updating the buffer at kexec execute, is there anything else that needs to be done (e.g. updating digests)?

I will also wait for his response. :)

Quoted 14 lines
Quoted 10 lines
Quoted 5 lines
Quoted 2 lines

The function should handle the scenario where
the kexec load is called multiple times.

Currently the buffer is being freed with the kexec 'unload'. With this patch IMA is allocating a buffer for the measurement list, which needs to be freed independently of the kexec 'unload'.

If we end up allocating the buffer at kexec ‘execute’ (which results in soft boot to next Kernel) – is it technically possible that kexec ‘unload’ being called after calling kexec ‘execute’? If not, should I still free the buffer at kexec ‘unload’ in this scenario?

The question is how to access the buffer once kexec_add_buffer() is called.

Mimi

#6 lore raw

PATCH 2/10 ima: implement function to populate buffer at kexec execute

In reply to Tushar Sugandhi

There is no existing IMA functionality to just populate the buffer at kexec execute with IMA measurements.

Implement a function to iterate over ima_measurements and populate the ima_kexec_file buffer. After the loop, populate ima_khdr with buffer details (version, buffer size, number of measurements). Copy the ima_khdr data into ima_kexec_file.buf and update buffer_size and buffer.

The patch assumes that the ima_kexec_file.size is sufficient to hold all the measurements. It returns an error and does not handle scenarios where additional space might be needed.

---
 security/integrity/ima/ima_kexec.c | 52 ++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)
security/integrity/ima/ima_kexec.c +52 -0
index 48a683874044..858b67689701 100644
@@ -62,6 +62,58 @@ static int ima_allocate_buf_at_kexec_load(void)
 	return 0;
 }
 
+static int ima_populate_buf_at_kexec_execute(unsigned long *buffer_size, void **buffer)
+{
+	struct ima_queue_entry *qe;
+	int ret = 0;
+
+	/*
+	 * Ensure the kexec buffer is large enough to hold ima_khdr
+	 */
+	if (ima_kexec_file.size < sizeof(ima_khdr)) {
+		pr_err("%s: Kexec buffer size too low to hold ima_khdr\n",
+			__func__);
+		ima_clear_kexec_file();
+		return -ENOMEM;
+	}
+
+	list_for_each_entry_rcu(qe, &ima_measurements, later) {
+		if (ima_kexec_file.count < ima_kexec_file.size) {
+			ima_khdr.count++;
+			ima_measurements_show(&ima_kexec_file, qe);
+		} else {
+			ret = -ENOMEM;
+			pr_err("%s: Kexec ima_measurements buffer too small\n",
+				__func__);
+			break;
+		}
+	}
+	if (ret < 0)
+		goto out;
+
+	/*
+	 * fill in reserved space with some buffer details
+	 * (eg. version, buffer size, number of measurements)
+	 */
+	ima_khdr.buffer_size = ima_kexec_file.count;
+	if (ima_canonical_fmt) {
+		ima_khdr.version = cpu_to_le16(ima_khdr.version);
+		ima_khdr.count = cpu_to_le64(ima_khdr.count);
+		ima_khdr.buffer_size = cpu_to_le64(ima_khdr.buffer_size);
+	}
+
+	memcpy(ima_kexec_file.buf, &ima_khdr, sizeof(ima_khdr));
+	*buffer_size = ima_kexec_file.count;
+	*buffer = ima_kexec_file.buf;
+
+out:
+	if (ret < 0)
+		ima_clear_kexec_file();
+
+	return ret;
+}
+
+
 static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
 				     unsigned long segment_size)
 {
Signature · 1 line
2.25.1
maintainer
#7 lore raw

Re: [PATCH 02/10] ima: implement function to populate buffer at kexec execute

Hi Tushar,

Quoted 2 lines · Tushar Sugandhi

There is no existing IMA functionality to just populate the buffer at kexec execute with IMA measurements.

The same function that copies the measurement list at kexec 'load',
could be re-used at kexec 'exec'. Why is a new function that is very
similar to the existing ima_dump_measurement_list() needed?

Quoted 79 lines

Implement a function to iterate over ima_measurements and populate the ima_kexec_file buffer. After the loop, populate ima_khdr with buffer details (version, buffer size, number of measurements). Copy the ima_khdr data into ima_kexec_file.buf and update buffer_size and buffer.

The patch assumes that the ima_kexec_file.size is sufficient to hold all the measurements. It returns an error and does not handle scenarios where additional space might be needed.

---
 security/integrity/ima/ima_kexec.c | 52 ++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)
security/integrity/ima/ima_kexec.c +51 -0
index 48a683874044..858b67689701 100644
@@ -62,6 +62,58 @@ static int ima_allocate_buf_at_kexec_load(void)
 	return 0;
 }
 
+static int ima_populate_buf_at_kexec_execute(unsigned long *buffer_size, void **buffer)
+{
+	struct ima_queue_entry *qe;
+	int ret = 0;
+
+	/*
+	 * Ensure the kexec buffer is large enough to hold ima_khdr
+	 */
+	if (ima_kexec_file.size < sizeof(ima_khdr)) {
+		pr_err("%s: Kexec buffer size too low to hold ima_khdr\n",
+			__func__);
+		ima_clear_kexec_file();
+		return -ENOMEM;
+	}
+
+	list_for_each_entry_rcu(qe, &ima_measurements, later) {
+		if (ima_kexec_file.count < ima_kexec_file.size) {
+			ima_khdr.count++;
+			ima_measurements_show(&ima_kexec_file, qe);
+		} else {
+			ret = -ENOMEM;
+			pr_err("%s: Kexec ima_measurements buffer too small\n",
+				__func__);
+			break;
+		}
+	}
+	if (ret < 0)
+		goto out;
+
+	/*
+	 * fill in reserved space with some buffer details
+	 * (eg. version, buffer size, number of measurements)
+	 */
+	ima_khdr.buffer_size = ima_kexec_file.count;
+	if (ima_canonical_fmt) {
+		ima_khdr.version = cpu_to_le16(ima_khdr.version);
+		ima_khdr.count = cpu_to_le64(ima_khdr.count);
+		ima_khdr.buffer_size = cpu_to_le64(ima_khdr.buffer_size);
+	}
+
+	memcpy(ima_kexec_file.buf, &ima_khdr, sizeof(ima_khdr));
+	*buffer_size = ima_kexec_file.count;
+	*buffer = ima_kexec_file.buf;
+
+out:
+	if (ret < 0)
+		ima_clear_kexec_file();
+
+	return ret;
+}
+

b+
static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
unsigned long segment_size)
{

Signature · 9 lines
thanks,

Mimi


_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
#8 lore raw

Re: [PATCH 02/10] ima: implement function to populate buffer at kexec execute

Adding Eric to cc.

Quoted 8 lines · Mimi Zohar

Hi Tushar,

Quoted 2 lines · Tushar Sugandhi

There is no existing IMA functionality to just populate the buffer at kexec execute with IMA measurements.

The same function that copies the measurement list at kexec 'load',
could be re-used at kexec 'exec'. Why is a new function that is very
similar to the existing ima_dump_measurement_list() needed?

The current implementation of ima_dump_measurement_list() does both -
(1) allocation of buffer and (2) copying the measurements at kexec ‘load’.

The goal is to copy the measurements at kexec ‘execute’.

As I mentioned earlier, my understanding is the buffer must be allocated at kexec ‘load’ time.  And the segment size cannot change between kexec ‘load’ and kexec ‘execute’.

That’s why I believe the two new functions are needed. So I split the functionality in ima_dump_measurement_list() into two functions –
 (1) ima_allocate_buf_at_kexec_load() in patch 01/10 and
 (2) ima_populate_buf_at_kexec_execute()  in patch 02/10

and then deprecated ima_dump_measurement_list() in patch 7/10.

If I call ima_dump_measurement_list() both at kexec ‘load’ as well as kexec ‘execute’, it will result in double memory allocation.

As you said, if the functionality can be achieved by simply moving ima_dump_measurement_list() from kexec ‘load’ to kexec ‘execute’ – then you are right, we don’t need the two separate functions.

~Tushar

Quoted 79 lines
Quoted 79 lines

Implement a function to iterate over ima_measurements and populate the ima_kexec_file buffer. After the loop, populate ima_khdr with buffer details (version, buffer size, number of measurements). Copy the ima_khdr data into ima_kexec_file.buf and update buffer_size and buffer.

The patch assumes that the ima_kexec_file.size is sufficient to hold all the measurements. It returns an error and does not handle scenarios where additional space might be needed.

---
  security/integrity/ima/ima_kexec.c | 52 ++++++++++++++++++++++++++++++
  1 file changed, 52 insertions(+)
security/integrity/ima/ima_kexec.c +51 -0
index 48a683874044..858b67689701 100644
@@ -62,6 +62,58 @@ static int ima_allocate_buf_at_kexec_load(void)
  	return 0;
  }
 
+static int ima_populate_buf_at_kexec_execute(unsigned long *buffer_size, void **buffer)
+{
+	struct ima_queue_entry *qe;
+	int ret = 0;
+
+	/*
+	 * Ensure the kexec buffer is large enough to hold ima_khdr
+	 */
+	if (ima_kexec_file.size < sizeof(ima_khdr)) {
+		pr_err("%s: Kexec buffer size too low to hold ima_khdr\n",
+			__func__);
+		ima_clear_kexec_file();
+		return -ENOMEM;
+	}
+
+	list_for_each_entry_rcu(qe, &ima_measurements, later) {
+		if (ima_kexec_file.count < ima_kexec_file.size) {
+			ima_khdr.count++;
+			ima_measurements_show(&ima_kexec_file, qe);
+		} else {
+			ret = -ENOMEM;
+			pr_err("%s: Kexec ima_measurements buffer too small\n",
+				__func__);
+			break;
+		}
+	}
+	if (ret < 0)
+		goto out;
+
+	/*
+	 * fill in reserved space with some buffer details
+	 * (eg. version, buffer size, number of measurements)
+	 */
+	ima_khdr.buffer_size = ima_kexec_file.count;
+	if (ima_canonical_fmt) {
+		ima_khdr.version = cpu_to_le16(ima_khdr.version);
+		ima_khdr.count = cpu_to_le64(ima_khdr.count);
+		ima_khdr.buffer_size = cpu_to_le64(ima_khdr.buffer_size);
+	}
+
+	memcpy(ima_kexec_file.buf, &ima_khdr, sizeof(ima_khdr));
+	*buffer_size = ima_kexec_file.count;
+	*buffer = ima_kexec_file.buf;
+
+out:
+	if (ret < 0)
+		ima_clear_kexec_file();
+
+	return ret;
+}
+

b+
static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
unsigned long segment_size)
{

#9 lore raw

PATCH 3/10 ima: allocate buffer at kexec load to hold ima measurements

In reply to Tushar Sugandhi

The IMA subsystem needs a dedicated mechanism to reserve extra memory for measurements added between the kexec 'load' and kexec 'execute'.

Update ima_add_kexec_buffer to allocate a buffer of a sufficient size taking ima binary runtime measurements size, size of ima_kexec_hdr, and IMA_KEXEC_EXTRA_SIZE into account. Adjust the kexec_segment_size to align to the PAGE_SIZE. Call ima_allocate_buf_at_kexec_load() to allocate the buffer.

This patch assumes the extra space defined (IMA_KEXEC_EXTRA_SIZE) is sufficient to handle the additional measurements. This should be as per the system requirements and based on the number of additional measurements expected during the window from kexec 'load' to kexec 'execute'.

---
 security/integrity/ima/ima.h       |  2 ++
 security/integrity/ima/ima_kexec.c | 21 ++++++++++-----------
 2 files changed, 12 insertions(+), 11 deletions(-)
security/integrity/ima/ima.h +2 -0
index c29db699c996..2ffda9449b9b 100644
@@ -43,6 +43,8 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8, TPM_PCR10 = 10 };
 
 #define NR_BANKS(chip) ((chip != NULL) ? chip->nr_allocated_banks : 0)
 
+#define IMA_KEXEC_EXTRA_SIZE (16 * PAGE_SIZE)
+
 /* current content of the policy */
 extern int ima_policy_flag;
 
security/integrity/ima/ima_kexec.c +10 -11
index 858b67689701..7deb8df31485 100644
@@ -188,31 +188,30 @@ void ima_add_kexec_buffer(struct kimage *image)
 	/* use more understandable variable names than defined in kbuf */
 	void *kexec_buffer = NULL;
 	size_t kexec_buffer_size;
-	size_t kexec_segment_size;
 	int ret;
 
 	/*
-	 * Reserve an extra half page of memory for additional measurements
-	 * added during the kexec load.
+	 * Reserve extra memory for measurements added in the window from
+	 * kexec 'load' to kexec 'execute'.
 	 */
-	binary_runtime_size = ima_get_binary_runtime_size();
+	binary_runtime_size = ima_get_binary_runtime_size() +
+			      sizeof(struct ima_kexec_hdr) +
+			      IMA_KEXEC_EXTRA_SIZE;
+
 	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");
 		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");
+	ret = ima_allocate_buf_at_kexec_load();
+	if (ret < 0)
 		return;
-	}
 
 	kbuf.buffer = kexec_buffer;
 	kbuf.bufsz = kexec_buffer_size;
Signature · 1 line
2.25.1
maintainer
#10 lore raw

Re: [PATCH 03/10] ima: allocate buffer at kexec load to hold ima measurements

Hi Tushar,

The function to "ima: allocate buffer at kexec load to hold ima measurements" already exists. Please update the Subject line to indicate increasing the IMA kexec buffer size.

Quoted 2 lines · Tushar Sugandhi

The IMA subsystem needs a dedicated mechanism to reserve extra memory for measurements added between the kexec 'load' and kexec 'execute'.

What is a "dedicated mechanism?". Either start the sentence with "reserve ..." or completely remove it.

Quoted 5 lines

Update ima_add_kexec_buffer to allocate a buffer of a sufficient size taking ima binary runtime measurements size, size of ima_kexec_hdr, and IMA_KEXEC_EXTRA_SIZE into account. Adjust the kexec_segment_size to align to the PAGE_SIZE. Call ima_allocate_buf_at_kexec_load() to allocate the buffer.

The size of the ima_kexec_hdr kind of gets lost in the amount of additional memory being allocated, but sure it's a nice clean up.

Quoted 4 lines

This patch assumes the extra space defined (IMA_KEXEC_EXTRA_SIZE) is sufficient to handle the additional measurements. This should be as per the system requirements and based on the number of additional measurements expected during the window from kexec 'load' to kexec 'execute'.

Should the extra amount of memory be hard coded?

Quoted 11 lines
---
 security/integrity/ima/ima.h       |  2 ++
 security/integrity/ima/ima_kexec.c | 21 ++++++++++-----------
 2 files changed, 12 insertions(+), 11 deletions(-)
security/integrity/ima/ima.h +0 -0
index c29db699c996..2ffda9449b9b 100644

security/integrity/ima/ima.h enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8, TPM_PCR10 = 10 }; · line 47

Quoted 5 lines
security/integrity/ima/ima.h +1 -0
@@ -43,6 +43,8 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8, TPM_PCR10 = 10 };
 
 #define NR_BANKS(chip) ((chip != NULL) ? chip->nr_allocated_banks : 0)
 
+#define IMA_KEXEC_EXTRA_SIZE (16 * PAGE_SIZE)
 

Not all IMA policies require extra memory. Define and use a new IMA Kconfig to set the amount of extra memory.

Quoted 30 lines
security/integrity/ima/ima.h +0 -0
 /* current content of the policy */
 extern int ima_policy_flag;
security/integrity/ima/ima_kexec.c +6 -6
index 858b67689701..7deb8df31485 100644
@@ -188,31 +188,30 @@ void ima_add_kexec_buffer(struct kimage *image)
 	/* use more understandable variable names than defined in kbuf */
 	void *kexec_buffer = NULL;
 	size_t kexec_buffer_size;
-	size_t kexec_segment_size;
 	int ret;
 
 	/*
-	 * Reserve an extra half page of memory for additional measurements
-	 * added during the kexec load.
+	 * Reserve extra memory for measurements added in the window from
+	 * kexec 'load' to kexec 'execute'.
 	 */
-	binary_runtime_size = ima_get_binary_runtime_size();
+	binary_runtime_size = ima_get_binary_runtime_size() +
+			      sizeof(struct ima_kexec_hdr) +
+			      IMA_KEXEC_EXTRA_SIZE;
+
 	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);

security/integrity/ima/ima_kexec.c void ima_add_kexec_buffer(struct kimage *image) · line 211

Quoted 10 lines
security/integrity/ima/ima_kexec.c +2 -2
+		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");
 		return;
 	}
 
-	ima_dump_measurement_list(&kexec_buffer_size, &kexec_buffer,
-				  kexec_segment_size);

Removing the call to ima_dump_measurement_list here is not bisect safe.

Quoted 9 lines
security/integrity/ima/ima_kexec.c +2 -3
-	if (!kexec_buffer) {
-		pr_err("Not enough memory for the kexec measurement buffer.\n");
+	ret = ima_allocate_buf_at_kexec_load();
+	if (ret < 0)
 		return;
-	}
 
 	kbuf.buffer = kexec_buffer;
 	kbuf.bufsz = kexec_buffer_size;
Signature · 9 lines
thanks,

Mimi


_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
#11 lore raw

Re: [PATCH 03/10] ima: allocate buffer at kexec load to hold ima measurements

Adding Eric to cc.

Quoted 6 lines · Mimi Zohar

Hi Tushar,

The function to "ima: allocate buffer at kexec load to hold ima measurements" already exists. Please update the Subject line to indicate increasing the IMA kexec buffer size.

Quoted 6 lines
Quoted 2 lines · Tushar Sugandhi

The IMA subsystem needs a dedicated mechanism to reserve extra memory for measurements added between the kexec 'load' and kexec 'execute'.

What is a "dedicated mechanism?". Either start the sentence with "reserve ..." or completely remove it.

Will do.

Quoted 7 lines
Quoted 5 lines

Update ima_add_kexec_buffer to allocate a buffer of a sufficient size taking ima binary runtime measurements size, size of ima_kexec_hdr, and IMA_KEXEC_EXTRA_SIZE into account. Adjust the kexec_segment_size to align to the PAGE_SIZE. Call ima_allocate_buf_at_kexec_load() to allocate the buffer.

The size of the ima_kexec_hdr kind of gets lost in the amount of additional memory being allocated, but sure it's a nice clean up.

Thanks. :)

Quoted 6 lines
Quoted 4 lines

This patch assumes the extra space defined (IMA_KEXEC_EXTRA_SIZE) is sufficient to handle the additional measurements. This should be as per the system requirements and based on the number of additional measurements expected during the window from kexec 'load' to kexec 'execute'.

Should the extra amount of memory be hard coded?

You are right.  As you suggested below, defining the extra amount in Kconfig is a cleaner approach.

Quoted 12 lines
Quoted 12 lines
---
  security/integrity/ima/ima.h       |  2 ++
  security/integrity/ima/ima_kexec.c | 21 ++++++++++-----------
  2 files changed, 12 insertions(+), 11 deletions(-)
security/integrity/ima/ima.h +0 -0
index c29db699c996..2ffda9449b9b 100644
@@ -43,6 +43,8 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8, TPM_PCR10 = 10 };
 
Quoted 6 lines

security/integrity/ima/ima.h enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8, TPM_PCR10 = 10 }; · line 50

Quoted 4 lines
security/integrity/ima/ima.h +1 -0
  #define NR_BANKS(chip) ((chip != NULL) ? chip->nr_allocated_banks : 0)
 
+#define IMA_KEXEC_EXTRA_SIZE (16 * PAGE_SIZE)
 

Not all IMA policies require extra memory. Define and use a new IMA Kconfig to set the amount of extra memory.

Sure.  Will do.

Quoted 38 lines
Quoted 38 lines
security/integrity/ima/ima.h +0 -0
  /* current content of the policy */
  extern int ima_policy_flag;
security/integrity/ima/ima_kexec.c +8 -6
index 858b67689701..7deb8df31485 100644
@@ -188,31 +188,30 @@ void ima_add_kexec_buffer(struct kimage *image)
  	/* use more understandable variable names than defined in kbuf */
  	void *kexec_buffer = NULL;
  	size_t kexec_buffer_size;
-	size_t kexec_segment_size;
  	int ret;
 
  	/*
-	 * Reserve an extra half page of memory for additional measurements
-	 * added during the kexec load.
+	 * Reserve extra memory for measurements added in the window from
+	 * kexec 'load' to kexec 'execute'.
  	 */
-	binary_runtime_size = ima_get_binary_runtime_size();
+	binary_runtime_size = ima_get_binary_runtime_size() +
+			      sizeof(struct ima_kexec_hdr) +
+			      IMA_KEXEC_EXTRA_SIZE;
+
  	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");
  		return;
  	}
 
Quoted 3 lines

security/integrity/ima/ima_kexec.c void ima_add_kexec_buffer(struct kimage *image) · line 211

Quoted 2 lines
security/integrity/ima/ima_kexec.c +0 -2
-	ima_dump_measurement_list(&kexec_buffer_size, &kexec_buffer,
-				  kexec_segment_size);

Removing the call to ima_dump_measurement_list here is not bisect safe.

Agreed.  Will take care of this based on if we end up using just ima_dump_measurement_list(), or combination of ima_allocate_buf_at_kexec_load() and ima_populate_buf_at_kexec_execute().

~Tushar

Quoted 9 lines
Quoted 9 lines
security/integrity/ima/ima_kexec.c +2 -3
-	if (!kexec_buffer) {
-		pr_err("Not enough memory for the kexec measurement buffer.\n");
+	ret = ima_allocate_buf_at_kexec_load();
+	if (ret < 0)
  		return;
-	}
 
  	kbuf.buffer = kexec_buffer;
  	kbuf.bufsz = kexec_buffer_size;
#12 lore raw

Re: [PATCH 03/10] ima: allocate buffer at kexec load to hold ima measurements

In reply to Tushar Sugandhi
Quoted 9 lines · Tushar Sugandhi

The IMA subsystem needs a dedicated mechanism to reserve extra memory for measurements added between the kexec 'load' and kexec 'execute'.

Update ima_add_kexec_buffer to allocate a buffer of a sufficient size taking ima binary runtime measurements size, size of ima_kexec_hdr, and IMA_KEXEC_EXTRA_SIZE into account. Adjust the kexec_segment_size to align to the PAGE_SIZE. Call ima_allocate_buf_at_kexec_load() to allocate the buffer.

Quoted 4 lines

This patch assumes the extra space defined (IMA_KEXEC_EXTRA_SIZE) is sufficient to handle the additional measurements. This should be as per the system requirements and based on the number of additional measurements expected during the window from kexec 'load' to kexec 'execute'.

This could be the most problematic part if the 'execute' happens much later than the 'load' with lots of measurement activity in between. I am wondering whether not doing anything at 'load' time and doing the whole work at 'execute' time wouldn't be the right thing to do ?

Otherwise, if we wanted the work to be split as you suggest, could you
- krealloc the src_pages (now in kimage_map_segment) to add space for a few more pages needed for the additional measurements
- add those few more pages to src_pages
- vunmap the previous mapping
- vmap the extended src_pages array
- update ima_kexec_file.buf with the diff between the new and old vmap'ed addresses
- append to the existing log

This presumably would help resolve this potential issue.

The src_pages is currently not kfree'd -- may be a memory leak.

Regards,
Stefan

Quoted 56 lines
---
  security/integrity/ima/ima.h       |  2 ++
  security/integrity/ima/ima_kexec.c | 21 ++++++++++-----------
  2 files changed, 12 insertions(+), 11 deletions(-)
security/integrity/ima/ima.h +2 -0
index c29db699c996..2ffda9449b9b 100644
@@ -43,6 +43,8 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8, TPM_PCR10 = 10 };
 
  #define NR_BANKS(chip) ((chip != NULL) ? chip->nr_allocated_banks : 0)
 
+#define IMA_KEXEC_EXTRA_SIZE (16 * PAGE_SIZE)
+
  /* current content of the policy */
  extern int ima_policy_flag;
 
security/integrity/ima/ima_kexec.c +8 -7
index 858b67689701..7deb8df31485 100644
@@ -188,31 +188,30 @@ void ima_add_kexec_buffer(struct kimage *image)
  	/* use more understandable variable names than defined in kbuf */
  	void *kexec_buffer = NULL;
  	size_t kexec_buffer_size;
-	size_t kexec_segment_size;
  	int ret;
 
  	/*
-	 * Reserve an extra half page of memory for additional measurements
-	 * added during the kexec load.
+	 * Reserve extra memory for measurements added in the window from
+	 * kexec 'load' to kexec 'execute'.
  	 */
-	binary_runtime_size = ima_get_binary_runtime_size();
+	binary_runtime_size = ima_get_binary_runtime_size() +
+			      sizeof(struct ima_kexec_hdr) +
+			      IMA_KEXEC_EXTRA_SIZE;
+
  	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");
  		return;
  	}
 
-	ima_dump_measurement_list(&kexec_buffer_size, &kexec_buffer,

security/integrity/ima/ima_kexec.c void ima_add_kexec_buffer(struct kimage *image) · line 217

Quoted 10 lines
security/integrity/ima/ima_kexec.c +2 -4
-				  kexec_segment_size);
-	if (!kexec_buffer) {
-		pr_err("Not enough memory for the kexec measurement buffer.\n");
+	ret = ima_allocate_buf_at_kexec_load();
+	if (ret < 0)
  		return;
-	}
 
  	kbuf.buffer = kexec_buffer;
  	kbuf.bufsz = kexec_buffer_size;

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#13 lore raw

Re: [PATCH 03/10] ima: allocate buffer at kexec load to hold ima measurements

Quoted 12 lines · Stefan Berger
Quoted 9 lines · Tushar Sugandhi

The IMA subsystem needs a dedicated mechanism to reserve extra memory for measurements added between the kexec 'load' and kexec 'execute'.

Update ima_add_kexec_buffer to allocate a buffer of a sufficient size taking ima binary runtime measurements size, size of ima_kexec_hdr, and IMA_KEXEC_EXTRA_SIZE into account.  Adjust the kexec_segment_size to align to the PAGE_SIZE.  Call ima_allocate_buf_at_kexec_load() to allocate the buffer.

Quoted 8 lines
Quoted 4 lines

This patch assumes the extra space defined (IMA_KEXEC_EXTRA_SIZE) is sufficient to handle the additional measurements.  This should be as per the system requirements and based on the number of additional measurements expected during the window from kexec 'load' to kexec 'execute'.

This could be the most problematic part if the 'execute' happens much later than the 'load' with lots of measurement activity in between. I am wondering whether not doing anything at 'load' time and doing the whole work at 'execute' time

Technically I don't want to do anything at kexec 'load' time.
But as I said elsewhere in this series, I am under impression that segment allocation must happen at kexec 'load' time.

But if that understanding is wrong - then we can move the entire logic to kexec 'execute' time.

I am currently trying to validate if moving the logic to kexec 'execute' works.

Quoted 12 lines

wouldn't be the right thing to do ?

Otherwise, if we wanted the work to be split as you suggest, could you
- krealloc the src_pages (now in kimage_map_segment) to add space for a few more pages needed for the additional measurements
- add those few more pages to src_pages
- vunmap the previous mapping
- vmap the extended src_pages array
- update ima_kexec_file.buf with the diff between the new and old vmap'ed addresses
- append to the existing log

Quoted 1 line

This presumably would help resolve this potential issue.

Thanks for the detailed thoughts.
I will investigate if this approach is needed, based on my comment above. If it is needed and feasible, I will incorporate it in the next iteration.

Thanks again.

~Tushar

Quoted 68 lines

The src_pages is currently not kfree'd -- may be a memory leak.

Regards,
   Stefan

Quoted 62 lines

---
  security/integrity/ima/ima.h       |  2 ++ security/integrity/ima/ima_kexec.c | 21 ++++++++++-----------

  2 files changed, 12 insertions(+), 11 deletions(-)
security/integrity/ima/ima.h +1 -0
index c29db699c996..2ffda9449b9b 100644
@@ -43,6 +43,8 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8, 
 TPM_PCR10 = 10 };
     #define NR_BANKS(chip) ((chip != NULL) ? chip->nr_allocated_banks : 0)
   +#define IMA_KEXEC_EXTRA_SIZE (16 * PAGE_SIZE)
+
   /* current content of the policy */
   extern int ima_policy_flag;

  diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c index 858b67689701..7deb8df31485 100644

security/integrity/ima/ima_kexec.c +6 -4
@@ -188,31 +188,30 @@ void ima_add_kexec_buffer(struct kimage *image)
       /* use more understandable variable names than defined in kbuf */
       void *kexec_buffer = NULL;
       size_t kexec_buffer_size;
-    size_t kexec_segment_size;
       int ret;
         /*
-     * Reserve an extra half page of memory for additional measurements
-     * added during the kexec load.
+     * Reserve extra memory for measurements added in the window from
+     * kexec 'load' to kexec 'execute'.
        */
-    binary_runtime_size = ima_get_binary_runtime_size();
+    binary_runtime_size = ima_get_binary_runtime_size() +
+                  sizeof(struct ima_kexec_hdr) +
+                  IMA_KEXEC_EXTRA_SIZE;
+
       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"); 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");
+    ret = ima_allocate_buf_at_kexec_load();
+    if (ret < 0)
          return;
-    }
        kbuf.buffer = kexec_buffer;
      kbuf.bufsz = kexec_buffer_size;

#14 lore raw

PATCH 4/10 ima: implement functions to suspend and resume measurements

In reply to Tushar Sugandhi

The IMA subsystem needs to provide a mechanism to suspend or resume measurements. This functionality is needed to temporarily halt the recording of IMA measurements during certain system operations.

Add functions ima_measurements_suspend() and ima_measurements_resume() functions to set and reset the suspend_ima_measurements variable, respectively, to suspend/resume IMA measurements. Use ima_extend_list_mutex to ensure that the operations are thread-safe.

Note: Use ima_measurements_suspend() and ima_measurements_resume() in pairs to avoid indefinitely suspending IMA measurements.

---
 security/integrity/ima/ima.h       |  2 ++
 security/integrity/ima/ima_queue.c | 19 +++++++++++++++++++
 2 files changed, 21 insertions(+)
security/integrity/ima/ima.h +2 -0
index 2ffda9449b9b..7127c5cf1909 100644
@@ -163,6 +163,8 @@ bool ima_template_has_modsig(const struct ima_template_desc *ima_template);
 int ima_restore_measurement_entry(struct ima_template_entry *entry);
 int ima_restore_measurement_list(loff_t bufsize, void *buf);
 int ima_measurements_show(struct seq_file *m, void *v);
+void ima_measurements_suspend(void);
+void ima_measurements_resume(void);
 unsigned long ima_get_binary_runtime_size(void);
 int ima_init_template(void);
 void ima_init_template_list(void);
security/integrity/ima/ima_queue.c +19 -0
index 532da87ce519..cb9abc02a304 100644
@@ -44,6 +44,11 @@ struct ima_h_table ima_htable = {
  */
 static DEFINE_MUTEX(ima_extend_list_mutex);
 
+/*
+ * Used internally by the kernel to suspend-resume ima measurements.
+ */
+static atomic_t suspend_ima_measurements;
+
 /* lookup up the digest value in the hash table, and return the entry */
 static struct ima_queue_entry *ima_lookup_digest_entry(u8 *digest_value,
 						       int pcr)
@@ -148,6 +153,20 @@ static int ima_pcr_extend(struct tpm_digest *digests_arg, int pcr)
 	return result;
 }
 
+void ima_measurements_suspend(void)
+{
+	mutex_lock(&ima_extend_list_mutex);
+	atomic_set(&suspend_ima_measurements, 1);
+	mutex_unlock(&ima_extend_list_mutex);
+}
+
+void ima_measurements_resume(void)
+{
+	mutex_lock(&ima_extend_list_mutex);
+	atomic_set(&suspend_ima_measurements, 0);
+	mutex_unlock(&ima_extend_list_mutex);
+}
+
 /*
  * Add template entry to the measurement list and hash table, and
  * extend the pcr.
Signature · 1 line
2.25.1
#15 lore raw

PATCH 5/10 kexec: implement functions to map and unmap segment to kimage

In reply to Tushar Sugandhi

Currently, there's no mechanism to map and unmap segments to the kimage structure. This functionality is needed when dealing with memory segments in the context of a kexec operation.

The patch adds two new functions: kimage_map_segment() and kimage_unmap_segment().

Implement kimage_map_segment() which takes a kimage pointer, an address, and a size. Ensures that the entire segment is being mapped by comparing the given address and size to each segment in the kimage's segment array. Collect the source pages that correspond to the given address range, allocate an array of pointers to these pages, and map them to a contiguous range of virtual addresses. If the mapping operation is successful, the function returns the start of this range. Otherwise, it frees the page pointer array and returns NULL.

Implement kimage_unmap_segment() that takes a pointer to a segment buffer and unmaps it using vunmap().

Finally, move for_each_kimage_entry() macro to kexec.h.

Note: Use kimage_map_segment() and kimage_unmap_segment() carefully to avoid memory leaks and ensure that all mapped segments are properly unmapped when they're no longer needed.

---
 include/linux/kexec.h | 13 ++++++++
 kernel/kexec_core.c   | 72 ++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 80 insertions(+), 5 deletions(-)
include/linux/kexec.h +13 -0
index 22b5cd24f581..e00b8101b53b 100644
@@ -490,6 +490,15 @@ static inline int arch_kexec_post_alloc_pages(void *vaddr, unsigned int pages, g
 static inline void arch_kexec_pre_free_pages(void *vaddr, unsigned int pages) { }
 #endif
 
+#define for_each_kimage_entry(image, ptr, entry) \
+	for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); \
+		ptr = (entry & IND_INDIRECTION) ? \
+			boot_phys_to_virt((entry & PAGE_MASK)) : ptr + 1)
+
+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;
@@ -497,6 +506,10 @@ 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 */
 
kernel/kexec_core.c +67 -5

84 lines not on this page · raw message

Signature · 1 line
2.25.1
#16 lore raw

Re: [PATCH 05/10] kexec: implement functions to map and unmap segment to kimage

Quoted 27 lines · Tushar Sugandhi

Currently, there's no mechanism to map and unmap segments to the kimage structure. This functionality is needed when dealing with memory segments in the context of a kexec operation.

The patch adds two new functions: kimage_map_segment() and kimage_unmap_segment().

Implement kimage_map_segment() which takes a kimage pointer, an address, and a size. Ensures that the entire segment is being mapped by comparing the given address and size to each segment in the kimage's segment array. Collect the source pages that correspond to the given address range, allocate an array of pointers to these pages, and map them to a contiguous range of virtual addresses. If the mapping operation is successful, the function returns the start of this range. Otherwise, it frees the page pointer array and returns NULL.

Implement kimage_unmap_segment() that takes a pointer to a segment buffer and unmaps it using vunmap().

Finally, move for_each_kimage_entry() macro to kexec.h.

Note: Use kimage_map_segment() and kimage_unmap_segment() carefully to avoid memory leaks and ensure that all mapped segments are properly unmapped when they're no longer needed.

kernel/kexec_core.c int kimage_load_segment(struct kimage *image, · line 962

Quoted 9 lines
kernel/kexec_core.c +9 -0
+
+	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++] = phys_to_page(src_page_addr);

Since phys_to_page is not defined on many/most architectures I change it for ppc64 and have successfully used the following:

+ src_pages[i++] = virt_to_page(__va(src_page_addr))

After several kexecs the following check still works:

# evmctl ima_measurement --ignore-violations /sys/kernel/security/ima/binary_runtime_measurements
Matched per TPM bank calculated digest(s).

Stefan

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#17 lore raw

Re: [PATCH 05/10] kexec: implement functions to map and unmap segment to kimage

Adding Eric to cc.

Quoted 46 lines · Stefan Berger
Quoted 27 lines · Tushar Sugandhi

Currently, there's no mechanism to map and unmap segments to the kimage structure.  This functionality is needed when dealing with memory segments in the context of a kexec operation.

The patch adds two new functions: kimage_map_segment() and kimage_unmap_segment().

Implement kimage_map_segment() which takes a kimage pointer, an address, and a size.  Ensures that the entire segment is being mapped by comparing the given address and size to each segment in the kimage's segment array. Collect the source pages that correspond to the given address range, allocate an array of pointers to these pages, and map them to a contiguous range of virtual addresses.  If the mapping operation is successful, the function returns the start of this range.  Otherwise, it frees the page pointer array and returns NULL.

Implement kimage_unmap_segment() that takes a pointer to a segment buffer and unmaps it using vunmap().

Finally, move for_each_kimage_entry() macro to kexec.h.

Note: Use kimage_map_segment() and kimage_unmap_segment() carefully to avoid memory leaks and ensure that all mapped segments are properly unmapped when they're no longer needed.

Quoted 9 lines

+
+    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++] = phys_to_page(src_page_addr);

Since phys_to_page is not defined on many/most architectures I change it for ppc64 and have successfully used the following:

+                               src_pages[i++] =
virt_to_page(__va(src_page_addr))

Quoted 7 lines

After several kexecs the following check still works:

# evmctl ima_measurement --ignore-violations /sys/kernel/security/ima/binary_runtime_measurements
Matched per TPM bank calculated digest(s).

   Stefan

Thank you so much Stefan for reviewing this series, and catching this issue.  Are you suggesting I should use virt_to_page on all architectures unconditionally, or use it only when phys_to_page is not available?

~Tushar

#18 lore raw

Re: [PATCH 05/10] kexec: implement functions to map and unmap segment to kimage

Quoted 50 lines · Tushar Sugandhi

Adding Eric to cc.

Quoted 47 lines · Stefan Berger
Quoted 27 lines · Tushar Sugandhi

Currently, there's no mechanism to map and unmap segments to the kimage structure.  This functionality is needed when dealing with memory segments in the context of a kexec operation.

The patch adds two new functions: kimage_map_segment() and kimage_unmap_segment().

Implement kimage_map_segment() which takes a kimage pointer, an address, and a size.  Ensures that the entire segment is being mapped by comparing the given address and size to each segment in the kimage's segment array. Collect the source pages that correspond to the given address range, allocate an array of pointers to these pages, and map them to a contiguous range of virtual addresses.  If the mapping operation is successful, the function returns the start of this range.  Otherwise, it frees the page pointer array and returns NULL.

Implement kimage_unmap_segment() that takes a pointer to a segment buffer and unmaps it using vunmap().

Finally, move for_each_kimage_entry() macro to kexec.h.

Note: Use kimage_map_segment() and kimage_unmap_segment() carefully to avoid memory leaks and ensure that all mapped segments are properly unmapped when they're no longer needed.

Quoted 9 lines

+
+    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++] = phys_to_page(src_page_addr);

Since phys_to_page is not defined on many/most architectures I change it for ppc64 and have successfully used the following:

+                               src_pages[i++] = virt_to_page(__va(src_page_addr))

After several kexecs the following check still works:

Quoted 8 lines
Quoted 5 lines
# evmctl ima_measurement --ignore-violations /sys/kernel/security/ima/binary_runtime_measurements
Matched per TPM bank calculated digest(s).

   Stefan

Thank you so much Stefan for reviewing this series, and catching this issue.  Are you suggesting I should use virt_to_page on all architectures unconditionally, or use it only when phys_to_page is not available?

I would try to used it on all architectures.

Stefan

Quoted 7 lines

~Tushar

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#19 lore raw

Re: [PATCH 05/10] kexec: implement functions to map and unmap segment to kimage

Quoted 58 lines · Stefan Berger
Quoted 55 lines · Tushar Sugandhi

Adding Eric to cc.

Quoted 52 lines · Stefan Berger
Quoted 27 lines · Tushar Sugandhi

Currently, there's no mechanism to map and unmap segments to the kimage structure.  This functionality is needed when dealing with memory segments in the context of a kexec operation.

The patch adds two new functions: kimage_map_segment() and kimage_unmap_segment().

Implement kimage_map_segment() which takes a kimage pointer, an address, and a size.  Ensures that the entire segment is being mapped by comparing the given address and size to each segment in the kimage's segment array. Collect the source pages that correspond to the given address range, allocate an array of pointers to these pages, and map them to a contiguous range of virtual addresses.  If the mapping operation is successful, the function returns the start of this range.  Otherwise, it frees the page pointer array and returns NULL.

Implement kimage_unmap_segment() that takes a pointer to a segment buffer and unmaps it using vunmap().

Finally, move for_each_kimage_entry() macro to kexec.h.

Note: Use kimage_map_segment() and kimage_unmap_segment() carefully to avoid memory leaks and ensure that all mapped segments are properly unmapped when they're no longer needed.

Quoted 9 lines

+
+    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++] = phys_to_page(src_page_addr);

Since phys_to_page is not defined on many/most architectures I change it for ppc64 and have successfully used the following:

+                               src_pages[i++] =
virt_to_page(__va(src_page_addr))

After several kexecs the following check still works:

# evmctl ima_measurement --ignore-violations /sys/kernel/security/ima/binary_runtime_measurements
Matched per TPM bank calculated digest(s).
Quoted 9 lines
Quoted 4 lines
Quoted 1 line

   Stefan

Thank you so much Stefan for reviewing this series, and catching this issue.  Are you suggesting I should use virt_to_page on all architectures unconditionally, or use it only when phys_to_page is not available?

I would try to used it on all architectures.

   Stefan

Ok.  Thanks.

Quoted 7 lines
Quoted 7 lines

~Tushar

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#20 lore raw

PATCH 6/10 ima: update buffer at kexec execute with ima measurements

In reply to Tushar Sugandhi

In the current implementation, the measurement list is not updated in the buffer during the window between kexec load and execute. This leads to measurement loss in the buffer when transitioning from the old to the new kernel. This patch provides a way to update the measurement list in the buffer during a kexec execution. Suspending the measurements during the buffer update ensures the buffer doesn't get corrupted, or goes out of sync with TPM PCRs. Thus it ensures the integrity of measurements is maintained across kernel transitions during a kexec.

Introduce a new variable ima_kexec_buffer that is used to hold the address of the IMA kexec buffer.

Implement a function ima_update_kexec_buffer() that is called during kexec execute, allowing the IMA to update the measurement list with the events between kexec load and execute. First check if a kexec is in progress and if the IMA kexec buffer is initialized. If these conditions are met, suspend IMA measurements and check if the new buffer size obtained from ima_get_binary_runtime_size() is larger than the current buffer size. If the new buffer size is too large, output an error message, and resume the measurements.

If the new buffer size fits, populate the new buffer with the current measurements using ima_populate_buf_at_kexec_execute() and copy it into ima_kexec_buffer.

Unmap ima_kexec_buffer segment from the image. Resuming the measurements is not needed in case of successful measurements since the control is being passed to the new kernel anyways through kexec execute. However, the measurements should be resumed if there are any errors flagged in the function.

---
 security/integrity/ima/ima_kexec.c | 50 ++++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)
security/integrity/ima/ima_kexec.c +50 -0
index 7deb8df31485..224d88ccfe85 100644
@@ -18,6 +18,7 @@
 struct seq_file ima_kexec_file;
 struct ima_kexec_hdr ima_khdr;
 static size_t kexec_segment_size;
+static void *ima_kexec_buffer;
 
 void ima_clear_kexec_file(void)
 {
@@ -230,6 +231,55 @@ void ima_add_kexec_buffer(struct kimage *image)
 	pr_debug("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)
+{
+	void *new_buffer = NULL;
+	size_t new_buffer_size, cur_buffer_size;
+	bool resume = false;
+
+	if (!kexec_in_progress) {
+		pr_info("%s: No kexec in progress.\n", __func__);
+		return NOTIFY_OK;
+	}
+
+	if (!ima_kexec_buffer) {
+		pr_err("%s: Kexec buffer not set.\n", __func__);
+		return NOTIFY_OK;
+	}
+
+	ima_measurements_suspend();
+
+	cur_buffer_size = kexec_segment_size - sizeof(struct ima_kexec_hdr);
+	new_buffer_size = ima_get_binary_runtime_size();
+	if (new_buffer_size > cur_buffer_size) {
+		pr_err("%s: Measurement list grew too large.\n", __func__);
+		resume = true;
+		goto out;
+	}
+
+	ima_populate_buf_at_kexec_execute(&new_buffer_size, &new_buffer);
+
+	if (!new_buffer) {
+		pr_err("%s: Dump measurements failed.\n", __func__);
+		resume = true;
+		goto out;
+	}
+	memcpy(ima_kexec_buffer, new_buffer, new_buffer_size);
+out:
+	kimage_unmap_segment(ima_kexec_buffer);
+	ima_kexec_buffer = NULL;
+
+	if (resume)
+		ima_measurements_resume();
+
+	return NOTIFY_OK;
+}
+
 #endif /* IMA_KEXEC */
 
 /*
Signature · 1 line
2.25.1
maintainer
#21 lore raw

Re: [PATCH 06/10] ima: update buffer at kexec execute with ima measurements

Hi Tushar,

Quoted 19 lines · Tushar Sugandhi
security/integrity/ima/ima_kexec.c +19 -0
+/*
+ * 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)
+{
+	void *new_buffer = NULL;
+	size_t new_buffer_size, cur_buffer_size;
+	bool resume = false;
+
+	if (!kexec_in_progress) {
+		pr_info("%s: No kexec in progress.\n", __func__);
+		return NOTIFY_OK;
+	}
+
+	if (!ima_kexec_buffer) {
+		pr_err("%s: Kexec buffer not set.\n", __func__);
+		return NOTIFY_OK;
+	}

security/integrity/ima/ima_kexec.c void ima_add_kexec_buffer(struct kimage *image) · line 263

Quoted 10 lines
security/integrity/ima/ima_kexec.c +10 -0
+
+	ima_measurements_suspend();
+
+	cur_buffer_size = kexec_segment_size - sizeof(struct ima_kexec_hdr);
+	new_buffer_size = ima_get_binary_runtime_size();
+	if (new_buffer_size > cur_buffer_size) {
+		pr_err("%s: Measurement list grew too large.\n", __func__);
+		resume = true;
+		goto out;
+	}

This changes the current behavior of carrying as many measurements across kexec as possible. True the measurement list won't verify against the TPM PCRs, but not copying the measurements leaves the impression there weren't any previous measurements.

This also explains the reason for allocating an IMA buffer (patch 1/10) and not writing the measurements directly into the kexec buffer.

Quoted 21 lines
security/integrity/ima/ima_kexec.c +18 -0
+	ima_populate_buf_at_kexec_execute(&new_buffer_size, &new_buffer);
+
+	if (!new_buffer) {
+		pr_err("%s: Dump measurements failed.\n", __func__);
+		resume = true;
+		goto out;
+	}
+	memcpy(ima_kexec_buffer, new_buffer, new_buffer_size);
+out:
+	kimage_unmap_segment(ima_kexec_buffer);
+	ima_kexec_buffer = NULL;
+
+	if (resume)
+		ima_measurements_resume();
+
+	return NOTIFY_OK;
+}
+
 #endif /* IMA_KEXEC */
 
 /*
Signature · 9 lines
thanks,

Mimi


_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
maintainer
#22 lore raw

Re: [PATCH 06/10] ima: update buffer at kexec execute with ima measurements

Quoted 39 lines · Mimi Zohar

Hi Tushar,

Quoted 19 lines · Tushar Sugandhi
security/integrity/ima/ima_kexec.c +19 -0
+/*
+ * 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)
+{
+	void *new_buffer = NULL;
+	size_t new_buffer_size, cur_buffer_size;
+	bool resume = false;
+
+	if (!kexec_in_progress) {
+		pr_info("%s: No kexec in progress.\n", __func__);
+		return NOTIFY_OK;
+	}
+
+	if (!ima_kexec_buffer) {
+		pr_err("%s: Kexec buffer not set.\n", __func__);
+		return NOTIFY_OK;
+	}

security/integrity/ima/ima_kexec.c void ima_add_kexec_buffer(struct kimage *image) · line 263

Quoted 10 lines
security/integrity/ima/ima_kexec.c +10 -0
+
+	ima_measurements_suspend();
+
+	cur_buffer_size = kexec_segment_size - sizeof(struct ima_kexec_hdr);
+	new_buffer_size = ima_get_binary_runtime_size();
+	if (new_buffer_size > cur_buffer_size) {
+		pr_err("%s: Measurement list grew too large.\n", __func__);
+		resume = true;
+		goto out;
+	}

This changes the current behavior of carrying as many measurements across kexec as possible. True the measurement list won't verify against the TPM PCRs, but not copying the measurements leaves the impression there weren't any previous measurements.

Quoted 2 lines

This also explains the reason for allocating an IMA buffer (patch 1/10) and not writing the measurements directly into the kexec buffer.

If not carrying even a partial measurement list across kexec is desired, then in addition to the "boot_aggregate" record, define a new record containing the TPM pcrcounter. With this information, attestation servers will at least be able to detect if the measurement list was truncated.

thanks,

Mimi

Quoted 21 lines
Quoted 21 lines
security/integrity/ima/ima_kexec.c +18 -0
+	ima_populate_buf_at_kexec_execute(&new_buffer_size, &new_buffer);
+
+	if (!new_buffer) {
+		pr_err("%s: Dump measurements failed.\n", __func__);
+		resume = true;
+		goto out;
+	}
+	memcpy(ima_kexec_buffer, new_buffer, new_buffer_size);
+out:
+	kimage_unmap_segment(ima_kexec_buffer);
+	ima_kexec_buffer = NULL;
+
+	if (resume)
+		ima_measurements_resume();
+
+	return NOTIFY_OK;
+}
+
 #endif /* IMA_KEXEC */
Quoted 2 lines
Quoted 1 line

/*

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#23 lore raw

Re: [PATCH 06/10] ima: update buffer at kexec execute with ima measurements

Adding Eric to cc.

Quoted 47 lines · Mimi Zohar
Quoted 38 lines · Mimi Zohar

Hi Tushar,

Quoted 19 lines · Tushar Sugandhi
security/integrity/ima/ima_kexec.c +19 -0
+/*
+ * 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)
+{
+	void *new_buffer = NULL;
+	size_t new_buffer_size, cur_buffer_size;
+	bool resume = false;
+
+	if (!kexec_in_progress) {
+		pr_info("%s: No kexec in progress.\n", __func__);
+		return NOTIFY_OK;
+	}
+
+	if (!ima_kexec_buffer) {
+		pr_err("%s: Kexec buffer not set.\n", __func__);
+		return NOTIFY_OK;
+	}

security/integrity/ima/ima_kexec.c void ima_add_kexec_buffer(struct kimage *image) · line 263

Quoted 10 lines
security/integrity/ima/ima_kexec.c +10 -0
+
+	ima_measurements_suspend();
+
+	cur_buffer_size = kexec_segment_size - sizeof(struct ima_kexec_hdr);
+	new_buffer_size = ima_get_binary_runtime_size();
+	if (new_buffer_size > cur_buffer_size) {
+		pr_err("%s: Measurement list grew too large.\n", __func__);
+		resume = true;
+		goto out;
+	}

This changes the current behavior of carrying as many measurements across kexec as possible. True the measurement list won't verify against the TPM PCRs, but not copying the measurements leaves the impression there weren't any previous measurements.

Quoted 2 lines

This also explains the reason for allocating an IMA buffer (patch 1/10) and not writing the measurements directly into the kexec buffer.

If not carrying even a partial measurement list across kexec is desired, then in addition to the "boot_aggregate" record, define a new record containing the TPM pcrcounter. With this information, attestation servers will at least be able to detect if the measurement list was truncated.

Quoted 3 lines

thanks,

Mimi

Sure.  Recording TPM pcrcounter at boot aggregate and Kexec 'load' should provide the necessary information to the attestation servers.  We can implement this if needed, based on how rest of the series evolves.

~Tushar

Quoted 21 lines
Quoted 21 lines
Quoted 21 lines
security/integrity/ima/ima_kexec.c +18 -0
+	ima_populate_buf_at_kexec_execute(&new_buffer_size, &new_buffer);
+
+	if (!new_buffer) {
+		pr_err("%s: Dump measurements failed.\n", __func__);
+		resume = true;
+		goto out;
+	}
+	memcpy(ima_kexec_buffer, new_buffer, new_buffer_size);
+out:
+	kimage_unmap_segment(ima_kexec_buffer);
+	ima_kexec_buffer = NULL;
+
+	if (resume)
+		ima_measurements_resume();
+
+	return NOTIFY_OK;
+}
+
  #endif /* IMA_KEXEC */
 
  /*
maintainer
#24 lore raw

Re: [PATCH 06/10] ima: update buffer at kexec execute with ima measurements

Quoted 50 lines · Tushar Sugandhi

Adding Eric to cc.

Quoted 39 lines · Mimi Zohar
Quoted 38 lines · Mimi Zohar

Hi Tushar,

Quoted 19 lines · Tushar Sugandhi
security/integrity/ima/ima_kexec.c +19 -0
+/*
+ * 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)
+{
+	void *new_buffer = NULL;
+	size_t new_buffer_size, cur_buffer_size;
+	bool resume = false;
+
+	if (!kexec_in_progress) {
+		pr_info("%s: No kexec in progress.\n", __func__);
+		return NOTIFY_OK;
+	}
+
+	if (!ima_kexec_buffer) {
+		pr_err("%s: Kexec buffer not set.\n", __func__);
+		return NOTIFY_OK;
+	}

security/integrity/ima/ima_kexec.c void ima_add_kexec_buffer(struct kimage *image) · line 263

Quoted 10 lines
security/integrity/ima/ima_kexec.c +10 -0
+
+	ima_measurements_suspend();
+
+	cur_buffer_size = kexec_segment_size - sizeof(struct ima_kexec_hdr);
+	new_buffer_size = ima_get_binary_runtime_size();
+	if (new_buffer_size > cur_buffer_size) {
+		pr_err("%s: Measurement list grew too large.\n", __func__);
+		resume = true;
+		goto out;
+	}

This changes the current behavior of carrying as many measurements across kexec as possible. True the measurement list won't verify against the TPM PCRs, but not copying the measurements leaves the impression there weren't any previous measurements.

Quoted 7 lines
Quoted 2 lines

This also explains the reason for allocating an IMA buffer (patch 1/10) and not writing the measurements directly into the kexec buffer.

If not carrying even a partial measurement list across kexec is desired, then in addition to the "boot_aggregate" record, define a new record containing the TPM pcrcounter. With this information, attestation servers will at least be able to detect if the measurement list was truncated.

Quoted 4 lines

Sure. Recording TPM pcrcounter at boot aggregate and Kexec 'load' should provide the necessary information to the attestation servers. We can implement this if needed, based on how rest of the series evolves.

Recording the TPM pcrcounter should be done independently of this patch set. This patch set would have a dependency on it.

Signature · 9 lines
thanks,

Mimi


_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
#25 lore raw

Re: [PATCH 06/10] ima: update buffer at kexec execute with ima measurements

In reply to Mimi Zohar

Adding Eric to cc.

Quoted 38 lines · Mimi Zohar

Hi Tushar,

Quoted 19 lines · Tushar Sugandhi
security/integrity/ima/ima_kexec.c +19 -0
+/*
+ * 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)
+{
+	void *new_buffer = NULL;
+	size_t new_buffer_size, cur_buffer_size;
+	bool resume = false;
+
+	if (!kexec_in_progress) {
+		pr_info("%s: No kexec in progress.\n", __func__);
+		return NOTIFY_OK;
+	}
+
+	if (!ima_kexec_buffer) {
+		pr_err("%s: Kexec buffer not set.\n", __func__);
+		return NOTIFY_OK;
+	}

security/integrity/ima/ima_kexec.c void ima_add_kexec_buffer(struct kimage *image) · line 263

Quoted 10 lines
security/integrity/ima/ima_kexec.c +10 -0
+
+	ima_measurements_suspend();
+
+	cur_buffer_size = kexec_segment_size - sizeof(struct ima_kexec_hdr);
+	new_buffer_size = ima_get_binary_runtime_size();
+	if (new_buffer_size > cur_buffer_size) {
+		pr_err("%s: Measurement list grew too large.\n", __func__);
+		resume = true;
+		goto out;
+	}

This changes the current behavior of carrying as many measurements across kexec as possible. True the measurement list won't verify against the TPM PCRs, but not copying the measurements leaves the impression there weren't any previous measurements.

Quoted 2 lines

This also explains the reason for allocating an IMA buffer (patch 1/10) and not writing the measurements directly into the kexec buffer.

Thanks.

I will update this logic depending if we decide to use ima_dump_measurement_list() at kexec ‘execute’, or combination of ima_allocate_buf_at_kexec_load() and ima_populate_buf_at_kexec_execute() at kexec ‘load’ and kexec ‘execute’ respectively.

~Tushar

Quoted 21 lines
Quoted 21 lines
security/integrity/ima/ima_kexec.c +18 -0
+	ima_populate_buf_at_kexec_execute(&new_buffer_size, &new_buffer);
+
+	if (!new_buffer) {
+		pr_err("%s: Dump measurements failed.\n", __func__);
+		resume = true;
+		goto out;
+	}
+	memcpy(ima_kexec_buffer, new_buffer, new_buffer_size);
+out:
+	kimage_unmap_segment(ima_kexec_buffer);
+	ima_kexec_buffer = NULL;
+
+	if (resume)
+		ima_measurements_resume();
+
+	return NOTIFY_OK;
+}
+
  #endif /* IMA_KEXEC */
 
  /*
#26 lore raw

PATCH 7/10 ima: remove function ima_dump_measurement_list

In reply to Tushar Sugandhi

The ima_dump_measurement_list function was designed to iterate over the IMA measurement list and store each entry into a buffer. The buffer, along with its size, would be returned to the caller. However, the function is no longer required in the IMA subsystem. It previously served to dump the measurement list during the kexec 'load' operation, but this functionality has been replaced by an alternative approach in this patch series.

Remove the unused ima_dump_measurement_list function from the IMA subsystem, to ensure a cleaner and more maintainable code.

---
 security/integrity/ima/ima_kexec.c | 58 ------------------------------
 1 file changed, 58 deletions(-)
security/integrity/ima/ima_kexec.c +0 -58
index 224d88ccfe85..424930085c18 100644
@@ -115,64 +115,6 @@ static int ima_populate_buf_at_kexec_execute(unsigned long *buffer_size, void **
 }
 
 
-static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
-				     unsigned long segment_size)
-{
-	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) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	file.size = segment_size;
-	file.read_pos = 0;
-	file.count = sizeof(khdr);	/* reserved space */
-
-	memset(&khdr, 0, sizeof(khdr));
-	khdr.version = 1;
-	list_for_each_entry_rcu(qe, &ima_measurements, later) {
-		if (file.count < file.size) {
-			khdr.count++;
-			ima_measurements_show(&file, qe);
-		} else {
-			ret = -EINVAL;
-			break;
-		}
-	}
-
-	if (ret < 0)
-		goto out;
-
-	/*
-	 * fill in reserved space with some buffer details
-	 * (eg. version, buffer size, number of measurements)
-	 */
-	khdr.buffer_size = 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));
-
-	print_hex_dump_debug("ima dump: ", DUMP_PREFIX_NONE, 16, 1,
-			     file.buf, file.count < 100 ? file.count : 100,
-			     true);
-
-	*buffer_size = file.count;
-	*buffer = file.buf;
-out:
-	if (ret == -EINVAL)
-		vfree(file.buf);
-	return ret;
-}
-
 /*
  * Called during kexec_file_load so that IMA can add a segment to the kexec
  * image for the measurement list for the next kernel.
Signature · 1 line
2.25.1
maintainer
#27 lore raw

Re: [PATCH 07/10] ima: remove function ima_dump_measurement_list

Hi Tushar,

Quoted 8 lines · Tushar Sugandhi

The ima_dump_measurement_list function was designed to iterate over the IMA measurement list and store each entry into a buffer. The buffer, along with its size, would be returned to the caller. However, the function is no longer required in the IMA subsystem. It previously served to dump the measurement list during the kexec 'load' operation, but this functionality has been replaced by an alternative approach in this patch series.

Quoted 4 lines

Remove the unused ima_dump_measurement_list function from the IMA subsystem, to ensure a cleaner and more maintainable code.

Have you compiled the code and tested after applying each patch? Removing the caller before removing the code should have resulted in a warning.

Signature · 3 lines
thanks,

Mimi
#28 lore raw

Re: [PATCH 07/10] ima: remove function ima_dump_measurement_list

Adding Eric to cc.

Quoted 11 lines · Mimi Zohar

Hi Tushar,

Quoted 8 lines · Tushar Sugandhi

The ima_dump_measurement_list function was designed to iterate over the IMA measurement list and store each entry into a buffer. The buffer, along with its size, would be returned to the caller. However, the function is no longer required in the IMA subsystem. It previously served to dump the measurement list during the kexec 'load' operation, but this functionality has been replaced by an alternative approach in this patch series.

Quoted 8 lines
Quoted 4 lines

Remove the unused ima_dump_measurement_list function from the IMA subsystem, to ensure a cleaner and more maintainable code.

Have you compiled the code and tested after applying each patch? Removing the caller before removing the code should have resulted in a warning.

Yes, I compiled each patch separately, and I did see this warning. But removing ima_dump_measurement_list after implementing and calling the alternate ima_allocate_buf_at_kexec_load() and ima_populate_buf_at_kexec_execute() felt cleaner in terms of organizing the patches.

I can remove the definition when I deprecate the usage, if we end up using the alternate two functions.

~Tushar

#29 lore raw

PATCH 8/10 ima: implement and register a reboot notifier function to update kexec buffer

In reply to Tushar Sugandhi

The IMA subsystem needs to ensure that the measurement list is up to date during a kexec operation, i.e., when the kernel is rebooted without going through the full system reboot process. Currently, there is no mechanism to update the measurement list when the system is soft booted using kexec.

Add a notifier function ima_update_kexec_buffer that is called during a kexec soft reboot. Implement ima_kexec_post_load, which maps the IMA buffer after a kexec load and registers the reboot notifier.

Define a new notifier block update_buffer_nb, with ima_update_kexec_buffer as its notifier function. Register the notifier function in ima_kexec_post_load if it hasn't been already, indicated by the ima_kexec_update_registered flag.

When a kexec soft reboot is triggered, ima_update_kexec_buffer will be executed to update the IMA buffer. This ensures that the events between kexec 'load' and 'execute' are captured and integrity of measurements remains intact across kexec reboots.

---
 include/linux/ima.h                |  3 +++
 security/integrity/ima/ima_kexec.c | 35 ++++++++++++++++++++++++++++++
 2 files changed, 38 insertions(+)
include/linux/ima.h +3 -0
index 86b57757c7b1..006db20f852d 100644
@@ -49,6 +49,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
security/integrity/ima/ima_kexec.c +35 -0
index 424930085c18..363c107dc4a5 100644
@@ -12,6 +12,8 @@
 #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
@@ -19,6 +21,7 @@ struct seq_file ima_kexec_file;
 struct ima_kexec_hdr ima_khdr;
 static size_t kexec_segment_size;
 static void *ima_kexec_buffer;
+static bool ima_kexec_update_registered;
 
 void ima_clear_kexec_file(void)
 {
@@ -222,6 +225,38 @@ static int ima_update_kexec_buffer(struct notifier_block *self,
 	return NOTIFY_OK;
 }
 
+struct notifier_block update_buffer_nb = {
+	.notifier_call = ima_update_kexec_buffer,
+};
+
+/*
+ * 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("%s: Could not map measurements buffer.\n", __func__);
+		return;
+	}
+
+	if (!ima_kexec_update_registered) {
+		register_reboot_notifier(&update_buffer_nb);
+		ima_kexec_update_registered = true;
+	}
+}
+
 #endif /* IMA_KEXEC */
 
 /*
Signature · 1 line
2.25.1
#30 lore raw

PATCH 9/10 ima: suspend measurements while the kexec buffer is being copied

In reply to Tushar Sugandhi

If the new measurements are added to the list while the kexec buffer is being copied during kexec execute, the buffer may get corrupted, or it can go out of sync with TPM PCRs. This could potentially lead to breaking the integrity of the measurements after the kexec soft reboot to the new kernel.

Introduce a check in the ima_add_template_entry function not to measure events and return from the function early when the suspend_ima_measurements flag is set.

This ensures the consistency of the IMA measurement list during the copying of the kexec buffer. When the suspend_ima_measurements flag is set, any new measurements will be ignored until the flag is unset. This allows the buffer to be safely copied without worrying about concurrent modifications to the measurement list. This is crucial for maintaining the integrity of the measurements during a kexec soft reboot.

---
 security/integrity/ima/ima_queue.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)
security/integrity/ima/ima_queue.c +13 -0
index cb9abc02a304..5946a26a2849 100644
@@ -195,6 +195,19 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
 		}
 	}
 
+	/*
+	 * suspend_ima_measurements will be set if the system is
+	 * undergoing kexec soft boot to a new kernel.
+	 * suspending measurements in this short window ensures the
+	 * consistency of the IMA measurement list during copying
+	 * of the kexec buffer.
+	 */
+	if (atomic_read(&suspend_ima_measurements)) {
+		audit_cause = "measurements_suspended";
+		audit_info = 0;
+		goto out;
+	}
+
 	result = ima_add_digest_entry(entry,
 				      !IS_ENABLED(CONFIG_IMA_DISABLE_HTABLE));
 	if (result < 0) {
Signature · 1 line
2.25.1
#31 lore raw

PATCH 10/10 kexec: update kexec_file_load syscall to call ima_kexec_post_load

In reply to Tushar Sugandhi

The kexec_file_load syscall is used to load a new kernel for kexec. The syscall needs to update its function to call ima_kexec_post_load, which was implemented in a previous patch. ima_kexec_post_load takes care of mapping the measurement list for the next kernel and registering a reboot notifier if it's not already registered.

Modify the kexec_file_load syscall to call ima_kexec_post_load after the image has been loaded and prepared for kexec. This ensures that the IMA measurement list will be available to the next kernel after a kexec reboot. This also ensures the measurements taken in the window between kexec load and execute are captured and passed to the next kernel.

Declare the kimage_file_post_load function in the kernel/kexec_internal.h, so it can be properly used in the syscall.

---
 kernel/kexec_file.c     | 7 +++++++
 kernel/kexec_internal.h | 1 +
 2 files changed, 8 insertions(+)
kernel/kexec_file.c +7 -0
index f989f5f1933b..efe28e77280c 100644
@@ -184,6 +184,11 @@ kimage_validate_signature(struct kimage *image)
 }
 #endif
 
+void kimage_file_post_load(struct kimage *image)
+{
+	ima_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
@@ -399,6 +404,8 @@ SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd,
 
 	kimage_terminate(image);
 
+	kimage_file_post_load(image);
+
 	ret = machine_kexec_post_load(image);
 	if (ret)
 		goto out;
kernel/kexec_internal.h +1 -0
index 74da1409cd14..98dd5fcafaf0 100644
@@ -30,6 +30,7 @@ static inline void kexec_unlock(void)
 
 #ifdef CONFIG_KEXEC_FILE
 #include <linux/purgatory.h>
+void kimage_file_post_load(struct kimage *image);
 void kimage_file_post_load_cleanup(struct kimage *image);
 extern char kexec_purgatory[];
 extern size_t kexec_purgatory_size;
Signature · 1 line
2.25.1
#32 lore raw

Re: [PATCH 10/10] kexec: update kexec_file_load syscall to call ima_kexec_post_load

Quoted 39 lines · Tushar Sugandhi

The kexec_file_load syscall is used to load a new kernel for kexec. The syscall needs to update its function to call ima_kexec_post_load, which was implemented in a previous patch. ima_kexec_post_load takes care of mapping the measurement list for the next kernel and registering a reboot notifier if it's not already registered.

Modify the kexec_file_load syscall to call ima_kexec_post_load after the image has been loaded and prepared for kexec. This ensures that the IMA measurement list will be available to the next kernel after a kexec reboot. This also ensures the measurements taken in the window between kexec load and execute are captured and passed to the next kernel.

Declare the kimage_file_post_load function in the kernel/kexec_internal.h, so it can be properly used in the syscall.

---
 kernel/kexec_file.c     | 7 +++++++
 kernel/kexec_internal.h | 1 +
 2 files changed, 8 insertions(+)
kernel/kexec_file.c +5 -0
index f989f5f1933b..efe28e77280c 100644
@@ -184,6 +184,11 @@ kimage_validate_signature(struct kimage *image)
 }
 #endif
 
+void kimage_file_post_load(struct kimage *image)
+{
+       ima_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

kernel/kexec_file.c SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd, · line 407

Quoted 4 lines
kernel/kexec_file.c +1 -0
@@ -399,6 +404,8 @@ SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd,
 
        kimage_terminate(image);
 
+       kimage_file_post_load(image);

I think it should be only done for the reboot case, please just exclude the kdump case here..

Quoted 20 lines
kernel/kexec_file.c +1 -0
+
        ret = machine_kexec_post_load(image);
        if (ret)
                goto out;
kernel/kexec_internal.h +1 -1
index 74da1409cd14..98dd5fcafaf0 100644
@@ -30,6 +30,7 @@ static inline void kexec_unlock(void)
 
 #ifdef CONFIG_KEXEC_FILE
 #include <linux/purgatory.h>
+void kimage_file_post_load(struct kimage *image);
 void kimage_file_post_load_cleanup(struct kimage *image);
 extern char kexec_purgatory[];
 extern size_t kexec_purgatory_size;
--

2.25.1

Quoted 5 lines

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#33 lore raw

Re: [PATCH 10/10] kexec: update kexec_file_load syscall to call ima_kexec_post_load

Quoted 41 lines · RuiRui Yang
Quoted 39 lines · Tushar Sugandhi

The kexec_file_load syscall is used to load a new kernel for kexec. The syscall needs to update its function to call ima_kexec_post_load, which was implemented in a previous patch. ima_kexec_post_load takes care of mapping the measurement list for the next kernel and registering a reboot notifier if it's not already registered.

Modify the kexec_file_load syscall to call ima_kexec_post_load after the image has been loaded and prepared for kexec. This ensures that the IMA measurement list will be available to the next kernel after a kexec reboot. This also ensures the measurements taken in the window between kexec load and execute are captured and passed to the next kernel.

Declare the kimage_file_post_load function in the kernel/kexec_internal.h, so it can be properly used in the syscall.

---
  kernel/kexec_file.c     | 7 +++++++
  kernel/kexec_internal.h | 1 +
  2 files changed, 8 insertions(+)
kernel/kexec_file.c +5 -0
index f989f5f1933b..efe28e77280c 100644
@@ -184,6 +184,11 @@ kimage_validate_signature(struct kimage *image)
  }
  #endif
 
+void kimage_file_post_load(struct kimage *image)
+{
+       ima_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
@@ -399,6 +404,8 @@ SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd,
 
Quoted 6 lines

kernel/kexec_file.c SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd, · line 407

Quoted 3 lines
kernel/kexec_file.c +1 -0
         kimage_terminate(image);
 
+       kimage_file_post_load(image);

I think it should be only done for the reboot case, please just exclude the kdump case here..

Thanks for the feedback RuiRui.  Appreciate it.

Conceptually I agree with you that this needs to be done only for reboot. I need to figure out how to do it implementation wise.

If you can give me pointers/suggestions, that would help.

~Tushar

Quoted 25 lines
Quoted 25 lines
kernel/kexec_file.c +1 -0
+
         ret = machine_kexec_post_load(image);
         if (ret)
                 goto out;
kernel/kexec_internal.h +1 -1
index 74da1409cd14..98dd5fcafaf0 100644
@@ -30,6 +30,7 @@ static inline void kexec_unlock(void)
 
  #ifdef CONFIG_KEXEC_FILE
  #include <linux/purgatory.h>
+void kimage_file_post_load(struct kimage *image);
  void kimage_file_post_load_cleanup(struct kimage *image);
  extern char kexec_purgatory[];
  extern size_t kexec_purgatory_size;
--

2.25.1

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#34 lore raw

Re: [PATCH 10/10] kexec: update kexec_file_load syscall to call ima_kexec_post_load

Quoted 50 lines · Tushar Sugandhi
Quoted 41 lines · RuiRui Yang
Quoted 39 lines · Tushar Sugandhi

The kexec_file_load syscall is used to load a new kernel for kexec. The syscall needs to update its function to call ima_kexec_post_load, which was implemented in a previous patch. ima_kexec_post_load takes care of mapping the measurement list for the next kernel and registering a reboot notifier if it's not already registered.

Modify the kexec_file_load syscall to call ima_kexec_post_load after the image has been loaded and prepared for kexec. This ensures that the IMA measurement list will be available to the next kernel after a kexec reboot. This also ensures the measurements taken in the window between kexec load and execute are captured and passed to the next kernel.

Declare the kimage_file_post_load function in the kernel/kexec_internal.h, so it can be properly used in the syscall.

---
  kernel/kexec_file.c     | 7 +++++++
  kernel/kexec_internal.h | 1 +
  2 files changed, 8 insertions(+)
kernel/kexec_file.c +5 -0
index f989f5f1933b..efe28e77280c 100644
@@ -184,6 +184,11 @@ kimage_validate_signature(struct kimage *image)
  }
  #endif
 
+void kimage_file_post_load(struct kimage *image)
+{
+       ima_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
@@ -399,6 +404,8 @@ SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd,
 
Quoted 6 lines

kernel/kexec_file.c SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd, · line 407

Quoted 3 lines
kernel/kexec_file.c +1 -0
         kimage_terminate(image);
 
+       kimage_file_post_load(image);

I think it should be only done for the reboot case, please just exclude the kdump case here..

Quoted 6 lines

Thanks for the feedback RuiRui. Appreciate it.

Conceptually I agree with you that this needs to be done only for reboot. I need to figure out how to do it implementation wise.

If you can give me pointers/suggestions, that would help.

Hi Tushar,

You can check the flags argument in the function
if (flags & KEXEC_FILE_ON_CRASH) is true then this is a kdump kernel loading, just skip the kimage_file_post_load in that case?

Quoted 28 lines

~Tushar

Quoted 25 lines
Quoted 25 lines
kernel/kexec_file.c +1 -0
+
         ret = machine_kexec_post_load(image);
         if (ret)
                 goto out;
kernel/kexec_internal.h +1 -1
index 74da1409cd14..98dd5fcafaf0 100644
@@ -30,6 +30,7 @@ static inline void kexec_unlock(void)
 
  #ifdef CONFIG_KEXEC_FILE
  #include <linux/purgatory.h>
+void kimage_file_post_load(struct kimage *image);
  void kimage_file_post_load_cleanup(struct kimage *image);
  extern char kexec_purgatory[];
  extern size_t kexec_purgatory_size;
--

2.25.1

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#35 lore raw

Re: [PATCH 10/10] kexec: update kexec_file_load syscall to call ima_kexec_post_load

Quoted 56 lines · RuiRui Yang
Quoted 54 lines · Tushar Sugandhi
Quoted 41 lines · RuiRui Yang
Quoted 39 lines · Tushar Sugandhi

The kexec_file_load syscall is used to load a new kernel for kexec. The syscall needs to update its function to call ima_kexec_post_load, which was implemented in a previous patch. ima_kexec_post_load takes care of mapping the measurement list for the next kernel and registering a reboot notifier if it's not already registered.

Modify the kexec_file_load syscall to call ima_kexec_post_load after the image has been loaded and prepared for kexec. This ensures that the IMA measurement list will be available to the next kernel after a kexec reboot. This also ensures the measurements taken in the window between kexec load and execute are captured and passed to the next kernel.

Declare the kimage_file_post_load function in the kernel/kexec_internal.h, so it can be properly used in the syscall.

---
   kernel/kexec_file.c     | 7 +++++++
   kernel/kexec_internal.h | 1 +
   2 files changed, 8 insertions(+)
kernel/kexec_file.c +5 -0
index f989f5f1933b..efe28e77280c 100644
@@ -184,6 +184,11 @@ kimage_validate_signature(struct kimage *image)
   }
   #endif
 
+void kimage_file_post_load(struct kimage *image)
+{
+       ima_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
@@ -399,6 +404,8 @@ SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd,
 
Quoted 6 lines

kernel/kexec_file.c SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd, · line 407

Quoted 3 lines
kernel/kexec_file.c +1 -0
          kimage_terminate(image);
 
+       kimage_file_post_load(image);

I think it should be only done for the reboot case, please just exclude the kdump case here..

Thanks for the feedback RuiRui. Appreciate it.

Conceptually I agree with you that this needs to be done only for reboot. I need to figure out how to do it implementation wise.

Quoted 6 lines
Quoted 1 line

If you can give me pointers/suggestions, that would help.

Hi Tushar,

You can check the flags argument in the function
if (flags & KEXEC_FILE_ON_CRASH) is true then this is a kdump kernel loading, just skip the kimage_file_post_load in that case?

Great.  Thanks for the pointer.  Will do.
~Tushar

Quoted 26 lines
Quoted 26 lines

~Tushar

Quoted 25 lines
Quoted 25 lines
kernel/kexec_file.c +1 -0
+
          ret = machine_kexec_post_load(image);
          if (ret)
                  goto out;
kernel/kexec_internal.h +1 -1
index 74da1409cd14..98dd5fcafaf0 100644
@@ -30,6 +30,7 @@ static inline void kexec_unlock(void)
 
   #ifdef CONFIG_KEXEC_FILE
   #include <linux/purgatory.h>
+void kimage_file_post_load(struct kimage *image);
   void kimage_file_post_load_cleanup(struct kimage *image);
   extern char kexec_purgatory[];
   extern size_t kexec_purgatory_size;
--

2.25.1

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#36 lore raw
In reply to Tushar Sugandhi

[Add Eric in cc]

Quoted 82 lines · Tushar Sugandhi

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'.

Some devices can be configured to call kexec 'load' first, and followed by kexec 'execute' after some time. (as opposed to calling 'load' and 'execute' in one single kexec command). In such scenario, if new IMA measurements are added between kexec 'load' and kexec 'execute', the TPM PCRs are extended with the IMA events between 'load' and 'execute'; but those IMA events are not carried over to the new kernel after kexec soft reboot. This results in mismatch between TPM PCR quotes and the actual IMA measurements list after the device boots into the new kexec image. This mismatch results in the remote attestation failing for that device.

This patch series proposes a solution to solve this problem by allocating the necessary buffer at kexec 'load' time, and populating the buffer with the IMA measurements at kexec 'execute' time.

The solution includes:
- addition of new functionality to allocate a buffer to hold IMA measurements at kexec 'load',

- ima functionality to suspend and resume measurements as needed during buffer copy at kexec 'execute',

- ima functionality for mapping the measurement list 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',

- and removal of deprecated functions.

The modifications 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.

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

[1] [PATHC v2 5/9] ima: on soft reboot, save the measurement list
https://lore.kernel.org/lkml/[email protected]/

[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/[email protected]/T/

Tushar Sugandhi (10):
ima: implement function to allocate buffer at kexec load
ima: implement function to populate buffer at kexec execute
ima: allocate buffer at kexec load to hold ima measurements
ima: implement functions to suspend and resume measurements
kexec: implement functions to map and unmap segment to kimage
ima: update buffer at kexec execute with ima measurements
ima: remove function ima_dump_measurement_list
ima: implement and register a reboot notifier function to update kexec
buffer
ima: suspend measurements while the kexec buffer is being copied
kexec: update kexec_file_load syscall to call ima_kexec_post_load

 include/linux/ima.h                |   3 +
 include/linux/kexec.h              |  13 ++
 kernel/kexec_core.c                |  72 +++++++++-
 kernel/kexec_file.c                |   7 +
 kernel/kexec_internal.h            |   1 +
 security/integrity/ima/ima.h       |   4 +
 security/integrity/ima/ima_kexec.c | 211 +++++++++++++++++++++++------
 security/integrity/ima/ima_queue.c |  32 +++++
 8 files changed, 295 insertions(+), 48 deletions(-)
Quoted 9 lines

--
2.25.1

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#37 lore raw

Thanks Dave for taking a look at this.

I will keep Eric looped in on the next versions of this patch series.

~Tushar

Quoted 94 lines · Dave Young

[Add Eric in cc]

Quoted 90 lines · Tushar Sugandhi

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'.

Some devices can be configured to call kexec 'load' first, and followed by kexec 'execute' after some time. (as opposed to calling 'load' and 'execute' in one single kexec command). In such scenario, if new IMA measurements are added between kexec 'load' and kexec 'execute', the TPM PCRs are extended with the IMA events between 'load' and 'execute'; but those IMA events are not carried over to the new kernel after kexec soft reboot. This results in mismatch between TPM PCR quotes and the actual IMA measurements list after the device boots into the new kexec image. This mismatch results in the remote attestation failing for that device.

This patch series proposes a solution to solve this problem by allocating the necessary buffer at kexec 'load' time, and populating the buffer with the IMA measurements at kexec 'execute' time.

The solution includes:
- addition of new functionality to allocate a buffer to hold IMA measurements at kexec 'load',

- ima functionality to suspend and resume measurements as needed during buffer copy at kexec 'execute',

- ima functionality for mapping the measurement list 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',

- and removal of deprecated functions.

The modifications 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.

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

[1] [PATHC v2 5/9] ima: on soft reboot, save the measurement list
https://lore.kernel.org/lkml/[email protected]/

[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/[email protected]/T/

Tushar Sugandhi (10):
ima: implement function to allocate buffer at kexec load
ima: implement function to populate buffer at kexec execute
ima: allocate buffer at kexec load to hold ima measurements
ima: implement functions to suspend and resume measurements
kexec: implement functions to map and unmap segment to kimage
ima: update buffer at kexec execute with ima measurements
ima: remove function ima_dump_measurement_list
ima: implement and register a reboot notifier function to update kexec
buffer
ima: suspend measurements while the kexec buffer is being copied
kexec: update kexec_file_load syscall to call ima_kexec_post_load

  include/linux/ima.h                |   3 +
  include/linux/kexec.h              |  13 ++
  kernel/kexec_core.c                |  72 +++++++++-
  kernel/kexec_file.c                |   7 +
  kernel/kexec_internal.h            |   1 +
  security/integrity/ima/ima.h       |   4 +
  security/integrity/ima/ima_kexec.c | 211 +++++++++++++++++++++++------
  security/integrity/ima/ima_queue.c |  32 +++++
  8 files changed, 295 insertions(+), 48 deletions(-)

--
2.25.1

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

maintainer
#38 lore raw
In reply to Tushar Sugandhi
Quoted 15 lines · Tushar Sugandhi

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'.

Some devices can be configured to call kexec 'load' first, and followed by kexec 'execute' after some time. (as opposed to calling 'load' and 'execute' in one single kexec command). In such scenario, if new IMA measurements are added between kexec 'load' and kexec 'execute', the TPM PCRs are extended with the IMA events between 'load' and 'execute'; but those IMA events are not carried over to the new kernel after kexec soft reboot. This results in mismatch between TPM PCR quotes and the actual IMA measurements list after the device boots into the new kexec image. This mismatch results in the remote attestation failing for that device.

Quoted 3 lines

This patch series proposes a solution to solve this problem by allocating the necessary buffer at kexec 'load' time, and populating the buffer with the IMA measurements at kexec 'execute' time.

Thanks, Tushar. Depending on the IMA policy, the above problem
statement is correct, but not all policies are affected by it. It's also unclear why so much needs to change. Instead of copying the measurement list at kexec 'load', using the existing method and simply copying them at kexec 'exec' would suffice.

Also as mentioned in comment on 3/10, the ordering of this patch set is not bisect safe. If the same method of copying the measurement list was used, changing from copying at kexec 'load' to kexec 'exec' could be done in the same patch.

Mimi

Quoted 53 lines

The solution includes:
- addition of new functionality to allocate a buffer to hold IMA measurements at kexec 'load',

- ima functionality to suspend and resume measurements as needed during buffer copy at kexec 'execute',

- ima functionality for mapping the measurement list 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',

- and removal of deprecated functions.

The modifications 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.

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

[1] [PATHC v2 5/9] ima: on soft reboot, save the measurement list
https://lore.kernel.org/lkml/[email protected]/

[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/[email protected]/T/

Tushar Sugandhi (10):
ima: implement function to allocate buffer at kexec load
ima: implement function to populate buffer at kexec execute
ima: allocate buffer at kexec load to hold ima measurements
ima: implement functions to suspend and resume measurements
kexec: implement functions to map and unmap segment to kimage
ima: update buffer at kexec execute with ima measurements
ima: remove function ima_dump_measurement_list
ima: implement and register a reboot notifier function to update kexec
buffer
ima: suspend measurements while the kexec buffer is being copied
kexec: update kexec_file_load syscall to call ima_kexec_post_load

Quoted 10 lines
 include/linux/ima.h                |   3 +
 include/linux/kexec.h              |  13 ++
 kernel/kexec_core.c                |  72 +++++++++-
 kernel/kexec_file.c                |   7 +
 kernel/kexec_internal.h            |   1 +
 security/integrity/ima/ima.h       |   4 +
 security/integrity/ima/ima_kexec.c | 211 +++++++++++++++++++++++------
 security/integrity/ima/ima_queue.c |  32 +++++
 8 files changed, 295 insertions(+), 48 deletions(-)

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#39 lore raw

Thanks for reviewing this series Mimi. Appreciate it.

Adding Eric to cc.

Quoted 16 lines · Mimi Zohar
Quoted 15 lines · Tushar Sugandhi

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'.

Some devices can be configured to call kexec 'load' first, and followed by kexec 'execute' after some time. (as opposed to calling 'load' and 'execute' in one single kexec command). In such scenario, if new IMA measurements are added between kexec 'load' and kexec 'execute', the TPM PCRs are extended with the IMA events between 'load' and 'execute'; but those IMA events are not carried over to the new kernel after kexec soft reboot. This results in mismatch between TPM PCR quotes and the actual IMA measurements list after the device boots into the new kexec image. This mismatch results in the remote attestation failing for that device.

Quoted 8 lines
Quoted 3 lines

This patch series proposes a solution to solve this problem by allocating the necessary buffer at kexec 'load' time, and populating the buffer with the IMA measurements at kexec 'execute' time.

Thanks, Tushar. Depending on the IMA policy, the above problem
statement is correct, but not all policies are affected by it. It's also unclear why so much needs to change. Instead of copying the measurement list at kexec 'load', using the existing method and simply copying them at kexec 'exec' would suffice.

My understanding is the buffer must be allocated at kexec ‘load’ time. The segment size cannot change between kexec ‘load’ and kexec ‘execute’. Not sure if this is a technical limitation of IMA, or KEXEC.

Could you/someone from kexec side let me know?

If my current understanding is not correct, then I agree, simply copying the measurements at kexec ‘execute’ using ima_dump_measurement_list should suffice.

Quoted 7 lines

Also as mentioned in comment on 3/10, the ordering of this patch set is not bisect safe. If the same method of copying the measurement list was used, changing from copying at kexec 'load' to kexec 'exec' could be done in the same patch.

Mimi

Ok. Based on my above response, if there is no such technical limitation to allocate and copy at kexec ‘execute’ – I will simply move the call to ima_dump_measurement_list from kexec 'load' to 'exec'. And that can be done inthe same patch as you mentioned.

~Tushar

Quoted 63 lines
Quoted 63 lines

The solution includes:
- addition of new functionality to allocate a buffer to hold IMA measurements at kexec 'load',

- ima functionality to suspend and resume measurements as needed during buffer copy at kexec 'execute',

- ima functionality for mapping the measurement list 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',

- and removal of deprecated functions.

The modifications 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.

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

[1] [PATHC v2 5/9] ima: on soft reboot, save the measurement list
https://lore.kernel.org/lkml/[email protected]/

[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/[email protected]/T/

Tushar Sugandhi (10):
ima: implement function to allocate buffer at kexec load
ima: implement function to populate buffer at kexec execute
ima: allocate buffer at kexec load to hold ima measurements
ima: implement functions to suspend and resume measurements
kexec: implement functions to map and unmap segment to kimage
ima: update buffer at kexec execute with ima measurements
ima: remove function ima_dump_measurement_list
ima: implement and register a reboot notifier function to update kexec
buffer
ima: suspend measurements while the kexec buffer is being copied
kexec: update kexec_file_load syscall to call ima_kexec_post_load

  include/linux/ima.h                |   3 +
  include/linux/kexec.h              |  13 ++
  kernel/kexec_core.c                |  72 +++++++++-
  kernel/kexec_file.c                |   7 +
  kernel/kexec_internal.h            |   1 +
  security/integrity/ima/ima.h       |   4 +
  security/integrity/ima/ima_kexec.c | 211 +++++++++++++++++++++++------
  security/integrity/ima/ima_queue.c |  32 +++++
  8 files changed, 295 insertions(+), 48 deletions(-)
#40 lore raw
Quoted 45 lines · Tushar Sugandhi

Thanks for reviewing this series Mimi. Appreciate it.

Adding Eric to cc.

Quoted 16 lines · Mimi Zohar
Quoted 15 lines · Tushar Sugandhi

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'.

Some devices can be configured to call kexec 'load' first, and followed by kexec 'execute' after some time. (as opposed to calling 'load' and 'execute' in one single kexec command).  In such scenario, if new IMA measurements are added between kexec 'load' and kexec 'execute', the TPM PCRs are extended with the IMA events between 'load' and 'execute'; but those IMA events are not carried over to the new kernel after kexec soft reboot.  This results in mismatch between TPM PCR quotes and the actual IMA measurements list after the device boots into the new kexec image.  This mismatch results in the remote attestation failing for that device.

Quoted 8 lines
Quoted 3 lines

This patch series proposes a solution to solve this problem by allocating the necessary buffer at kexec 'load' time, and populating the buffer with the IMA measurements at kexec 'execute' time.

Thanks, Tushar.   Depending on the IMA policy, the above problem statement is correct, but not all policies are affected by it.  It's also unclear why so much needs to change.  Instead of copying the measurement list at kexec 'load',  using the existing method and simply copying them at kexec 'exec' would suffice.

My understanding is the buffer must be allocated at kexec ‘load’ time. The segment size cannot change between kexec ‘load’ and kexec ‘execute’. Not sure if this is a technical limitation of IMA, or KEXEC.

Could you/someone from kexec side let me know?

If my current understanding is not correct, then I agree, simply copying the measurements at kexec ‘execute’ using ima_dump_measurement_list should suffice.

Quoted 6 lines

Also as mentioned in comment on 3/10, the ordering of this patch set is not bisect safe.  If the same method of copying the measurement list was used, changing from copying at  kexec 'load'  to kexec 'exec' could be done in the same patch.

Quoted 7 lines
Quoted 1 line

Mimi

Ok. Based on my above response, if there is no such technical limitation to allocate and copy at kexec ‘execute’ – I will simply move the call to ima_dump_measurement_list from kexec 'load' to 'exec'. And that can be done inthe same patch as you mentioned.

~Tushar

Hello all,
For the last few days, I did several experiments to allocate the memory during kexec 'execute' rather than at the existing kexec 'load'.

My experiments either resulted in Kernel panics, or didn't copy the IMA log entries added between 'load' and 'execute'.

As per my understanding, and also documented in several comments in kexec code (e.g. in kexec_file.c [1]), adding buffer after allocating control pages is not allowed. All segments need to be placed first before any control pages are allocated.

And control page allocation happens at kexec 'load' [3][4][5].

There are several checks that ensures new buffer segments are not allocated after control pages are allocated at kexec 'load'. e.g. kexec_file.c[1][3], kexec_core.c[2].

If we want to allocate buffer at kexec 'execute' to address this issue of "missing entries in IMA log during kexec load-execute window", we will have to bypass those checks. That would be a very significant change in kexec logic. And I do not believe its the right approach.

I believe we have to stick with the current approach of allocating memory segments at kexec 'load', and copy whatever we can, during kexe 'execute'.

Thanks,
Tushar

[1] https://elixir.bootlin.com/linux/latest/source/kernel/kexec_file.c#L652
int kexec_add_buffer(struct kexec_buf *kbuf)
{
...

/*
* Make sure we are not trying to add buffer after allocating
* control pages. All segments need to be placed first before
* any control pages are allocated. As control page allocation
* logic goes through list of segments to make sure there are
* no destination overlaps.
*/
if (!list_empty(&kbuf->image->control_pages)) {
      WARN_ON(1);
      return -EINVAL;
}
...
}

[2] https://elixir.bootlin.com/linux/latest/source/kernel/kexec_core.c#L352
static struct page *kimage_alloc_normal_control_pages(struct kimage *image, unsigned int order)
{
      /* Control pages are special, they are the intermediaries
       * that are needed while we copy the rest of the pages
       * to their final resting place. As such they must
       * not conflict with either the destination addresses
       * or memory the kernel is already using.
       *
       * The only case where we really need more than one of
       * these are for architectures where we cannot disable
       * the MMU and must instead generate an identity mapped
       * page table for all of the memory.
       *
       * At worst this runs in O(N) of the image size.
       */
...
}

[3] https://elixir.bootlin.com/linux/latest/source/kernel/kexec_file.c#L299
static int
kimage_file_alloc_init(struct kimage **rimage, int kernel_fd, int initrd_fd, const char __user *cmdline_ptr, unsigned long cmdline_len, unsigned long flags) {
      image->control_code_page = kimage_alloc_control_pages(image, get_order(KEXEC_CONTROL_PAGE_SIZE)); if (!image->control_code_page) {
            pr_err("Could not allocate control_code_buffer\n"); goto out_free_post_load_bufs;
      }
}

[4] https://elixir.bootlin.com/linux/latest/source/kernel/kexec_file.c#L366
SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd, unsigned long, cmdline_len, const char __user *, cmdline_ptr, unsigned long, flags)
{
...
ret = kimage_file_alloc_init(&image, kernel_fd, initrd_fd, cmdline_ptr,
...                      cmdline_len, flags);
}

[5] https://elixir.bootlin.com/linux/latest/source/kernel/kexec.c#L63
static int kimage_alloc_init(struct kimage **rimage, unsigned long entry, unsigned long nr_segments,
                   struct kexec_segment *segments,
                   unsigned long flags)

{
    ...
    image->control_code_page = kimage_alloc_control_pages(image,
                           get_order(KEXEC_CONTROL_PAGE_SIZE));
    if (!image->control_code_page) {
      pr_err("Could not allocate control_code_buffer\n");
      goto out_free_image;
    }
    ...
}
Quoted 63 lines
Quoted 63 lines
Quoted 63 lines

The solution includes:
  - addition of new functionality to allocate a buffer to hold IMA measurements at kexec 'load',

  - ima functionality to suspend and resume measurements as needed during buffer copy at kexec 'execute',

  - ima functionality for mapping the measurement list 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',

  - and removal of deprecated functions.

The modifications 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.

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

[1] [PATHC v2 5/9] ima: on soft reboot, save the measurement list
https://lore.kernel.org/lkml/[email protected]/

[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/[email protected]/T/

Tushar Sugandhi (10):
   ima: implement function to allocate buffer at kexec load
   ima: implement function to populate buffer at kexec execute
   ima: allocate buffer at kexec load to hold ima measurements
   ima: implement functions to suspend and resume measurements
   kexec: implement functions to map and unmap segment to kimage
   ima: update buffer at kexec execute with ima measurements
   ima: remove function ima_dump_measurement_list
   ima: implement and register a reboot notifier function to update kexec buffer
   ima: suspend measurements while the kexec buffer is being copied
   kexec: update kexec_file_load syscall to call ima_kexec_post_load

  include/linux/ima.h                |   3 + include/linux/kexec.h              |  13 ++ kernel/kexec_core.c                |  72 +++++++++- kernel/kexec_file.c                |   7 + kernel/kexec_internal.h            |   1 + security/integrity/ima/ima.h       |   4 + security/integrity/ima/ima_kexec.c | 211 +++++++++++++++++++++++------ security/integrity/ima/ima_queue.c |  32 +++++

  8 files changed, 295 insertions(+), 48 deletions(-)