grub-module-verifierXX.c 15 KB

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