Linux kernel -stable discussions
 help / color / mirror / Atom feed
* [PATCH 6.12.y 0/2] ima: kexec: fix kexec_file_load panic with IMA_KEXEC
@ 2026-06-09 21:58 Sherry Yang
  2026-06-09 21:58 ` [PATCH 6.12.y 1/2] ima: kexec: skip IMA segment validation after kexec soft reboot Sherry Yang
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Sherry Yang @ 2026-06-09 21:58 UTC (permalink / raw)
  To: stable
  Cc: sashal, chenste, sherry.yang, ebiederm, tusharsu, zohar,
	roberto.sassu, dmitry.kasatkin, eric.snowberg

Hi Stable Maintainers,

This series backports two upstream IMA/kexec commits to linux-6.12.y:

  9ee8888a80fe ("ima: kexec: skip IMA segment validation after kexec soft reboot")
  9f0ec4b16f2b ("ima: kexec: move IMA log copy from kexec load to execute")

linux-6.12.y already contains the surrounding IMA kexec backports, including
the buffer reuse change:

  d0a00ce470e3 ("ima: verify if the segment size has changed")

but it is missing the commit that moves the measurement list copy from
kexec load time to kexec execute time.  With CONFIG_IMA_KEXEC=y and
CONFIG_KEXEC_FILE=y, this leaves the static IMA seq_file buffer with the
old load-time ownership model.

With repeated file-based kexec loads, for example

  kexec -l /boot/vmlinuz-$(uname -r) \
    --initrd=/boot/initramfs-$(uname -r).img --reuse-cmdline

We hit kernel panic

[   64.411644] BUG: unable to handle page fault for address: ff5f3d77a44d9018
[   64.423320] Call Trace:
[   64.423516]  <TASK>
[   64.423684]  ima_measurements_show+0xb2/0x250
[   64.424015]  ima_dump_measurement_list.constprop.0.isra.0+0x81/0x15e
[   64.424475]  ima_add_kexec_buffer+0x160/0x1f2
[   64.424809]  kimage_file_alloc_init+0x1af/0x3df
[   64.425143]  __do_sys_kexec_file_load+0xc4/0x2bc
[   64.425483]  do_syscall_64+0x90/0x1c0
[   64.425768]  ? srso_alias_return_thunk+0x5/0xfbef5
[   64.426121]  ? srso_alias_return_thunk+0x5/0xfbef5
[   64.426473]  ? syscall_exit_work+0x103/0x130
[   64.426794]  ? srso_alias_return_thunk+0x5/0xfbef5
[   64.427142]  ? arch_exit_to_user_mode_prepare.isra.0+0x1e/0xf0
[   64.427562]  ? srso_alias_return_thunk+0x5/0xfbef5
[   64.427911]  ? syscall_exit_to_user_mode+0x36/0x190
[   64.428263]  ? srso_alias_return_thunk+0x5/0xfbef5
[   64.428616]  ? do_syscall_64+0xb6/0x1c0
[   64.428894]  ? inode_security+0x22/0x60
[   64.429179]  ? srso_alias_return_thunk+0x5/0xfbef5
[   64.429519]  ? mutex_lock+0x12/0x40
[   64.429783]  ? srso_alias_return_thunk+0x5/0xfbef5
[   64.430405]  ? seq_read_iter+0x1fc/0x433
[   64.430931]  ? srso_alias_return_thunk+0x5/0xfbef5
[   64.431513]  ? srso_alias_return_thunk+0x5/0xfbef5
[   64.432167]  ? vfs_read+0x252/0x370
[   64.432676]  ? srso_alias_return_thunk+0x5/0xfbef5
[   64.433249]  ? syscall_exit_work+0x103/0x130
[   64.433791]  ? srso_alias_return_thunk+0x5/0xfbef5
[   64.434362]  ? arch_exit_to_user_mode_prepare.isra.0+0x1e/0xf0
[   64.435010]  ? srso_alias_return_thunk+0x5/0xfbef5
[   64.435579]  ? syscall_exit_to_user_mode+0x36/0x190
[   64.436149]  ? srso_alias_return_thunk+0x5/0xfbef5
[   64.436718]  ? do_syscall_64+0xb6/0x1c0
[   64.437222]  ? srso_alias_return_thunk+0x5/0xfbef5
[   64.437801]  ? syscall_exit_work+0x103/0x130
[   64.438337]  ? srso_alias_return_thunk+0x5/0xfbef5
[   64.438899]  ? arch_exit_to_user_mode_prepare.isra.0+0x1e/0xf0
[   64.439545]  ? srso_alias_return_thunk+0x5/0xfbef5
[   64.440099]  ? syscall_exit_to_user_mode+0x36/0x190
[   64.440656]  ? srso_alias_return_thunk+0x5/0xfbef5
[   64.441202]  ? do_syscall_64+0xb6/0x1c0
[   64.441680]  ? srso_alias_return_thunk+0x5/0xfbef5
[   64.442221]  entry_SYSCALL_64_after_hwframe+0x76/0x7e
[   64.442792] RIP: 0033:0x7f2cef50887d
[   64.443249] Code: 5b 41 5c c3 66 0f 1f 84 00 00 00 00 00 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 6b 15 0f 00 f7 d8 64 89 01 48
[   64.444968] RSP: 002b:00007ffdb22657b8 EFLAGS: 00000246 ORIG_RAX: 0000000000000140
[   64.445715] RAX: ffffffffffffffda RBX: 0000000000000080 RCX: 00007f2cef50887d
[   64.446432] RDX: 00000000000001de RSI: 0000000000000005 RDI: 0000000000000003
[   64.447153] RBP: 0000000000000003 R08: 0000000000000000 R09: 00000005b2265b28
[   64.447870] R10: 0000561563d37dc0 R11: 0000000000000246 R12: 0000000000000000
[   64.448589] R13: 00007ffdb2265b28 R14: 00007f2cee241010 R15: 00007ffdb22662a7
[   64.449313]  </TASK>

After backporting these two patches and tested with CONFIG_IMA_KEXEC=y
and CONFIG_KEXEC_FILE=y, the panic is no longer reproducible.

Thanks,
Sherry

Steven Chen (2):
  ima: kexec: skip IMA segment validation after kexec soft reboot
  ima: kexec: move IMA log copy from kexec load to execute

 include/linux/kexec.h              |  3 ++
 kernel/kexec_file.c                | 33 ++++++++++++++++++++-
 security/integrity/ima/ima_kexec.c | 46 +++++++++++++++++++++---------
 3 files changed, 67 insertions(+), 15 deletions(-)

-- 
2.50.1


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

* [PATCH 6.12.y 1/2] ima: kexec: skip IMA segment validation after kexec soft reboot
  2026-06-09 21:58 [PATCH 6.12.y 0/2] ima: kexec: fix kexec_file_load panic with IMA_KEXEC Sherry Yang
@ 2026-06-09 21:58 ` Sherry Yang
  2026-06-09 21:58 ` [PATCH 6.12.y 2/2] ima: kexec: move IMA log copy from kexec load to execute Sherry Yang
  2026-06-11  0:45 ` [PATCH 6.12.y 0/2] ima: kexec: fix kexec_file_load panic with IMA_KEXEC Sasha Levin
  2 siblings, 0 replies; 4+ messages in thread
