elf_update might crash for 65280+ sections when section zero headers
aren't loaded. Make sure section zero is loaded before trying to write
to it.

Add testcase to tests/test-manyfuncs.c but use ELF_C_READ_MMAP_PRIVATE
to workaround https://sourceware.org/bugzilla/show_bug.cgi?id=33968

        * libelf/elf32_updatenull.c (updatenull_wrlock): Call
        getshdr_wrlock to load shdr.
        * tests/test-manyfuncs.c (check_elf): Use elf_begin with
        ELF_C_READ_MMAP_PRIVATE if use_mmap. Call elf_update early.

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

Signed-off-by: Mark Wielaard <[email protected]>
---
 libelf/elf32_updatenull.c |  4 ++++
 tests/test-manyfuncs.c    | 15 ++++++++++++++-
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/libelf/elf32_updatenull.c b/libelf/elf32_updatenull.c
index 74c27fdaa7b5..57239ee4ac90 100644
--- a/libelf/elf32_updatenull.c
+++ b/libelf/elf32_updatenull.c
@@ -184,6 +184,10 @@ __elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int 
*change_bop, size_t shnum)
             of the zeroth section.  */
          Elf_Scn *scn0 = &elf->state.ELFW(elf,LIBELFBITS).scns.data[0];
 
+         /* Make sure section zero header is actually loaded.  */
+         if (scn0->shdr.ELFW(e,LIBELFBITS) == NULL)
+           (void) __elfw2(LIBELFBITS,getshdr_wrlock) (scn0);
+
          update_if_changed (scn0->shdr.ELFW(e,LIBELFBITS)->sh_size,
                             shnum, scn0->shdr_flags);
        }
diff --git a/tests/test-manyfuncs.c b/tests/test-manyfuncs.c
index 725690203ff1..3129682d59e4 100644
--- a/tests/test-manyfuncs.c
+++ b/tests/test-manyfuncs.c
@@ -52,13 +52,26 @@ check_elf (const char *fname, bool use_mmap)
       exit (1);
     }
 
-  Elf *elf = elf_begin (fd, use_mmap ? ELF_C_READ_MMAP : ELF_C_READ, NULL);
+  Elf *elf = elf_begin (fd, use_mmap ? ELF_C_READ_MMAP_PRIVATE : ELF_C_READ,
+                       NULL);
   if (elf == NULL)
     {
       printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
       exit (1);
     }
 
+  /* Check if we can update the elf layout without having read anything.
+     This used to crash with 65280+ sections.
+     https://sourceware.org/bugzilla/show_bug.cgi?id=33967
+     Still crashes for read-only mmap.
+     https://sourceware.org/bugzilla/show_bug.cgi?id=33968
+  */
+  if (elf_update (elf, ELF_C_NULL) < 0)
+    {
+      printf ("failure in elf_update: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
   /* How many sections are there?  */
   size_t shnum;
   if (elf_getshdrnum (elf, &shnum) < 0)
-- 
2.53.0

Reply via email to