diff --git a/grub-core/genmod.sh.in b/grub-core/genmod.sh.in index 045817b15..03cc3b7f6 100644 --- a/grub-core/genmod.sh.in +++ b/grub-core/genmod.sh.in @@ -94,6 +94,6 @@ else rm -f $tmpfile.bin fi if test x@platform@ != xemu; then - ./build-grub-module-verifier@BUILD_EXEEXT@ $tmpfile @target_cpu@ + ./build-grub-module-verifier@BUILD_EXEEXT@ $tmpfile @target_cpu@ @platform@ fi mv $tmpfile $outfile diff --git a/include/grub/module_verifier.h b/include/grub/module_verifier.h index 6cddff30f..f4870cb9c 100644 --- a/include/grub/module_verifier.h +++ b/include/grub/module_verifier.h @@ -16,5 +16,5 @@ struct grub_module_verifier_arch { const int *short_relocations; }; -void grub_module_verify64(void *module_img, size_t module_size, const struct grub_module_verifier_arch *arch); -void grub_module_verify32(void *module_img, size_t module_size, const struct grub_module_verifier_arch *arch); +void grub_module_verify64(void *module_img, size_t module_size, const struct grub_module_verifier_arch *arch, const char **whitelist_empty); +void grub_module_verify32(void *module_img, size_t module_size, const struct grub_module_verifier_arch *arch, const char **whitelist_empty); diff --git a/util/grub-module-verifier.c b/util/grub-module-verifier.c index 405c91170..de14c62e7 100644 --- a/util/grub-module-verifier.c +++ b/util/grub-module-verifier.c @@ -116,15 +116,27 @@ struct grub_module_verifier_arch archs[] = { }, }; +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}} +}; + int main (int argc, char **argv) { size_t module_size; - unsigned arch; + unsigned arch, whitelist; + const char **whitelist_empty = 0; char *module_img; - if (argc != 3) { - fprintf (stderr, "usage: %s FILE ARCH\n", argv[0]); + if (argc != 4) { + fprintf (stderr, "usage: %s FILE ARCH PLATFORM\n", argv[0]); return 1; } @@ -134,11 +146,18 @@ main (int argc, char **argv) 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]); + grub_module_verify64(module_img, module_size, &archs[arch], whitelist_empty); else - grub_module_verify32(module_img, module_size, &archs[arch]); + grub_module_verify32(module_img, module_size, &archs[arch], whitelist_empty); return 0; } diff --git a/util/grub-module-verifierXX.c b/util/grub-module-verifierXX.c index 9c04caa63..2c0c690fa 100644 --- a/util/grub-module-verifierXX.c +++ b/util/grub-module-verifierXX.c @@ -184,8 +184,24 @@ get_symtab (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e, Elf_Word return sym; } +static int +is_whitelisted (const char *modname, const char **whitelist) +{ + const char **ptr; + if (!whitelist) + return 0; + if (!modname) + return 0; + for (ptr = whitelist; *ptr; ptr++) + if (strcmp (modname, *ptr) == 0) + return 1; + return 0; +} + static void -check_symbols (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e) +check_symbols (const struct grub_module_verifier_arch *arch, + Elf_Ehdr *e, const char *modname, + const char **whitelist_empty) { Elf_Sym *sym; Elf_Word size, entsize; @@ -196,7 +212,16 @@ check_symbols (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e) sym = get_symtab (arch, e, &size, &entsize); if (!sym) { - Elf_Shdr *s = find_section (arch, e, ".moddeps"); + Elf_Shdr *s; + + /* However some modules are dependencies-only, + e.g. insmod all_video pulls in all video drivers. + Some platforms e.g. xen have no video drivers, so + the module does nothing. */ + if (is_whitelisted (modname, whitelist_empty)) + return; + + s = find_section (arch, e, ".moddeps"); if (!s) grub_util_error ("no symbol table and no .moddeps section"); @@ -324,7 +349,9 @@ check_relocations (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e) } void -SUFFIX(grub_module_verify) (void *module_img, size_t size, const struct grub_module_verifier_arch *arch) +SUFFIX(grub_module_verify) (void *module_img, size_t size, + const struct grub_module_verifier_arch *arch, + const char **whitelist_empty) { Elf_Ehdr *e = module_img; @@ -361,11 +388,14 @@ SUFFIX(grub_module_verify) (void *module_img, size_t size, const struct grub_mod check_license (arch, e); Elf_Shdr *s; + const char *modname; s = find_section (arch, e, ".modname"); if (!s) grub_util_error ("no module name found"); - check_symbols(arch, e); + modname = (const char *) e + grub_target_to_host (s->sh_offset); + + check_symbols(arch, e, modname, whitelist_empty); check_relocations(arch, e); }