grub-module-verifierXX.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. #include <string.h>
  2. #include <grub/elf.h>
  3. #include <grub/module_verifier.h>
  4. #include <grub/util/misc.h>
  5. #if defined(MODULEVERIFIER_ELF32)
  6. # define SUFFIX(x) x ## 32
  7. # define ELFCLASSXX ELFCLASS32
  8. # define Elf_Ehdr Elf32_Ehdr
  9. # define Elf_Phdr Elf32_Phdr
  10. # define Elf_Nhdr Elf32_Nhdr
  11. # define Elf_Addr Elf32_Addr
  12. # define Elf_Sym Elf32_Sym
  13. # define Elf_Off Elf32_Off
  14. # define Elf_Shdr Elf32_Shdr
  15. # define Elf_Rela Elf32_Rela
  16. # define Elf_Rel Elf32_Rel
  17. # define Elf_Word Elf32_Word
  18. # define Elf_Half Elf32_Half
  19. # define Elf_Section Elf32_Section
  20. # define ELF_R_SYM(val) ELF32_R_SYM(val)
  21. # define ELF_R_TYPE(val) ELF32_R_TYPE(val)
  22. # define ELF_ST_TYPE(val) ELF32_ST_TYPE(val)
  23. #elif defined(MODULEVERIFIER_ELF64)
  24. # define SUFFIX(x) x ## 64
  25. # define ELFCLASSXX ELFCLASS64
  26. # define Elf_Ehdr Elf64_Ehdr
  27. # define Elf_Phdr Elf64_Phdr
  28. # define Elf_Nhdr Elf64_Nhdr
  29. # define Elf_Addr Elf64_Addr
  30. # define Elf_Sym Elf64_Sym
  31. # define Elf_Off Elf64_Off
  32. # define Elf_Shdr Elf64_Shdr
  33. # define Elf_Rela Elf64_Rela
  34. # define Elf_Rel Elf64_Rel
  35. # define Elf_Word Elf64_Word
  36. # define Elf_Half Elf64_Half
  37. # define Elf_Section Elf64_Section
  38. # define ELF_R_SYM(val) ELF64_R_SYM(val)
  39. # define ELF_R_TYPE(val) ELF64_R_TYPE(val)
  40. # define ELF_ST_TYPE(val) ELF64_ST_TYPE(val)
  41. #else
  42. #error "I'm confused"
  43. #endif
  44. #define grub_target_to_host32(x) (grub_target_to_host32_real (arch, (x)))
  45. #define grub_host_to_target32(x) (grub_host_to_target32_real (arch, (x)))
  46. #define grub_target_to_host64(x) (grub_target_to_host64_real (arch, (x)))
  47. #define grub_host_to_target64(x) (grub_host_to_target64_real (arch, (x)))
  48. #define grub_host_to_target_addr(x) (grub_host_to_target_addr_real (arch, (x)))
  49. #define grub_target_to_host16(x) (grub_target_to_host16_real (arch, (x)))
  50. #define grub_host_to_target16(x) (grub_host_to_target16_real (arch, (x)))
  51. #define grub_target_to_host(val) grub_target_to_host_real(arch, (val))
  52. static inline grub_uint32_t
  53. grub_target_to_host32_real (const struct grub_module_verifier_arch *arch,
  54. grub_uint32_t in)
  55. {
  56. if (arch->bigendian)
  57. return grub_be_to_cpu32 (in);
  58. else
  59. return grub_le_to_cpu32 (in);
  60. }
  61. static inline grub_uint64_t
  62. grub_target_to_host64_real (const struct grub_module_verifier_arch *arch,
  63. grub_uint64_t in)
  64. {
  65. if (arch->bigendian)
  66. return grub_be_to_cpu64 (in);
  67. else
  68. return grub_le_to_cpu64 (in);
  69. }
  70. static inline grub_uint64_t
  71. grub_host_to_target64_real (const struct grub_module_verifier_arch *arch,
  72. grub_uint64_t in)
  73. {
  74. if (arch->bigendian)
  75. return grub_cpu_to_be64 (in);
  76. else
  77. return grub_cpu_to_le64 (in);
  78. }
  79. static inline grub_uint32_t
  80. grub_host_to_target32_real (const struct grub_module_verifier_arch *arch,
  81. grub_uint32_t in)
  82. {
  83. if (arch->bigendian)
  84. return grub_cpu_to_be32 (in);
  85. else
  86. return grub_cpu_to_le32 (in);
  87. }
  88. static inline grub_uint16_t
  89. grub_target_to_host16_real (const struct grub_module_verifier_arch *arch,
  90. grub_uint16_t in)
  91. {
  92. if (arch->bigendian)
  93. return grub_be_to_cpu16 (in);
  94. else
  95. return grub_le_to_cpu16 (in);
  96. }
  97. static inline grub_uint16_t
  98. grub_host_to_target16_real (const struct grub_module_verifier_arch *arch,
  99. grub_uint16_t in)
  100. {
  101. if (arch->bigendian)
  102. return grub_cpu_to_be16 (in);
  103. else
  104. return grub_cpu_to_le16 (in);
  105. }
  106. static inline grub_uint64_t
  107. grub_host_to_target_addr_real (const struct grub_module_verifier_arch *arch, grub_uint64_t in)
  108. {
  109. if (arch->voidp_sizeof == 8)
  110. return grub_host_to_target64_real (arch, in);
  111. else
  112. return grub_host_to_target32_real (arch, in);
  113. }
  114. static inline grub_uint64_t
  115. grub_target_to_host_real (const struct grub_module_verifier_arch *arch, grub_uint64_t in)
  116. {
  117. if (arch->voidp_sizeof == 8)
  118. return grub_target_to_host64_real (arch, in);
  119. else
  120. return grub_target_to_host32_real (arch, in);
  121. }
  122. static Elf_Shdr *
  123. find_section (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e, const char *name)
  124. {
  125. Elf_Shdr *s;
  126. const char *str;
  127. unsigned i;
  128. s = (Elf_Shdr *) ((char *) e + grub_target_to_host (e->e_shoff) + grub_target_to_host16 (e->e_shstrndx) * grub_target_to_host16 (e->e_shentsize));
  129. str = (char *) e + grub_target_to_host (s->sh_offset);
  130. for (i = 0, s = (Elf_Shdr *) ((char *) e + grub_target_to_host (e->e_shoff));
  131. i < grub_target_to_host16 (e->e_shnum);
  132. i++, s = (Elf_Shdr *) ((char *) s + grub_target_to_host16 (e->e_shentsize)))
  133. if (strcmp (str + grub_target_to_host32 (s->sh_name), name) == 0)
  134. return s;
  135. return NULL;
  136. }
  137. static void
  138. check_license (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e)
  139. {
  140. Elf_Shdr *s = find_section (arch, e, ".module_license");
  141. if (s && (strcmp ((char *) e + grub_target_to_host(s->sh_offset), "LICENSE=GPLv3") == 0
  142. || strcmp ((char *) e + grub_target_to_host(s->sh_offset), "LICENSE=GPLv3+") == 0
  143. || strcmp ((char *) e + grub_target_to_host(s->sh_offset), "LICENSE=GPLv2+") == 0))
  144. return;
  145. grub_util_error ("incompatible license");
  146. }
  147. static Elf_Sym *
  148. get_symtab (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e, Elf_Word *size, Elf_Word *entsize)
  149. {
  150. unsigned i;
  151. Elf_Shdr *s, *sections;
  152. Elf_Sym *sym;
  153. sections = (Elf_Shdr *) ((char *) e + grub_target_to_host (e->e_shoff));
  154. for (i = 0, s = sections;
  155. i < grub_target_to_host16 (e->e_shnum);
  156. i++, s = (Elf_Shdr *) ((char *) s + grub_target_to_host16 (e->e_shentsize)))
  157. if (grub_target_to_host32 (s->sh_type) == SHT_SYMTAB)
  158. break;
  159. if (i == grub_target_to_host16 (e->e_shnum))
  160. return NULL;
  161. sym = (Elf_Sym *) ((char *) e + grub_target_to_host (s->sh_offset));
  162. *size = grub_target_to_host (s->sh_size);
  163. *entsize = grub_target_to_host (s->sh_entsize);
  164. return sym;
  165. }
  166. static int
  167. is_whitelisted (const char *modname, const char **whitelist)
  168. {
  169. const char **ptr;
  170. if (!whitelist)
  171. return 0;
  172. if (!modname)
  173. return 0;
  174. for (ptr = whitelist; *ptr; ptr++)
  175. if (strcmp (modname, *ptr) == 0)
  176. return 1;
  177. return 0;
  178. }
  179. static void
  180. check_symbols (const struct grub_module_verifier_arch *arch,
  181. Elf_Ehdr *e, const char *modname,
  182. const char **whitelist_empty)
  183. {
  184. Elf_Sym *sym;
  185. Elf_Word size, entsize;
  186. unsigned i;
  187. /* Module without symbol table and without .moddeps section is useless
  188. at boot time, so catch it early to prevent build errors */
  189. sym = get_symtab (arch, e, &size, &entsize);
  190. if (!sym)
  191. {
  192. Elf_Shdr *s;
  193. /* However some modules are dependencies-only,
  194. e.g. insmod all_video pulls in all video drivers.
  195. Some platforms e.g. xen have no video drivers, so
  196. the module does nothing. */
  197. if (is_whitelisted (modname, whitelist_empty))
  198. return;
  199. s = find_section (arch, e, ".moddeps");
  200. if (!s)
  201. grub_util_error ("no symbol table and no .moddeps section");
  202. if (!s->sh_size)
  203. grub_util_error ("no symbol table and empty .moddeps section");
  204. return;
  205. }
  206. for (i = 0;
  207. i < size / entsize;
  208. i++, sym = (Elf_Sym *) ((char *) sym + entsize))
  209. {
  210. unsigned char type = ELF_ST_TYPE (sym->st_info);
  211. switch (type)
  212. {
  213. case STT_NOTYPE:
  214. case STT_OBJECT:
  215. case STT_FUNC:
  216. case STT_SECTION:
  217. case STT_FILE:
  218. break;
  219. default:
  220. return grub_util_error ("unknown symbol type `%d'", (int) type);
  221. }
  222. }
  223. }
  224. static int
  225. is_symbol_local(Elf_Sym *sym)
  226. {
  227. switch (ELF_ST_TYPE (sym->st_info))
  228. {
  229. case STT_NOTYPE:
  230. case STT_OBJECT:
  231. if (sym->st_name != 0 && sym->st_shndx == 0)
  232. return 0;
  233. return 1;
  234. case STT_FUNC:
  235. case STT_SECTION:
  236. return 1;
  237. default:
  238. return 0;
  239. }
  240. }
  241. static void
  242. section_check_relocations (const struct grub_module_verifier_arch *arch, void *ehdr,
  243. Elf_Shdr *s, size_t target_seg_size)
  244. {
  245. Elf_Rel *rel, *max;
  246. Elf_Sym *symtab;
  247. Elf_Word symtabsize, symtabentsize;
  248. symtab = get_symtab (arch, ehdr, &symtabsize, &symtabentsize);
  249. if (!symtab)
  250. grub_util_error ("relocation without symbol table");
  251. for (rel = (Elf_Rel *) ((char *) ehdr + grub_target_to_host (s->sh_offset)),
  252. max = (Elf_Rel *) ((char *) rel + grub_target_to_host (s->sh_size));
  253. rel < max;
  254. rel = (Elf_Rel *) ((char *) rel + grub_target_to_host (s->sh_entsize)))
  255. {
  256. Elf_Sym *sym;
  257. unsigned i;
  258. if (target_seg_size < grub_target_to_host (rel->r_offset))
  259. grub_util_error ("reloc offset is out of the segment");
  260. grub_uint32_t type = ELF_R_TYPE (grub_target_to_host (rel->r_info));
  261. if (arch->machine == EM_SPARCV9)
  262. type &= 0xff;
  263. for (i = 0; arch->supported_relocations[i] != -1; i++)
  264. if (type == arch->supported_relocations[i])
  265. break;
  266. if (arch->supported_relocations[i] != -1)
  267. continue;
  268. if (!arch->short_relocations)
  269. grub_util_error ("unsupported relocation 0x%x", type);
  270. for (i = 0; arch->short_relocations[i] != -1; i++)
  271. if (type == arch->short_relocations[i])
  272. break;
  273. if (arch->short_relocations[i] == -1)
  274. grub_util_error ("unsupported relocation 0x%x", type);
  275. sym = (Elf_Sym *) ((char *) symtab + symtabentsize * ELF_R_SYM (grub_target_to_host (rel->r_info)));
  276. if (is_symbol_local (sym))
  277. continue;
  278. grub_util_error ("relocation 0x%x is not module-local", type);
  279. }
  280. #if defined(MODULEVERIFIER_ELF64)
  281. if (arch->machine == EM_AARCH64)
  282. {
  283. unsigned unmatched_adr_got_page = 0;
  284. Elf_Rela *rel2;
  285. for (rel = (Elf_Rel *) ((char *) ehdr + grub_target_to_host (s->sh_offset)),
  286. max = (Elf_Rel *) ((char *) rel + grub_target_to_host (s->sh_size));
  287. rel < max;
  288. rel = (Elf_Rel *) ((char *) rel + grub_target_to_host (s->sh_entsize)))
  289. {
  290. switch (ELF_R_TYPE (grub_target_to_host (rel->r_info)))
  291. {
  292. case R_AARCH64_ADR_GOT_PAGE:
  293. unmatched_adr_got_page++;
  294. for (rel2 = (Elf_Rela *) ((char *) rel + grub_target_to_host (s->sh_entsize));
  295. rel2 < (Elf_Rela *) max;
  296. rel2 = (Elf_Rela *) ((char *) rel2 + grub_target_to_host (s->sh_entsize)))
  297. if (ELF_R_SYM (rel2->r_info)
  298. == ELF_R_SYM (rel->r_info)
  299. && ((Elf_Rela *) rel)->r_addend == rel2->r_addend
  300. && ELF_R_TYPE (rel2->r_info) == R_AARCH64_LD64_GOT_LO12_NC)
  301. break;
  302. if (rel2 >= (Elf_Rela *) max)
  303. grub_util_error ("ADR_GOT_PAGE without matching LD64_GOT_LO12_NC");
  304. break;
  305. case R_AARCH64_LD64_GOT_LO12_NC:
  306. if (unmatched_adr_got_page == 0)
  307. grub_util_error ("LD64_GOT_LO12_NC without matching ADR_GOT_PAGE");
  308. unmatched_adr_got_page--;
  309. break;
  310. }
  311. }
  312. }
  313. #endif
  314. }
  315. static void
  316. check_relocations (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e)
  317. {
  318. Elf_Shdr *s;
  319. unsigned i;
  320. for (i = 0, s = (Elf_Shdr *) ((char *) e + grub_target_to_host (e->e_shoff));
  321. i < grub_target_to_host16 (e->e_shnum);
  322. i++, s = (Elf_Shdr *) ((char *) s + grub_target_to_host16 (e->e_shentsize)))
  323. if (grub_target_to_host32 (s->sh_type) == SHT_REL || grub_target_to_host32 (s->sh_type) == SHT_RELA)
  324. {
  325. Elf_Shdr *ts;
  326. if (grub_target_to_host32 (s->sh_type) == SHT_REL && !(arch->flags & GRUB_MODULE_VERIFY_SUPPORTS_REL))
  327. grub_util_error ("unsupported SHT_REL");
  328. if (grub_target_to_host32 (s->sh_type) == SHT_RELA && !(arch->flags & GRUB_MODULE_VERIFY_SUPPORTS_RELA))
  329. grub_util_error ("unsupported SHT_RELA");
  330. /* Find the target segment. */
  331. if (grub_target_to_host32 (s->sh_info) >= grub_target_to_host16 (e->e_shnum))
  332. grub_util_error ("orphaned reloc section");
  333. ts = (Elf_Shdr *) ((char *) e + grub_target_to_host (e->e_shoff) + grub_target_to_host32 (s->sh_info) * grub_target_to_host16 (e->e_shentsize));
  334. section_check_relocations (arch, e, s, grub_target_to_host (ts->sh_size));
  335. }
  336. }
  337. void
  338. SUFFIX(grub_module_verify) (void *module_img, size_t size,
  339. const struct grub_module_verifier_arch *arch,
  340. const char **whitelist_empty)
  341. {
  342. Elf_Ehdr *e = module_img;
  343. /* Check the header size. */
  344. if (size < sizeof (Elf_Ehdr))
  345. grub_util_error ("ELF header smaller than expected");
  346. /* Check the magic numbers. */
  347. if (e->e_ident[EI_MAG0] != ELFMAG0
  348. || e->e_ident[EI_MAG1] != ELFMAG1
  349. || e->e_ident[EI_MAG2] != ELFMAG2
  350. || e->e_ident[EI_MAG3] != ELFMAG3
  351. || e->e_ident[EI_VERSION] != EV_CURRENT
  352. || grub_target_to_host32 (e->e_version) != EV_CURRENT)
  353. grub_util_error ("invalid arch-independent ELF magic");
  354. if (e->e_ident[EI_CLASS] != ELFCLASSXX
  355. || e->e_ident[EI_DATA] != (arch->bigendian ? ELFDATA2MSB : ELFDATA2LSB)
  356. || grub_target_to_host16 (e->e_machine) != arch->machine)
  357. grub_util_error ("invalid arch-dependent ELF magic");
  358. if (grub_target_to_host16 (e->e_type) != ET_REL)
  359. {
  360. grub_util_error ("this ELF file is not of the right type");
  361. }
  362. /* Make sure that every section is within the core. */
  363. if (size < grub_target_to_host (e->e_shoff)
  364. + (grub_uint32_t) grub_target_to_host16 (e->e_shentsize) * grub_target_to_host16(e->e_shnum))
  365. {
  366. grub_util_error ("ELF sections outside core");
  367. }
  368. check_license (arch, e);
  369. Elf_Shdr *s;
  370. const char *modname;
  371. s = find_section (arch, e, ".modname");
  372. if (!s)
  373. grub_util_error ("no module name found");
  374. modname = (const char *) e + grub_target_to_host (s->sh_offset);
  375. check_symbols(arch, e, modname, whitelist_empty);
  376. check_relocations(arch, e);
  377. }