dcavalca / rpms / grub2

Forked from rpms/grub2 3 years ago
Clone
28f7f8
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
28f7f8
From: Andrei Borzenkov <arvidjaar@gmail.com>
28f7f8
Date: Wed, 3 Feb 2016 20:34:55 +0300
28f7f8
Subject: [PATCH] support modules without symbol table
28f7f8
28f7f8
all_video module does not have any code or data and exists solely for
28f7f8
.moddeps section to pull in dependencies. This makes all symbols unneeded.
28f7f8
28f7f8
While in current binutils (last released version as of this commit is 2.26)
28f7f8
``strip --strip-unneeded'' unintentionally adds section symbols for each
28f7f8
existing section, this behavior was considered a bug and changed in commit
28f7f8
14f2c699ddca1e2f706342dffc59a6c7e23e844c to completely strip symbol table
28f7f8
in this case.
28f7f8
28f7f8
Older binutils (verified with 2.17) and some other toolchains (at least
28f7f8
elftoolchain r3223M), both used in FreeBSD, remove symbol table in all_video
28f7f8
as well.
28f7f8
28f7f8
Relax run-time check and do not return error for modules without symbol table.
28f7f8
Add additional checks to module verifier to make sure such modules
28f7f8
28f7f8
a) have non-empty .moddeps section. Without either externally visible symbols
28f7f8
or .moddeps modules are completely useless and should not be built.
28f7f8
28f7f8
b) do not have any relocations.
28f7f8
28f7f8
Closes: 46986
28f7f8
28f7f8
v2: add run-time check for empty symbol table if relocations are present as
28f7f8
    suggested by Vladimir.
28f7f8
---
28f7f8
 grub-core/kern/dl.c           |  8 +++++++-
28f7f8
 util/grub-module-verifierXX.c | 18 +++++++++++++++++-
28f7f8
 2 files changed, 24 insertions(+), 2 deletions(-)
28f7f8
28f7f8
diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
28f7f8
index b0b0405fcbe..c45afc64950 100644
28f7f8
--- a/grub-core/kern/dl.c
28f7f8
+++ b/grub-core/kern/dl.c
28f7f8
@@ -341,8 +341,11 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e)
28f7f8
     if (s->sh_type == SHT_SYMTAB)
28f7f8
       break;
28f7f8
 
28f7f8
+  /* Module without symbol table may still be used to pull in dependencies.
28f7f8
+     We verify at build time that such modules do not contain any relocations
28f7f8
+     that may reference symbol table. */
28f7f8
   if (i == e->e_shnum)
28f7f8
-    return grub_error (GRUB_ERR_BAD_MODULE, N_("no symbol table"));
28f7f8
+    return GRUB_ERR_NONE;
28f7f8
 
28f7f8
 #ifdef GRUB_MODULES_MACHINE_READONLY
28f7f8
   mod->symtab = grub_malloc (s->sh_size);
28f7f8
@@ -584,6 +587,9 @@ grub_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
28f7f8
 
28f7f8
 	if (seg)
28f7f8
 	  {
28f7f8
+	    if (!mod->symtab)
28f7f8
+	      return grub_error (GRUB_ERR_BAD_MODULE, "relocation without symbol table");
28f7f8
+
28f7f8
 	    err = grub_arch_dl_relocate_symbols (mod, ehdr, s, seg);
28f7f8
 	    if (err)
28f7f8
 	      return err;
28f7f8
diff --git a/util/grub-module-verifierXX.c b/util/grub-module-verifierXX.c
28f7f8
index f612d51f389..9c04caa63b4 100644
28f7f8
--- a/util/grub-module-verifierXX.c
28f7f8
+++ b/util/grub-module-verifierXX.c
28f7f8
@@ -176,7 +176,7 @@ get_symtab (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e, Elf_Word
28f7f8
       break;
28f7f8
 
28f7f8
   if (i == grub_target_to_host16 (e->e_shnum))
28f7f8
-    grub_util_error ("no symbol table");
28f7f8
+    return NULL;
28f7f8
 
28f7f8
   sym = (Elf_Sym *) ((char *) e + grub_target_to_host (s->sh_offset));
28f7f8
   *size = grub_target_to_host (s->sh_size);
28f7f8
@@ -191,7 +191,21 @@ check_symbols (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e)
28f7f8
   Elf_Word size, entsize;
28f7f8
   unsigned i;
28f7f8
 
28f7f8
+  /* Module without symbol table and without .moddeps section is useless
28f7f8
+     at boot time, so catch it early to prevent build errors */
28f7f8
   sym = get_symtab (arch, e, &size, &entsize);
28f7f8
+  if (!sym)
28f7f8
+    {
28f7f8
+      Elf_Shdr *s = find_section (arch, e, ".moddeps");
28f7f8
+
28f7f8
+      if (!s)
28f7f8
+	grub_util_error ("no symbol table and no .moddeps section");
28f7f8
+
28f7f8
+      if (!s->sh_size)
28f7f8
+	grub_util_error ("no symbol table and empty .moddeps section");
28f7f8
+
28f7f8
+      return;
28f7f8
+    }
28f7f8
 
28f7f8
   for (i = 0;
28f7f8
        i < size / entsize;
28f7f8
@@ -243,6 +257,8 @@ section_check_relocations (const struct grub_module_verifier_arch *arch, void *e
28f7f8
   Elf_Word symtabsize, symtabentsize;
28f7f8
 
28f7f8
   symtab = get_symtab (arch, ehdr, &symtabsize, &symtabentsize);
28f7f8
+  if (!symtab)
28f7f8
+    grub_util_error ("relocation without symbol table");
28f7f8
 
28f7f8
   for (rel = (Elf_Rel *) ((char *) ehdr + grub_target_to_host (s->sh_offset)),
28f7f8
 	 max = (Elf_Rel *) ((char *) rel + grub_target_to_host (s->sh_size));