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. Signed-off-by: Tushar Sugandhi <tusharsu@xxxxxxxxxxxxxxxxxxx> --- security/integrity/ima/ima_kexec.c | 47 ++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c index 419dc405c831..48a683874044 100644 --- a/security/integrity/ima/ima_kexec.c +++ b/security/integrity/ima/ima_kexec.c @@ -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) { -- 2.25.1