Skip to content

Commit 9ecd08c

Browse files
author
Baoquan He
committed
ima: kexec: move IMA log copy from kexec load to execute
JIRA: https://issues.redhat.com/browse/RHEL-114162 Upstream Status: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git commit 9f0ec4b Author: Steven Chen <chenste@linux.microsoft.com> Date: Mon Apr 21 15:25:12 2025 -0700 ima: kexec: move IMA log copy from kexec load to execute 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> Signed-off-by: Baoquan He <bhe@redhat.com>
1 parent 696bd14 commit 9ecd08c

File tree

2 files changed

+39
-15
lines changed

2 files changed

+39
-15
lines changed

kernel/kexec_file.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,15 @@ kimage_validate_signature(struct kimage *image)
201201
}
202202
#endif
203203

204+
static int kexec_post_load(struct kimage *image, unsigned long flags)
205+
{
206+
#ifdef CONFIG_IMA_KEXEC
207+
if (!(flags & KEXEC_FILE_ON_CRASH))
208+
ima_kexec_post_load(image);
209+
#endif
210+
return machine_kexec_post_load(image);
211+
}
212+
204213
/*
205214
* In file mode list of segments is prepared by kernel. Copy relevant
206215
* 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,
428437

429438
kimage_terminate(image);
430439

431-
ret = machine_kexec_post_load(image);
440+
ret = kexec_post_load(image, flags);
432441
if (ret)
433442
goto out;
434443

security/integrity/ima/ima_kexec.c

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#ifdef CONFIG_IMA_KEXEC
2020
static bool ima_kexec_update_registered;
2121
static struct seq_file ima_kexec_file;
22+
static size_t kexec_segment_size;
2223
static void *ima_kexec_buffer;
2324

2425
static void ima_free_kexec_file_buf(struct seq_file *sf)
@@ -72,9 +73,6 @@ static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
7273
}
7374
}
7475

75-
if (ret < 0)
76-
goto out;
77-
7876
/*
7977
* fill in reserved space with some buffer details
8078
* (eg. version, buffer size, number of measurements)
@@ -94,7 +92,7 @@ static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
9492

9593
*buffer_size = ima_kexec_file.count;
9694
*buffer = ima_kexec_file.buf;
97-
out:
95+
9896
return ret;
9997
}
10098

@@ -112,9 +110,8 @@ void ima_add_kexec_buffer(struct kimage *image)
112110
unsigned long binary_runtime_size;
113111

114112
/* use more understandable variable names than defined in kbuf */
113+
size_t kexec_buffer_size = 0;
115114
void *kexec_buffer = NULL;
116-
size_t kexec_buffer_size;
117-
size_t kexec_segment_size;
118115
int ret;
119116

120117
/*
@@ -139,13 +136,6 @@ void ima_add_kexec_buffer(struct kimage *image)
139136
return;
140137
}
141138

142-
ima_dump_measurement_list(&kexec_buffer_size, &kexec_buffer,
143-
kexec_segment_size);
144-
if (!kexec_buffer) {
145-
pr_err("Not enough memory for the kexec measurement buffer.\n");
146-
return;
147-
}
148-
149139
kbuf.buffer = kexec_buffer;
150140
kbuf.bufsz = kexec_buffer_size;
151141
kbuf.memsz = kexec_segment_size;
@@ -173,7 +163,32 @@ void ima_add_kexec_buffer(struct kimage *image)
173163
static int ima_update_kexec_buffer(struct notifier_block *self,
174164
unsigned long action, void *data)
175165
{
176-
return NOTIFY_OK;
166+
size_t buf_size = 0;
167+
int ret = NOTIFY_OK;
168+
void *buf = NULL;
169+
170+
if (!kexec_in_progress) {
171+
pr_info("No kexec in progress.\n");
172+
return ret;
173+
}
174+
175+
if (!ima_kexec_buffer) {
176+
pr_err("Kexec buffer not set.\n");
177+
return ret;
178+
}
179+
180+
ret = ima_dump_measurement_list(&buf_size, &buf, kexec_segment_size);
181+
182+
if (ret)
183+
pr_err("Dump measurements failed. Error:%d\n", ret);
184+
185+
if (buf_size != 0)
186+
memcpy(ima_kexec_buffer, buf, buf_size);
187+
188+
kimage_unmap_segment(ima_kexec_buffer);
189+
ima_kexec_buffer = NULL;
190+
191+
return ret;
177192
}
178193

179194
static struct notifier_block update_buffer_nb = {

0 commit comments

Comments
 (0)