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 <tusha...@linux.microsoft.com>
---
 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


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

Reply via email to