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