From: Sherry Yang @ 2026-06-09 21:58 UTC (permalink / raw)
  To: stable
  Cc: sashal, chenste, sherry.yang, ebiederm, tusharsu, zohar,
	roberto.sassu, dmitry.kasatkin, eric.snowberg

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

[ Upstream commit 9ee8888a80fe2bd20ce929ffbc1dedd57607a778 ]

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

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

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

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

Cc: Eric Biederman <ebiederm@xmission.com>
Cc: Baoquan He <bhe@redhat.com>
Cc: Vivek Goyal <vgoyal@redhat.com>
Cc: Dave Young <dyoung@redhat.com>
Co-developed-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
Signed-off-by: Steven Chen <chenste@linux.microsoft.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Acked-by: Baoquan He <bhe@redhat.com>
Tested-by: Stefan Berger <stefanb@linux.ibm.com> # ppc64/kvm
[zohar@linux.ibm.com: Fixed Signed-off-by tag to match author's email ]
Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
(cherry picked from commit 9ee8888a80fe2bd20ce929ffbc1dedd57607a778)
Signed-off-by: Sherry Yang <sherry.yang@oracle.com>
---
 include/linux/kexec.h              |  3 +++
 kernel/kexec_file.c                | 22 ++++++++++++++++++++++
 security/integrity/ima/ima_kexec.c |  3 +++
 3 files changed, 28 insertions(+)

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


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

* [PATCH 6.12.y 2/2] ima: kexec: move IMA log copy from kexec load to execute
  2026-06-09 21:58 [PATCH 6.12.y 0/2] ima: kexec: fix kexec_file_load panic with IMA_KEXEC Sherry Yang
  2026-06-09 21:58 ` [PATCH 6.12.y 1/2] ima: kexec: skip IMA segment validation after kexec soft reboot Sherry Yang
@ 2026-06-09 21:58 ` Sherry Yang
  2026-06-11  0:45 ` [PATCH 6.12.y 0/2] ima: kexec: fix kexec_file_load panic with IMA_KEXEC Sasha Levin
  2 siblings, 0 replies; 4+ messages in thread
From: Sherry Yang @ 2026-06-09 21:58 UTC (permalink / raw)
  To: stable
  Cc: sashal, chenste, sherry.yang, ebiederm, tusharsu, zohar,
	roberto.sassu, dmitry.kasatkin, eric.snowberg

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

[ Upstream commit 9f0ec4b16f2b41d663f688a8012e9e52b2657eba ]

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

Make the kexec_segment_size variable a local static variable within the
file, so it can be accessed during both kexec 'load' and 'execute'.

Define kexec_post_load() as a wrapper for calling ima_kexec_post_load() and
machine_kexec_post_load().  Replace the existing direct call to
machine_kexec_post_load() with kexec_post_load().

When there is insufficient memory to copy all the measurement logs, copy as
much of the measurement list as possible.

Co-developed-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
Cc: Eric Biederman <ebiederm@xmission.com>
Cc: Baoquan He <bhe@redhat.com>
Cc: Vivek Goyal <vgoyal@redhat.com>
Cc: Dave Young <dyoung@redhat.com>
Signed-off-by: Steven Chen <chenste@linux.microsoft.com>
Tested-by: Stefan Berger <stefanb@linux.ibm.com> # ppc64/kvm
Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
(cherry picked from commit 9f0ec4b16f2b41d663f688a8012e9e52b2657eba)
Signed-off-by: Sherry Yang <sherry.yang@oracle.com>
---
 kernel/kexec_file.c                | 11 +++++++-
 security/integrity/ima/ima_kexec.c | 43 ++++++++++++++++++++----------
 2 files changed, 39 insertions(+), 15 deletions(-)

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


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

* Re: [PATCH 6.12.y 0/2] ima: kexec: fix kexec_file_load panic with IMA_KEXEC
  2026-06-09 21:58 [PATCH 6.12.y 0/2] ima: kexec: fix kexec_file_load panic with IMA_KEXEC Sherry Yang
  2026-06-09 21:58 ` [PATCH 6.12.y 1/2] ima: kexec: skip IMA segment validation after kexec soft reboot Sherry Yang
  2026-06-09 21:58 ` [PATCH 6.12.y 2/2] ima: kexec: move IMA log copy from kexec load to execute Sherry Yang
@ 2026-06-11  0:45 ` Sasha Levin
  2 siblings, 0 replies; 4+ messages in thread
From: Sasha Levin @ 2026-06-11  0:45 UTC (permalink / raw)
  To: stable
  Cc: Sasha Levin, chenste, sherry.yang, ebiederm, tusharsu, zohar,
	roberto.sassu, dmitry.kasatkin, eric.snowberg

On Mon, Jun 09, 2026 at 02:58:42PM -0700, Sherry Yang wrote:
> This series backports two upstream IMA/kexec commits to 6.12.y to fix
> a kexec_file_load panic with IMA_KEXEC:
>  [PATCH 1/2] ima: kexec: skip IMA segment validation after kexec soft reboot
>  [PATCH 2/2] ima: kexec: move IMA log copy from kexec load to execute

Both queued for 6.12, thanks.

--
Thanks,
Sasha

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

end of thread, other threads:[~2026-06-11  0:45 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-09 21:58 [PATCH 6.12.y 0/2] ima: kexec: fix kexec_file_load panic with IMA_KEXEC Sherry Yang
2026-06-09 21:58 ` [PATCH 6.12.y 1/2] ima: kexec: skip IMA segment validation after kexec soft reboot Sherry Yang
2026-06-09 21:58 ` [PATCH 6.12.y 2/2] ima: kexec: move IMA log copy from kexec load to execute Sherry Yang
2026-06-11  0:45 ` [PATCH 6.12.y 0/2] ima: kexec: fix kexec_file_load panic with IMA_KEXEC Sasha Levin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox