grub-module-verifierXX.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  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 void
  167. check_symbols (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e)
  168. {
  169. Elf_Sym *sym;
  170. Elf_Word size, entsize;
  171. unsigned i;
  172. /* Module without symbol table and without .moddeps section is useless
  173. at boot time, so catch it early to prevent build errors */
  174. sym = get_symtab (arch, e, &size, &entsize);
  175. if (!sym)
  176. {
  177. Elf_Shdr *s = find_section (arch, e, ".moddeps");
  178. if (!s)
  179. grub_util_error ("no symbol table and no .moddeps section");
  180. if (!s->sh_size)
  181. grub_util_error ("no symbol table and empty .moddeps section");
  182. return;
  183. }
  184. for (i = 0;
  185. i < size / entsize;
  186. i++, sym = (Elf_Sym *) ((char *) sym + entsize))
  187. {
  188. unsigned char type = ELF_ST_TYPE (sym->st_info);
  189. switch (type)
  190. {
  191. case STT_NOTYPE:
  192. case STT_OBJECT:
  193. case STT_FUNC:
  194. case STT_SECTION:
  195. case STT_FILE:
  196. break;
  197. default:
  198. return grub_util_error ("unknown symbol type `%d'", (int) type);
  199. }
  200. }
  201. }
  202. static int
  203. is_symbol_local(Elf_Sym *sym)
  204. {
  205. switch (ELF_ST_TYPE (sym->st_info))
  206. {
  207. case STT_NOTYPE:
  208. case STT_OBJECT:
  209. if (sym->st_name != 0 && sym->st_shndx == 0)
  210. return 0;
  211. return 1;
  212. case STT_FUNC:
  213. case STT_SECTION:
  214. return 1;
  215. default:
  216. return 0;
  217. }
  218. }
  219. static void
  220. section_check_relocations (const struct grub_module_verifier_arch *arch, void *ehdr,
  221. Elf_Shdr *s, size_t target_seg_size)
  222. {
  223. Elf_Rel *rel, *max;
  224. Elf_Sym *symtab;
  225. Elf_Word symtabsize, symtabentsize;
  226. symtab = get_symtab (arch, ehdr, &symtabsize, &symtabentsize);
  227. if (!symtab)
  228. grub_util_error ("relocation without symbol table");
  229. for (rel = (Elf_Rel *) ((char *) ehdr + grub_target_to_host (s->sh_offset)),
  230. max = (Elf_Rel *) ((char *) rel + grub_target_to_host (s->sh_size));
  231. rel < max;
  232. rel = (Elf_Rel *) ((char *) rel + grub_target_to_host (s->sh_entsize)))
  233. {
  234. Elf_Sym *sym;
  235. unsigned i;
  236. if (target_seg_size < grub_target_to_host (rel->r_offset))
  237. grub_util_error ("reloc offset is out of the segment");
  238. grub_uint32_t type = ELF_R_TYPE (grub_target_to_host (rel->r_info));
  239. if (arch->machine == EM_SPARCV9)
  240. type &= 0xff;
  241. for (i = 0; arch->supported_relocations[i] != -1; i++)
  242. if (type == arch->supported_relocations[i])
  243. break;
  244. if (arch->supported_relocations[i] != -1)
  245. continue;
  246. if (!arch->short_relocations)
  247. grub_util_error ("unsupported relocation 0x%x", type);
  248. for (i = 0; arch->short_relocations[i] != -1; i++)
  249. if (type == arch->short_relocations[i])
  250. break;
  251. if (arch->short_relocations[i] == -1)
  252. grub_util_error ("unsupported relocation 0x%x", type);
  253. sym = (Elf_Sym *) ((char *) symtab + symtabentsize * ELF_R_SYM (grub_target_to_host (rel->r_info)));
  254. if (is_symbol_local (sym))
  255. continue;
  256. grub_util_error ("relocation 0x%x is not module-local", type);
  257. }
  258. }
  259. static void
  260. check_relocations (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e)
  261. {
  262. Elf_Shdr *s;
  263. unsigned i;
  264. for (i = 0, s = (Elf_Shdr *) ((char *) e + grub_target_to_host (e->e_shoff));
  265. i < grub_target_to_host16 (e->e_shnum);
  266. i++, s = (Elf_Shdr *) ((char *) s + grub_target_to_host16 (e->e_shentsize)))
  267. if (grub_target_to_host32 (s->sh_type) == SHT_REL || grub_target_to_host32 (s->sh_type) == SHT_RELA)
  268. {
  269. Elf_Shdr *ts;
  270. if (grub_target_to_host32 (s->sh_type) == SHT_REL && !(arch->flags & GRUB_MODULE_VERIFY_SUPPORTS_REL))
  271. grub_util_error ("unsupported SHT_REL");
  272. if (grub_target_to_host32 (s->sh_type) == SHT_RELA && !(arch->flags & GRUB_MODULE_VERIFY_SUPPORTS_RELA))
  273. grub_util_error ("unsupported SHT_RELA");
  274. /* Find the target segment. */
  275. if (grub_target_to_host32 (s->sh_info) >= grub_target_to_host16 (e->e_shnum))
  276. grub_util_error ("orphaned reloc section");
  277. 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));
  278. section_check_relocations (arch, e, s, grub_target_to_host (ts->sh_size));
  279. }
  280. }
  281. void
  282. SUFFIX(grub_module_verify) (void *module_img, size_t size, const struct grub_module_verifier_arch *arch)
  283. {
  284. Elf_Ehdr *e = module_img;
  285. /* Check the header size. */
  286. if (size < sizeof (Elf_Ehdr))
  287. grub_util_error ("ELF header smaller than expected");
  288. /* Check the magic numbers. */
  289. if (e->e_ident[EI_MAG0] != ELFMAG0
  290. || e->e_ident[EI_MAG1] != ELFMAG1
  291. || e->e_ident[EI_MAG2] != ELFMAG2
  292. || e->e_ident[EI_MAG3] != ELFMAG3
  293. || e->e_ident[EI_VERSION] != EV_CURRENT
  294. || grub_target_to_host32 (e->e_version) != EV_CURRENT)
  295. grub_util_error ("invalid arch-independent ELF magic");
  296. if (e->e_ident[EI_CLASS] != ELFCLASSXX
  297. || e->e_ident[EI_DATA] != (arch->bigendian ? ELFDATA2MSB : ELFDATA2LSB)
  298. || grub_target_to_host16 (e->e_machine) != arch->machine)
  299. grub_util_error ("invalid arch-dependent ELF magic");
  300. if (grub_target_to_host16 (e->e_type) != ET_REL)
  301. {
  302. grub_util_error ("this ELF file is not of the right type");
  303. }
  304. /* Make sure that every section is within the core. */
  305. if (size < grub_target_to_host (e->e_shoff)
  306. + (grub_uint32_t) grub_target_to_host16 (e->e_shentsize) * grub_target_to_host16(e->e_shnum))
  307. {
  308. grub_util_error ("ELF sections outside core");
  309. }
  310. check_license (arch, e);
  311. Elf_Shdr *s;
  312. s = find_section (arch, e, ".modname");
  313. if (!s)
  314. grub_util_error ("no module name found");
  315. check_symbols(arch, e);
  316. check_relocations(arch, e);
  317. }