grub-module-verifier.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  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. R_X86_64_PLT32,
  21. -1
  22. }
  23. },
  24. { "powerpc", 4, 1, EM_PPC, GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
  25. GRUB_ELF_R_PPC_ADDR16_LO,
  26. GRUB_ELF_R_PPC_REL24, /* It has limited range but GRUB adds trampolines when necessarry. */
  27. GRUB_ELF_R_PPC_ADDR16_HA,
  28. GRUB_ELF_R_PPC_ADDR32,
  29. GRUB_ELF_R_PPC_REL32,
  30. GRUB_ELF_R_PPC_PLTREL24,
  31. -1
  32. } },
  33. { "sparc64", 8, 1, EM_SPARCV9, GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
  34. R_SPARC_WDISP30, /* It has limited range but GRUB adds trampolines when necessarry. */
  35. R_SPARC_HH22,
  36. R_SPARC_HM10,
  37. R_SPARC_LM22,
  38. R_SPARC_LO10,
  39. R_SPARC_64,
  40. R_SPARC_OLO10,
  41. /* Following 2 relocations have limited range but unfortunately
  42. clang generates them, as it doesn't implement mcmodel=large properly.
  43. At least our heap and core are under 4G, so it's not a problem
  44. usually. */
  45. R_SPARC_HI22,
  46. R_SPARC_32,
  47. -1
  48. } },
  49. { "ia64", 8, 0, EM_IA_64, GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
  50. R_IA64_PCREL21B, /* We should verify that it's pointing either
  51. to a function or to a section in the same module.
  52. Checking that external symbol is a function is
  53. non-trivial and I have never seen this relocation used
  54. for anything else, so assume that it always points to a
  55. function.
  56. */
  57. R_IA64_SEGREL64LSB,
  58. R_IA64_FPTR64LSB,
  59. R_IA64_DIR64LSB,
  60. R_IA64_PCREL64LSB,
  61. R_IA64_LTOFF22X,
  62. R_IA64_LTOFF22,
  63. R_IA64_GPREL64I,
  64. R_IA64_LTOFF_FPTR22,
  65. R_IA64_LDXMOV,
  66. -1
  67. }, (int[]){
  68. R_IA64_GPREL22,
  69. -1
  70. } },
  71. { "mipsel", 4, 0, EM_MIPS, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
  72. R_MIPS_HI16,
  73. R_MIPS_LO16,
  74. R_MIPS_32,
  75. R_MIPS_GPREL32,
  76. R_MIPS_26,
  77. R_MIPS_GOT16,
  78. R_MIPS_CALL16,
  79. R_MIPS_JALR,
  80. -1
  81. } },
  82. { "mips", 4, 1, EM_MIPS, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
  83. R_MIPS_HI16,
  84. R_MIPS_LO16,
  85. R_MIPS_32,
  86. R_MIPS_GPREL32,
  87. R_MIPS_26,
  88. R_MIPS_GOT16,
  89. R_MIPS_CALL16,
  90. R_MIPS_JALR,
  91. -1
  92. } },
  93. { "arm", 4, 0, EM_ARM, GRUB_MODULE_VERIFY_SUPPORTS_REL, (int[]){
  94. /* Some relocations are range-limited but trampolines are added when necessarry. */
  95. R_ARM_ABS32,
  96. R_ARM_CALL,
  97. R_ARM_JUMP24,
  98. R_ARM_THM_CALL,
  99. R_ARM_THM_JUMP24,
  100. R_ARM_V4BX,
  101. R_ARM_THM_MOVW_ABS_NC,
  102. R_ARM_THM_MOVT_ABS,
  103. R_ARM_THM_JUMP19,
  104. -1
  105. } },
  106. { "arm64", 8, 0, EM_AARCH64, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
  107. R_AARCH64_ABS64,
  108. R_AARCH64_CALL26,
  109. R_AARCH64_JUMP26,
  110. R_AARCH64_ADR_GOT_PAGE,
  111. R_AARCH64_LD64_GOT_LO12_NC,
  112. -1
  113. }, (int[]){
  114. R_AARCH64_ADR_PREL_PG_HI21,
  115. R_AARCH64_ADD_ABS_LO12_NC,
  116. R_AARCH64_LDST64_ABS_LO12_NC,
  117. R_AARCH64_PREL32,
  118. -1
  119. } },
  120. { "riscv32", 4, 0, EM_RISCV, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
  121. R_RISCV_32,
  122. R_RISCV_64,
  123. R_RISCV_ADD8,
  124. R_RISCV_ADD16,
  125. R_RISCV_ADD32,
  126. R_RISCV_ADD64,
  127. R_RISCV_SUB8,
  128. R_RISCV_SUB16,
  129. R_RISCV_SUB32,
  130. R_RISCV_SUB64,
  131. R_RISCV_ALIGN,
  132. R_RISCV_BRANCH,
  133. R_RISCV_CALL,
  134. R_RISCV_CALL_PLT,
  135. R_RISCV_GOT_HI20,
  136. R_RISCV_HI20,
  137. R_RISCV_JAL,
  138. R_RISCV_LO12_I,
  139. R_RISCV_LO12_S,
  140. R_RISCV_PCREL_HI20,
  141. R_RISCV_PCREL_LO12_I,
  142. R_RISCV_PCREL_LO12_S,
  143. R_RISCV_RELAX,
  144. R_RISCV_RVC_BRANCH,
  145. R_RISCV_RVC_JUMP,
  146. -1
  147. } },
  148. { "riscv64", 8, 0, EM_RISCV, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
  149. R_RISCV_32,
  150. R_RISCV_64,
  151. R_RISCV_ADD8,
  152. R_RISCV_ADD16,
  153. R_RISCV_ADD32,
  154. R_RISCV_ADD64,
  155. R_RISCV_SUB8,
  156. R_RISCV_SUB16,
  157. R_RISCV_SUB32,
  158. R_RISCV_SUB64,
  159. R_RISCV_ALIGN,
  160. R_RISCV_BRANCH,
  161. R_RISCV_CALL,
  162. R_RISCV_CALL_PLT,
  163. R_RISCV_GOT_HI20,
  164. R_RISCV_HI20,
  165. R_RISCV_JAL,
  166. R_RISCV_LO12_I,
  167. R_RISCV_LO12_S,
  168. R_RISCV_PCREL_HI20,
  169. R_RISCV_PCREL_LO12_I,
  170. R_RISCV_PCREL_LO12_S,
  171. R_RISCV_RELAX,
  172. R_RISCV_RVC_BRANCH,
  173. R_RISCV_RVC_JUMP,
  174. -1
  175. }
  176. },
  177. };
  178. struct platform_whitelist {
  179. const char *arch;
  180. const char *platform;
  181. const char **whitelist_empty;
  182. };
  183. static struct platform_whitelist whitelists[] = {
  184. {"i386", "xen", (const char *[]) {"all_video", 0}},
  185. {"i386", "xen_pvh", (const char *[]) {"all_video", 0}},
  186. {"x86_64", "xen", (const char *[]) {"all_video", 0}},
  187. {"sparc64", "ieee1275", (const char *[]) {"all_video", 0}},
  188. /* video is compiled-in on MIPS. */
  189. {"mipsel", "loongson", (const char *[]) {"all_video", 0}},
  190. {"mipsel", "qemu_mips", (const char *[]) {"all_video", 0}},
  191. {"mipsel", "arc", (const char *[]) {"all_video", 0}},
  192. {"mips", "qemu_mips", (const char *[]) {"all_video", 0}},
  193. {"mips", "arc", (const char *[]) {"all_video", 0}},
  194. };
  195. int
  196. main (int argc, char **argv)
  197. {
  198. size_t module_size;
  199. unsigned arch, whitelist;
  200. const char **whitelist_empty = 0;
  201. char *module_img;
  202. if (argc != 4) {
  203. fprintf (stderr, "usage: %s FILE ARCH PLATFORM\n", argv[0]);
  204. return 1;
  205. }
  206. for (arch = 0; arch < ARRAY_SIZE(archs); arch++)
  207. if (strcmp(archs[arch].name, argv[2]) == 0)
  208. break;
  209. if (arch == ARRAY_SIZE(archs))
  210. grub_util_error("%s: unknown arch: %s", argv[1], argv[2]);
  211. for (whitelist = 0; whitelist < ARRAY_SIZE(whitelists); whitelist++)
  212. if (strcmp(whitelists[whitelist].arch, argv[2]) == 0
  213. && strcmp(whitelists[whitelist].platform, argv[3]) == 0)
  214. break;
  215. if (whitelist != ARRAY_SIZE(whitelists))
  216. whitelist_empty = whitelists[whitelist].whitelist_empty;
  217. module_size = grub_util_get_image_size (argv[1]);
  218. module_img = grub_util_read_image (argv[1]);
  219. if (archs[arch].voidp_sizeof == 8)
  220. grub_module_verify64(argv[1], module_img, module_size, &archs[arch], whitelist_empty);
  221. else
  222. grub_module_verify32(argv[1], module_img, module_size, &archs[arch], whitelist_empty);
  223. return 0;
  224. }