unstrip: Add sanity check for bogus sh_offset of allocated sections.
authorMark Wielaard <mark@klomp.org>
Sun, 20 Oct 2019 15:26:29 +0000 (17:26 +0200)
committerMark Wielaard <mark@klomp.org>
Sat, 26 Oct 2019 00:13:47 +0000 (02:13 +0200)
unstrip tries to preserve any allocated section offset in an
executable or shared library. If the offset is extremely large that
would cause the disk to fill up because we will write out a file with
lots of padding to put the section contents at that particular
offset. Add a sanity check that makes sure we just error out if there
is such a bogus offset by checking that no offset is larger than the
original ELF file size.

https://sourceware.org/bugzilla/show_bug.cgi?id=25083

Signed-off-by: Mark Wielaard <mark@klomp.org>
src/ChangeLog
src/unstrip.c

index 9a7d955..a20faff 100644 (file)
@@ -1,3 +1,7 @@
+2019-10-20  Mark Wielaard  <mark@klomp.org>
+
+       * unstrip.c (copy_elided_sections): Set and check max_off.
+
 2019-10-21  Mark Wielaard  <mark@klomp.org>
 
        * unstrip.c (adjust_relocs): Add map_size argument and check ndx
index c097d46..4e4366e 100644 (file)
@@ -1397,6 +1397,16 @@ more sections in stripped file than debug file -- arguments reversed?"));
   if (unlikely (stripped_shnum == 0))
     error (EXIT_FAILURE, 0, _("no sections in stripped file"));
 
+  /* Used as sanity check for allocated section offset, if the section
+     offset needs to be preserved.  We want to know the max size of the
+     ELF file, to check if any existing section offsets are OK.  */
+  int64_t max_off = -1;
+  if (stripped_ehdr->e_type != ET_REL)
+    {
+      elf_flagelf (stripped, ELF_C_SET, ELF_F_LAYOUT);
+      max_off = elf_update (stripped, ELF_C_NULL);
+    }
+
   /* Cache the stripped file's section details.  */
   struct section sections[stripped_shnum - 1];
   Elf_Scn *scn = NULL;
@@ -1697,6 +1707,11 @@ more sections in stripped file than debug file -- arguments reversed?"));
        /* Preserve the file layout of the allocated sections.  */
        if (stripped_ehdr->e_type != ET_REL && (shdr_mem.sh_flags & SHF_ALLOC))
          {
+           if (max_off > 0 && sec->shdr.sh_offset > (Elf64_Off) max_off)
+               error (EXIT_FAILURE, 0,
+                      "allocated section offset too large [%zd] %" PRIx64,
+                      elf_ndxscn (sec->scn), sec->shdr.sh_offset);
+
            shdr_mem.sh_offset = sec->shdr.sh_offset;
            placed[elf_ndxscn (sec->outscn) - 1] = true;