123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- #include <stdio.h>
- #include <string.h>
- #include <grub/elf.h>
- #include <grub/module_verifier.h>
- #include <grub/misc.h>
- #include <grub/util/misc.h>
- struct grub_module_verifier_arch archs[] = {
- { "i386", 4, 0, EM_386, GRUB_MODULE_VERIFY_SUPPORTS_REL, (int[]){
- R_386_32,
- R_386_PC32,
- -1
- } },
- { "x86_64", 8, 0, EM_X86_64, GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
- R_X86_64_64,
- R_X86_64_PC64,
- /* R_X86_64_32, R_X86_64_32S are supported but shouldn't be used because of their limited range. */
- -1
- }, (int[]){
- R_X86_64_PC32,
- -1
- }
- },
- { "powerpc", 4, 1, EM_PPC, GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
- GRUB_ELF_R_PPC_ADDR16_LO,
- GRUB_ELF_R_PPC_REL24, /* It has limited range but GRUB adds trampolines when necessarry. */
- GRUB_ELF_R_PPC_ADDR16_HA,
- GRUB_ELF_R_PPC_ADDR32,
- GRUB_ELF_R_PPC_REL32,
- -1
- } },
- { "sparc64", 8, 1, EM_SPARCV9, GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
- R_SPARC_WDISP30, /* It has limited range but GRUB adds trampolines when necessarry. */
- R_SPARC_HH22,
- R_SPARC_HM10,
- R_SPARC_LM22,
- R_SPARC_LO10,
- R_SPARC_64,
- R_SPARC_OLO10,
- /* Following 2 relocations have limited range but unfortunately
- clang generates them, as it doesn't implement mcmodel=large properly.
- At least our heap and core are under 4G, so it's not a problem
- usually. */
- R_SPARC_HI22,
- R_SPARC_32,
- -1
- } },
- { "ia64", 8, 0, EM_IA_64, GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
- R_IA64_PCREL21B, /* We should verify that it's pointing either
- to a function or to a section in the same module.
- Checking that external symbol is a function is
- non-trivial and I have never seen this relocation used
- for anything else, so assume that it always points to a
- function.
- */
- R_IA64_SEGREL64LSB,
- R_IA64_FPTR64LSB,
- R_IA64_DIR64LSB,
- R_IA64_PCREL64LSB,
- R_IA64_LTOFF22X,
- R_IA64_LTOFF22,
- R_IA64_GPREL64I,
- R_IA64_LTOFF_FPTR22,
- R_IA64_LDXMOV,
- -1
- }, (int[]){
- R_IA64_GPREL22,
- -1
- } },
- { "mipsel", 4, 0, EM_MIPS, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
- R_MIPS_HI16,
- R_MIPS_LO16,
- R_MIPS_32,
- R_MIPS_GPREL32,
- R_MIPS_26,
- R_MIPS_GOT16,
- R_MIPS_CALL16,
- R_MIPS_JALR,
- -1
- } },
- { "mips", 4, 1, EM_MIPS, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
- R_MIPS_HI16,
- R_MIPS_LO16,
- R_MIPS_32,
- R_MIPS_GPREL32,
- R_MIPS_26,
- R_MIPS_GOT16,
- R_MIPS_CALL16,
- R_MIPS_JALR,
- -1
- } },
- { "arm", 4, 0, EM_ARM, GRUB_MODULE_VERIFY_SUPPORTS_REL, (int[]){
- /* Some relocations are range-limited but trampolines are added when necessarry. */
- R_ARM_ABS32,
- R_ARM_CALL,
- R_ARM_JUMP24,
- R_ARM_THM_CALL,
- R_ARM_THM_JUMP24,
- R_ARM_V4BX,
- R_ARM_THM_MOVW_ABS_NC,
- R_ARM_THM_MOVT_ABS,
- R_ARM_THM_JUMP19,
- -1
- } },
- { "arm64", 8, 0, EM_AARCH64, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
- R_AARCH64_ABS64,
- R_AARCH64_CALL26,
- R_AARCH64_JUMP26,
- R_AARCH64_ADR_GOT_PAGE,
- R_AARCH64_LD64_GOT_LO12_NC,
- -1
- }, (int[]){
- R_AARCH64_ADR_PREL_PG_HI21,
- R_AARCH64_ADD_ABS_LO12_NC,
- R_AARCH64_LDST64_ABS_LO12_NC,
- R_AARCH64_PREL32,
- -1
- }
- },
- };
- struct platform_whitelist {
- const char *arch;
- const char *platform;
- const char **whitelist_empty;
- };
- static struct platform_whitelist whitelists[] = {
- {"i386", "xen", (const char *[]) {"all_video", 0}},
- {"x86_64", "xen", (const char *[]) {"all_video", 0}},
- {"sparc64", "ieee1275", (const char *[]) {"all_video", 0}},
- /* video is compiled-in on MIPS. */
- {"mipsel", "loongson", (const char *[]) {"all_video", 0}},
- {"mipsel", "qemu_mips", (const char *[]) {"all_video", 0}},
- {"mipsel", "arc", (const char *[]) {"all_video", 0}},
- {"mips", "qemu_mips", (const char *[]) {"all_video", 0}},
- {"mips", "arc", (const char *[]) {"all_video", 0}},
- };
- int
- main (int argc, char **argv)
- {
- size_t module_size;
- unsigned arch, whitelist;
- const char **whitelist_empty = 0;
- char *module_img;
- if (argc != 4) {
- fprintf (stderr, "usage: %s FILE ARCH PLATFORM\n", argv[0]);
- return 1;
- }
- for (arch = 0; arch < ARRAY_SIZE(archs); arch++)
- if (strcmp(archs[arch].name, argv[2]) == 0)
- break;
- if (arch == ARRAY_SIZE(archs))
- grub_util_error("unknown arch: %s", argv[2]);
- for (whitelist = 0; whitelist < ARRAY_SIZE(whitelists); whitelist++)
- if (strcmp(whitelists[whitelist].arch, argv[2]) == 0
- && strcmp(whitelists[whitelist].platform, argv[3]) == 0)
- break;
- if (whitelist != ARRAY_SIZE(whitelists))
- whitelist_empty = whitelists[whitelist].whitelist_empty;
- module_size = grub_util_get_image_size (argv[1]);
- module_img = grub_util_read_image (argv[1]);
- if (archs[arch].voidp_sizeof == 8)
- grub_module_verify64(module_img, module_size, &archs[arch], whitelist_empty);
- else
- grub_module_verify32(module_img, module_size, &archs[arch], whitelist_empty);
- return 0;
- }
|