grub-module-verifier.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  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. { "loongarch64", 8, 0, EM_LOONGARCH, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
  121. R_LARCH_NONE,
  122. R_LARCH_64,
  123. R_LARCH_MARK_LA,
  124. R_LARCH_SOP_PUSH_PCREL,
  125. R_LARCH_SOP_PUSH_ABSOLUTE,
  126. R_LARCH_SOP_PUSH_PLT_PCREL,
  127. R_LARCH_SOP_SUB,
  128. R_LARCH_SOP_SL,
  129. R_LARCH_SOP_SR,
  130. R_LARCH_SOP_ADD,
  131. R_LARCH_SOP_AND,
  132. R_LARCH_SOP_IF_ELSE,
  133. R_LARCH_SOP_POP_32_S_10_5,
  134. R_LARCH_SOP_POP_32_U_10_12,
  135. R_LARCH_SOP_POP_32_S_10_12,
  136. R_LARCH_SOP_POP_32_S_10_16,
  137. R_LARCH_SOP_POP_32_S_10_16_S2,
  138. R_LARCH_SOP_POP_32_S_5_20,
  139. R_LARCH_SOP_POP_32_S_0_5_10_16_S2,
  140. R_LARCH_SOP_POP_32_S_0_10_10_16_S2,
  141. R_LARCH_B26,
  142. R_LARCH_ABS_HI20,
  143. R_LARCH_ABS_LO12,
  144. R_LARCH_ABS64_LO20,
  145. R_LARCH_ABS64_HI12,
  146. R_LARCH_PCALA_HI20,
  147. R_LARCH_PCALA_LO12,
  148. -1
  149. }, (int[]){
  150. -1
  151. }
  152. },
  153. { "riscv32", 4, 0, EM_RISCV, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
  154. R_RISCV_32,
  155. R_RISCV_64,
  156. R_RISCV_ADD8,
  157. R_RISCV_ADD16,
  158. R_RISCV_ADD32,
  159. R_RISCV_ADD64,
  160. R_RISCV_SUB8,
  161. R_RISCV_SUB16,
  162. R_RISCV_SUB32,
  163. R_RISCV_SUB64,
  164. R_RISCV_ALIGN,
  165. R_RISCV_BRANCH,
  166. R_RISCV_CALL,
  167. R_RISCV_CALL_PLT,
  168. R_RISCV_GOT_HI20,
  169. R_RISCV_HI20,
  170. R_RISCV_JAL,
  171. R_RISCV_LO12_I,
  172. R_RISCV_LO12_S,
  173. R_RISCV_PCREL_HI20,
  174. R_RISCV_PCREL_LO12_I,
  175. R_RISCV_PCREL_LO12_S,
  176. R_RISCV_RELAX,
  177. R_RISCV_RVC_BRANCH,
  178. R_RISCV_RVC_JUMP,
  179. -1
  180. } },
  181. { "riscv64", 8, 0, EM_RISCV, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
  182. R_RISCV_32,
  183. R_RISCV_64,
  184. R_RISCV_ADD8,
  185. R_RISCV_ADD16,
  186. R_RISCV_ADD32,
  187. R_RISCV_ADD64,
  188. R_RISCV_SUB8,
  189. R_RISCV_SUB16,
  190. R_RISCV_SUB32,
  191. R_RISCV_SUB64,
  192. R_RISCV_ALIGN,
  193. R_RISCV_BRANCH,
  194. R_RISCV_CALL,
  195. R_RISCV_CALL_PLT,
  196. R_RISCV_GOT_HI20,
  197. R_RISCV_HI20,
  198. R_RISCV_JAL,
  199. R_RISCV_LO12_I,
  200. R_RISCV_LO12_S,
  201. R_RISCV_PCREL_HI20,
  202. R_RISCV_PCREL_LO12_I,
  203. R_RISCV_PCREL_LO12_S,
  204. R_RISCV_RELAX,
  205. R_RISCV_RVC_BRANCH,
  206. R_RISCV_RVC_JUMP,
  207. -1
  208. }
  209. },
  210. };
  211. struct platform_whitelist {
  212. const char *arch;
  213. const char *platform;
  214. const char **whitelist_empty;
  215. };
  216. static struct platform_whitelist whitelists[] = {
  217. {"i386", "xen", (const char *[]) {"all_video", 0}},
  218. {"i386", "xen_pvh", (const char *[]) {"all_video", 0}},
  219. {"x86_64", "xen", (const char *[]) {"all_video", 0}},
  220. {"sparc64", "ieee1275", (const char *[]) {"all_video", 0}},
  221. /* video is compiled-in on MIPS. */
  222. {"mipsel", "loongson", (const char *[]) {"all_video", 0}},
  223. {"mipsel", "qemu_mips", (const char *[]) {"all_video", 0}},
  224. {"mipsel", "arc", (const char *[]) {"all_video", 0}},
  225. {"mips", "qemu_mips", (const char *[]) {"all_video", 0}},
  226. {"mips", "arc", (const char *[]) {"all_video", 0}},
  227. };
  228. int
  229. main (int argc, char **argv)
  230. {
  231. size_t module_size;
  232. unsigned arch, whitelist;
  233. const char **whitelist_empty = 0;
  234. char *module_img;
  235. if (argc != 4) {
  236. fprintf (stderr, "usage: %s FILE ARCH PLATFORM\n", argv[0]);
  237. return 1;
  238. }
  239. for (arch = 0; arch < ARRAY_SIZE(archs); arch++)
  240. if (strcmp(archs[arch].name, argv[2]) == 0)
  241. break;
  242. if (arch == ARRAY_SIZE(archs))
  243. grub_util_error("%s: unknown arch: %s", argv[1], argv[2]);
  244. for (whitelist = 0; whitelist < ARRAY_SIZE(whitelists); whitelist++)
  245. if (strcmp(whitelists[whitelist].arch, argv[2]) == 0
  246. && strcmp(whitelists[whitelist].platform, argv[3]) == 0)
  247. break;
  248. if (whitelist != ARRAY_SIZE(whitelists))
  249. whitelist_empty = whitelists[whitelist].whitelist_empty;
  250. module_size = grub_util_get_image_size (argv[1]);
  251. module_img = grub_util_read_image (argv[1]);
  252. if (archs[arch].voidp_sizeof == 8)
  253. grub_module_verify64(argv[1], module_img, module_size, &archs[arch], whitelist_empty);
  254. else
  255. grub_module_verify32(argv[1], module_img, module_size, &archs[arch], whitelist_empty);
  256. return 0;
  257. }