ima_kexec.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /*
  2. * Copyright (C) 2016 IBM Corporation
  3. *
  4. * Authors:
  5. * Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com>
  6. * Mimi Zohar <zohar@linux.vnet.ibm.com>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. */
  13. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  14. #include <linux/seq_file.h>
  15. #include <linux/vmalloc.h>
  16. #include <linux/kexec.h>
  17. #include "ima.h"
  18. #ifdef CONFIG_IMA_KEXEC
  19. static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
  20. unsigned long segment_size)
  21. {
  22. struct ima_queue_entry *qe;
  23. struct seq_file file;
  24. struct ima_kexec_hdr khdr;
  25. int ret = 0;
  26. /* segment size can't change between kexec load and execute */
  27. file.buf = vmalloc(segment_size);
  28. if (!file.buf) {
  29. ret = -ENOMEM;
  30. goto out;
  31. }
  32. file.size = segment_size;
  33. file.read_pos = 0;
  34. file.count = sizeof(khdr); /* reserved space */
  35. memset(&khdr, 0, sizeof(khdr));
  36. khdr.version = 1;
  37. list_for_each_entry_rcu(qe, &ima_measurements, later) {
  38. if (file.count < file.size) {
  39. khdr.count++;
  40. ima_measurements_show(&file, qe);
  41. } else {
  42. ret = -EINVAL;
  43. break;
  44. }
  45. }
  46. if (ret < 0)
  47. goto out;
  48. /*
  49. * fill in reserved space with some buffer details
  50. * (eg. version, buffer size, number of measurements)
  51. */
  52. khdr.buffer_size = file.count;
  53. if (ima_canonical_fmt) {
  54. khdr.version = cpu_to_le16(khdr.version);
  55. khdr.count = cpu_to_le64(khdr.count);
  56. khdr.buffer_size = cpu_to_le64(khdr.buffer_size);
  57. }
  58. memcpy(file.buf, &khdr, sizeof(khdr));
  59. print_hex_dump(KERN_DEBUG, "ima dump: ", DUMP_PREFIX_NONE,
  60. 16, 1, file.buf,
  61. file.count < 100 ? file.count : 100, true);
  62. *buffer_size = file.count;
  63. *buffer = file.buf;
  64. out:
  65. if (ret == -EINVAL)
  66. vfree(file.buf);
  67. return ret;
  68. }
  69. /*
  70. * Called during kexec_file_load so that IMA can add a segment to the kexec
  71. * image for the measurement list for the next kernel.
  72. *
  73. * This function assumes that kexec_mutex is held.
  74. */
  75. void ima_add_kexec_buffer(struct kimage *image)
  76. {
  77. struct kexec_buf kbuf = { .image = image, .buf_align = PAGE_SIZE,
  78. .buf_min = 0, .buf_max = ULONG_MAX,
  79. .top_down = true };
  80. unsigned long binary_runtime_size;
  81. /* use more understandable variable names than defined in kbuf */
  82. void *kexec_buffer = NULL;
  83. size_t kexec_buffer_size;
  84. size_t kexec_segment_size;
  85. int ret;
  86. /*
  87. * Reserve an extra half page of memory for additional measurements
  88. * added during the kexec load.
  89. */
  90. binary_runtime_size = ima_get_binary_runtime_size();
  91. if (binary_runtime_size >= ULONG_MAX - PAGE_SIZE)
  92. kexec_segment_size = ULONG_MAX;
  93. else
  94. kexec_segment_size = ALIGN(ima_get_binary_runtime_size() +
  95. PAGE_SIZE / 2, PAGE_SIZE);
  96. if ((kexec_segment_size == ULONG_MAX) ||
  97. ((kexec_segment_size >> PAGE_SHIFT) > totalram_pages / 2)) {
  98. pr_err("Binary measurement list too large.\n");
  99. return;
  100. }
  101. ima_dump_measurement_list(&kexec_buffer_size, &kexec_buffer,
  102. kexec_segment_size);
  103. if (!kexec_buffer) {
  104. pr_err("Not enough memory for the kexec measurement buffer.\n");
  105. return;
  106. }
  107. kbuf.buffer = kexec_buffer;
  108. kbuf.bufsz = kexec_buffer_size;
  109. kbuf.memsz = kexec_segment_size;
  110. ret = kexec_add_buffer(&kbuf);
  111. if (ret) {
  112. pr_err("Error passing over kexec measurement buffer.\n");
  113. return;
  114. }
  115. ret = arch_ima_add_kexec_buffer(image, kbuf.mem, kexec_segment_size);
  116. if (ret) {
  117. pr_err("Error passing over kexec measurement buffer.\n");
  118. return;
  119. }
  120. pr_debug("kexec measurement buffer for the loaded kernel at 0x%lx.\n",
  121. kbuf.mem);
  122. }
  123. #endif /* IMA_KEXEC */
  124. /*
  125. * Restore the measurement list from the previous kernel.
  126. */
  127. void ima_load_kexec_buffer(void)
  128. {
  129. void *kexec_buffer = NULL;
  130. size_t kexec_buffer_size = 0;
  131. int rc;
  132. rc = ima_get_kexec_buffer(&kexec_buffer, &kexec_buffer_size);
  133. switch (rc) {
  134. case 0:
  135. rc = ima_restore_measurement_list(kexec_buffer_size,
  136. kexec_buffer);
  137. if (rc != 0)
  138. pr_err("Failed to restore the measurement list: %d\n",
  139. rc);
  140. ima_free_kexec_buffer();
  141. break;
  142. case -ENOTSUPP:
  143. pr_debug("Restoring the measurement list not supported\n");
  144. break;
  145. case -ENOENT:
  146. pr_debug("No measurement list to restore\n");
  147. break;
  148. default:
  149. pr_debug("Error restoring the measurement list: %d\n", rc);
  150. }
  151. }