grub-module-verifier.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <grub/elf.h>
  4. #include <grub/module_verifier.h>
  5. #include <grub/misc.h>
  6. #include <grub/util/misc.h>
  7. struct grub_module_verifier_arch archs[] = {
  8. { "i386", 4, 0, EM_386, GRUB_MODULE_VERIFY_SUPPORTS_REL, (int[]){
  9. R_386_32,
  10. R_386_PC32,
  11. -1
  12. } },
  13. { "x86_64", 8, 0, EM_X86_64, GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
  14. R_X86_64_64,
  15. R_X86_64_PC64,
  16. /* R_X86_64_32, R_X86_64_32S are supported but shouldn't be used because of their limited range. */
  17. -1
  18. }, (int[]){
  19. R_X86_64_PC32,
  20. -1
  21. }
  22. },
  23. { "powerpc", 4, 1, EM_PPC, GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
  24. GRUB_ELF_R_PPC_ADDR16_LO,
  25. GRUB_ELF_R_PPC_REL24, /* It has limited range but GRUB adds trampolines when necessarry. */
  26. GRUB_ELF_R_PPC_ADDR16_HA,
  27. GRUB_ELF_R_PPC_ADDR32,
  28. GRUB_ELF_R_PPC_REL32,
  29. -1
  30. } },
  31. { "sparc64", 8, 1, EM_SPARCV9, GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
  32. R_SPARC_WDISP30, /* It has limited range but GRUB adds trampolines when necessarry. */
  33. R_SPARC_HH22,
  34. R_SPARC_HM10,
  35. R_SPARC_LM22,
  36. R_SPARC_LO10,
  37. R_SPARC_64,
  38. R_SPARC_OLO10,
  39. /* Following 2 relocations have limited range but unfortunately
  40. clang generates them, as it doesn't implement mcmodel=large properly.
  41. At least our heap and core are under 4G, so it's not a problem
  42. usually. */
  43. R_SPARC_HI22,
  44. R_SPARC_32,
  45. -1
  46. } },
  47. { "ia64", 8, 0, EM_IA_64, GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
  48. R_IA64_PCREL21B, /* We should verify that it's pointing either
  49. to a function or to a section in the same module.
  50. Checking that external symbol is a function is
  51. non-trivial and I have never seen this relocation used
  52. for anything else, so assume that it always points to a
  53. function.
  54. */
  55. R_IA64_SEGREL64LSB,
  56. R_IA64_FPTR64LSB,
  57. R_IA64_DIR64LSB,
  58. R_IA64_PCREL64LSB,
  59. R_IA64_LTOFF22X,
  60. R_IA64_LTOFF22,
  61. R_IA64_GPREL64I,
  62. R_IA64_LTOFF_FPTR22,
  63. R_IA64_LDXMOV,
  64. -1
  65. }, (int[]){
  66. R_IA64_GPREL22,
  67. -1
  68. } },
  69. { "mipsel", 4, 0, EM_MIPS, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
  70. R_MIPS_HI16,
  71. R_MIPS_LO16,
  72. R_MIPS_32,
  73. R_MIPS_GPREL32,
  74. R_MIPS_26,
  75. R_MIPS_GOT16,
  76. R_MIPS_CALL16,
  77. R_MIPS_JALR,
  78. -1
  79. } },
  80. { "mips", 4, 1, EM_MIPS, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
  81. R_MIPS_HI16,
  82. R_MIPS_LO16,
  83. R_MIPS_32,
  84. R_MIPS_GPREL32,
  85. R_MIPS_26,
  86. R_MIPS_GOT16,
  87. R_MIPS_CALL16,
  88. R_MIPS_JALR,
  89. -1
  90. } },
  91. { "arm", 4, 0, EM_ARM, GRUB_MODULE_VERIFY_SUPPORTS_REL, (int[]){
  92. /* Some relocations are range-limited but trampolines are added when necessarry. */
  93. R_ARM_ABS32,
  94. R_ARM_CALL,
  95. R_ARM_JUMP24,
  96. R_ARM_THM_CALL,
  97. R_ARM_THM_JUMP24,
  98. R_ARM_V4BX,
  99. R_ARM_THM_MOVW_ABS_NC,
  100. R_ARM_THM_MOVT_ABS,
  101. R_ARM_THM_JUMP19,
  102. -1
  103. } },
  104. { "arm64", 8, 0, EM_AARCH64, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
  105. R_AARCH64_ABS64,
  106. R_AARCH64_CALL26,
  107. R_AARCH64_JUMP26,
  108. R_AARCH64_ADR_GOT_PAGE,
  109. R_AARCH64_LD64_GOT_LO12_NC,
  110. -1
  111. }, (int[]){
  112. R_AARCH64_ADR_PREL_PG_HI21,
  113. R_AARCH64_ADD_ABS_LO12_NC,
  114. R_AARCH64_LDST64_ABS_LO12_NC,
  115. R_AARCH64_PREL32,
  116. -1
  117. }
  118. },
  119. };
  120. struct platform_whitelist {
  121. const char *arch;
  122. const char *platform;
  123. const char **whitelist_empty;
  124. };
  125. static struct platform_whitelist whitelists[] = {
  126. {"i386", "xen", (const char *[]) {"all_video", 0}},
  127. {"x86_64", "xen", (const char *[]) {"all_video", 0}},
  128. {"sparc64", "ieee1275", (const char *[]) {"all_video", 0}},
  129. /* video is compiled-in on MIPS. */
  130. {"mipsel", "loongson", (const char *[]) {"all_video", 0}},
  131. {"mipsel", "qemu_mips", (const char *[]) {"all_video", 0}},
  132. {"mipsel", "arc", (const char *[]) {"all_video", 0}},
  133. {"mips", "qemu_mips", (const char *[]) {"all_video", 0}},
  134. {"mips", "arc", (const char *[]) {"all_video", 0}},
  135. };
  136. int
  137. main (int argc, char **argv)
  138. {
  139. size_t module_size;
  140. unsigned arch, whitelist;
  141. const char **whitelist_empty = 0;
  142. char *module_img;
  143. if (argc != 4) {
  144. fprintf (stderr, "usage: %s FILE ARCH PLATFORM\n", argv[0]);
  145. return 1;
  146. }
  147. for (arch = 0; arch < ARRAY_SIZE(archs); arch++)
  148. if (strcmp(archs[arch].name, argv[2]) == 0)
  149. break;
  150. if (arch == ARRAY_SIZE(archs))
  151. grub_util_error("unknown arch: %s", argv[2]);
  152. for (whitelist = 0; whitelist < ARRAY_SIZE(whitelists); whitelist++)
  153. if (strcmp(whitelists[whitelist].arch, argv[2]) == 0
  154. && strcmp(whitelists[whitelist].platform, argv[3]) == 0)
  155. break;
  156. if (whitelist != ARRAY_SIZE(whitelists))
  157. whitelist_empty = whitelists[whitelist].whitelist_empty;
  158. module_size = grub_util_get_image_size (argv[1]);
  159. module_img = grub_util_read_image (argv[1]);
  160. if (archs[arch].voidp_sizeof == 8)
  161. grub_module_verify64(module_img, module_size, &archs[arch], whitelist_empty);
  162. else
  163. grub_module_verify32(module_img, module_size, &archs[arch], whitelist_empty);
  164. return 0;
  165. }