grub-module-verifierXX.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  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 char * const filename,
  139. const struct grub_module_verifier_arch *arch, Elf_Ehdr *e)
  140. {
  141. Elf_Shdr *s = find_section (arch, e, ".module_license");
  142. if (s && (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=GPLv3+") == 0
  144. || strcmp ((char *) e + grub_target_to_host(s->sh_offset), "LICENSE=GPLv2+") == 0))
  145. return;
  146. grub_util_error ("%s: incompatible license", filename);
  147. }
  148. static Elf_Sym *
  149. get_symtab (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e, Elf_Word *size, Elf_Word *entsize)
  150. {
  151. unsigned i;
  152. Elf_Shdr *s, *sections;
  153. Elf_Sym *sym;
  154. sections = (Elf_Shdr *) ((char *) e + grub_target_to_host (e->e_shoff));
  155. for (i = 0, s = sections;
  156. i < grub_target_to_host16 (e->e_shnum);
  157. i++, s = (Elf_Shdr *) ((char *) s + grub_target_to_host16 (e->e_shentsize)))
  158. if (grub_target_to_host32 (s->sh_type) == SHT_SYMTAB)
  159. break;
  160. if (i == grub_target_to_host16 (e->e_shnum))
  161. return NULL;
  162. sym = (Elf_Sym *) ((char *) e + grub_target_to_host (s->sh_offset));
  163. *size = grub_target_to_host (s->sh_size);
  164. *entsize = grub_target_to_host (s->sh_entsize);
  165. return sym;
  166. }
  167. static int
  168. is_whitelisted (const char *modname, const char **whitelist)
  169. {
  170. const char **ptr;
  171. if (!whitelist)
  172. return 0;
  173. if (!modname)
  174. return 0;
  175. for (ptr = whitelist; *ptr; ptr++)
  176. if (strcmp (modname, *ptr) == 0)
  177. return 1;
  178. return 0;
  179. }
  180. static void
  181. check_symbols (const struct grub_module_verifier_arch *arch,
  182. Elf_Ehdr *e, const char *modname,
  183. const char **whitelist_empty)
  184. {
  185. Elf_Sym *sym;
  186. Elf_Word size, entsize;
  187. unsigned i;
  188. /* Module without symbol table and without .moddeps section is useless
  189. at boot time, so catch it early to prevent build errors */
  190. sym = get_symtab (arch, e, &size, &entsize);
  191. if (!sym)
  192. {
  193. Elf_Shdr *s;
  194. /* However some modules are dependencies-only,
  195. e.g. insmod all_video pulls in all video drivers.
  196. Some platforms e.g. xen have no video drivers, so
  197. the module does nothing. */
  198. if (is_whitelisted (modname, whitelist_empty))
  199. return;
  200. s = find_section (arch, e, ".moddeps");
  201. if (!s)
  202. grub_util_error ("%s: no symbol table and no .moddeps section", modname);
  203. if (!s->sh_size)
  204. grub_util_error ("%s: no symbol table and empty .moddeps section", modname);
  205. return;
  206. }
  207. for (i = 0;
  208. i < size / entsize;
  209. i++, sym = (Elf_Sym *) ((char *) sym + entsize))
  210. {
  211. unsigned char type = ELF_ST_TYPE (sym->st_info);
  212. switch (type)
  213. {
  214. case STT_NOTYPE:
  215. case STT_OBJECT:
  216. case STT_FUNC:
  217. case STT_SECTION:
  218. case STT_FILE:
  219. break;
  220. default:
  221. return grub_util_error ("%s: unknown symbol type `%d'", modname, (int) type);
  222. }
  223. }
  224. }
  225. static int
  226. is_symbol_local(Elf_Sym *sym)
  227. {
  228. switch (ELF_ST_TYPE (sym->st_info))
  229. {
  230. case STT_NOTYPE:
  231. case STT_OBJECT:
  232. if (sym->st_name != 0 && sym->st_shndx == 0)
  233. return 0;
  234. return 1;
  235. case STT_FUNC:
  236. case STT_SECTION:
  237. return 1;
  238. default:
  239. return 0;
  240. }
  241. }
  242. static void
  243. section_check_relocations (const char * const modname,
  244. const struct grub_module_verifier_arch *arch, void *ehdr,
  245. Elf_Shdr *s, size_t target_seg_size)
  246. {
  247. Elf_Rel *rel, *max;
  248. Elf_Sym *symtab;
  249. Elf_Word symtabsize, symtabentsize;
  250. symtab = get_symtab (arch, ehdr, &symtabsize, &symtabentsize);
  251. if (!symtab)
  252. grub_util_error ("%s: relocation without symbol table", modname);
  253. for (rel = (Elf_Rel *) ((char *) ehdr + grub_target_to_host (s->sh_offset)),
  254. max = (Elf_Rel *) ((char *) rel + grub_target_to_host (s->sh_size));
  255. rel < max;
  256. rel = (Elf_Rel *) ((char *) rel + grub_target_to_host (s->sh_entsize)))
  257. {
  258. Elf_Sym *sym;
  259. unsigned i;
  260. if (target_seg_size < grub_target_to_host (rel->r_offset))
  261. grub_util_error ("%s: reloc offset is out of the segment", modname);
  262. grub_uint32_t type = ELF_R_TYPE (grub_target_to_host (rel->r_info));
  263. if (arch->machine == EM_SPARCV9)
  264. type &= 0xff;
  265. for (i = 0; arch->supported_relocations[i] != -1; i++)
  266. if (type == arch->supported_relocations[i])
  267. break;
  268. if (arch->supported_relocations[i] != -1)
  269. continue;
  270. if (!arch->short_relocations)
  271. grub_util_error ("%s: unsupported relocation 0x%x", modname, type);
  272. for (i = 0; arch->short_relocations[i] != -1; i++)
  273. if (type == arch->short_relocations[i])
  274. break;
  275. if (arch->short_relocations[i] == -1)
  276. grub_util_error ("%s: unsupported relocation 0x%x", modname, type);
  277. sym = (Elf_Sym *) ((char *) symtab + symtabentsize * ELF_R_SYM (grub_target_to_host (rel->r_info)));
  278. if (is_symbol_local (sym))
  279. continue;
  280. grub_util_error ("%s: relocation 0x%x is not module-local", modname, type);
  281. }
  282. #if defined(MODULEVERIFIER_ELF64)
  283. if (arch->machine == EM_AARCH64)
  284. {
  285. unsigned unmatched_adr_got_page = 0;
  286. Elf_Rela *rel2;
  287. for (rel = (Elf_Rel *) ((char *) ehdr + grub_target_to_host (s->sh_offset)),
  288. max = (Elf_Rel *) ((char *) rel + grub_target_to_host (s->sh_size));
  289. rel < max;
  290. rel = (Elf_Rel *) ((char *) rel + grub_target_to_host (s->sh_entsize)))
  291. {
  292. switch (ELF_R_TYPE (grub_target_to_host (rel->r_info)))
  293. {
  294. case R_AARCH64_ADR_GOT_PAGE:
  295. unmatched_adr_got_page++;
  296. for (rel2 = (Elf_Rela *) ((char *) rel + grub_target_to_host (s->sh_entsize));
  297. rel2 < (Elf_Rela *) max;
  298. rel2 = (Elf_Rela *) ((char *) rel2 + grub_target_to_host (s->sh_entsize)))
  299. if (ELF_R_SYM (rel2->r_info)
  300. == ELF_R_SYM (rel->r_info)
  301. && ((Elf_Rela *) rel)->r_addend == rel2->r_addend
  302. && ELF_R_TYPE (rel2->r_info) == R_AARCH64_LD64_GOT_LO12_NC)
  303. break;
  304. if (rel2 >= (Elf_Rela *) max)
  305. grub_util_error ("%s: ADR_GOT_PAGE without matching LD64_GOT_LO12_NC", modname);
  306. break;
  307. case R_AARCH64_LD64_GOT_LO12_NC:
  308. if (unmatched_adr_got_page == 0)
  309. grub_util_error ("%s: LD64_GOT_LO12_NC without matching ADR_GOT_PAGE", modname);
  310. unmatched_adr_got_page--;
  311. break;
  312. }
  313. }
  314. }
  315. #endif
  316. }
  317. static void
  318. check_relocations (const char * const modname,
  319. const struct grub_module_verifier_arch *arch, Elf_Ehdr *e)
  320. {
  321. Elf_Shdr *s;
  322. unsigned i;
  323. for (i = 0, s = (Elf_Shdr *) ((char *) e + grub_target_to_host (e->e_shoff));
  324. i < grub_target_to_host16 (e->e_shnum);
  325. i++, s = (Elf_Shdr *) ((char *) s + grub_target_to_host16 (e->e_shentsize)))
  326. if (grub_target_to_host32 (s->sh_type) == SHT_REL || grub_target_to_host32 (s->sh_type) == SHT_RELA)
  327. {
  328. Elf_Shdr *ts;
  329. if (grub_target_to_host32 (s->sh_type) == SHT_REL && !(arch->flags & GRUB_MODULE_VERIFY_SUPPORTS_REL))
  330. grub_util_error ("%s: unsupported SHT_REL", modname);
  331. if (grub_target_to_host32 (s->sh_type) == SHT_RELA && !(arch->flags & GRUB_MODULE_VERIFY_SUPPORTS_RELA))
  332. grub_util_error ("%s: unsupported SHT_RELA", modname);
  333. /* Find the target segment. */
  334. if (grub_target_to_host32 (s->sh_info) >= grub_target_to_host16 (e->e_shnum))
  335. grub_util_error ("%s: orphaned reloc section", modname);
  336. 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));
  337. section_check_relocations (modname, arch, e, s, grub_target_to_host (ts->sh_size));
  338. }
  339. }
  340. void
  341. SUFFIX(grub_module_verify) (const char * const filename,
  342. void *module_img, size_t size,
  343. const struct grub_module_verifier_arch *arch,
  344. const char **whitelist_empty)
  345. {
  346. Elf_Ehdr *e = module_img;
  347. /* Check the header size. */
  348. if (size < sizeof (Elf_Ehdr))
  349. grub_util_error ("%s: ELF header smaller than expected", filename);
  350. /* Check the magic numbers. */
  351. if (e->e_ident[EI_MAG0] != ELFMAG0
  352. || e->e_ident[EI_MAG1] != ELFMAG1
  353. || e->e_ident[EI_MAG2] != ELFMAG2
  354. || e->e_ident[EI_MAG3] != ELFMAG3
  355. || e->e_ident[EI_VERSION] != EV_CURRENT
  356. || grub_target_to_host32 (e->e_version) != EV_CURRENT)
  357. grub_util_error ("%s: invalid arch-independent ELF magic", filename);
  358. if (e->e_ident[EI_CLASS] != ELFCLASSXX
  359. || e->e_ident[EI_DATA] != (arch->bigendian ? ELFDATA2MSB : ELFDATA2LSB)
  360. || grub_target_to_host16 (e->e_machine) != arch->machine)
  361. grub_util_error ("%s: invalid arch-dependent ELF magic", filename);
  362. if (grub_target_to_host16 (e->e_type) != ET_REL)
  363. {
  364. grub_util_error ("%s: this ELF file is not of the right type", filename);
  365. }
  366. /* Make sure that every section is within the core. */
  367. if (size < grub_target_to_host (e->e_shoff)
  368. + (grub_uint32_t) grub_target_to_host16 (e->e_shentsize) * grub_target_to_host16(e->e_shnum))
  369. {
  370. grub_util_error ("%s: ELF sections outside core", filename);
  371. }
  372. check_license (filename, arch, e);
  373. Elf_Shdr *s;
  374. const char *modname;
  375. s = find_section (arch, e, ".modname");
  376. if (!s)
  377. grub_util_error ("%s: no module name found", filename);
  378. modname = (const char *) e + grub_target_to_host (s->sh_offset);
  379. check_symbols(arch, e, modname, whitelist_empty);
  380. check_relocations(modname, arch, e);
  381. }