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