]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
elflint: Don't trust sh_entsize when checking hash sections.
authorMark Wielaard <mark@klomp.org>
Mon, 27 Mar 2017 22:38:52 +0000 (00:38 +0200)
committerMark Wielaard <mark@klomp.org>
Mon, 3 Apr 2017 22:18:48 +0000 (00:18 +0200)
Calculate and use the expected entsize instead of relying on the one
given by the ELF file section header. Return early if there isn't enough
data in the section to check the full hash table.

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

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

index 6031213f049dbbf5ce90924ffe57b1c84a004e1c..70744bcf70e7ca7dbf00a4e3e7caa37ccf314acd 100644 (file)
@@ -1,3 +1,10 @@
+2017-03-27  Mark Wielaard  <mark@klomp.org>
+
+       * elflint.c (check_sysv_hash): Return early if section size is
+       too small.
+       (check_sysv_hash64): Likewise.
+       (check_hash): Calculate expect_entsize to check section size.
+
 2017-03-27  Mark Wielaard  <mark@klomp.org>
 
        * elflint.c (check_symtab_shndx): Check data->d_size.
index 76fb1a0c57794b0222f0be63382913b8aacee2df..5e95ca959778a7fe0a940a9c4e00cf6570de5c4f 100644 (file)
@@ -1,5 +1,5 @@
 /* Pedantic checking of ELF files compliance with gABI/psABI spec.
-   Copyright (C) 2001-2015 Red Hat, Inc.
+   Copyright (C) 2001-2015, 2017 Red Hat, Inc.
    This file is part of elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 2001.
 
@@ -1993,11 +1993,14 @@ check_sysv_hash (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx,
   Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
   Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1];
 
-  if (shdr->sh_size < (2 + nbucket + nchain) * shdr->sh_entsize)
-    ERROR (gettext ("\
+  if (shdr->sh_size < (2 + nbucket + nchain) * sizeof (Elf32_Word))
+    {
+      ERROR (gettext ("\
 section [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"),
-          idx, section_name (ebl, idx), (long int) shdr->sh_size,
-          (long int) ((2 + nbucket + nchain) * shdr->sh_entsize));
+            idx, section_name (ebl, idx), (long int) shdr->sh_size,
+            (long int) ((2 + nbucket + nchain) * sizeof (Elf32_Word)));
+      return;
+    }
 
   size_t maxidx = nchain;
 
@@ -2044,11 +2047,14 @@ check_sysv_hash64 (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx,
   Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0];
   Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1];
 
-  if (shdr->sh_size < (2 + nbucket + nchain) * shdr->sh_entsize)
-    ERROR (gettext ("\
+  if (shdr->sh_size < (2 + nbucket + nchain) * sizeof (Elf64_Xword))
+    {
+      ERROR (gettext ("\
 section [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"),
-          idx, section_name (ebl, idx), (long int) shdr->sh_size,
-          (long int) ((2 + nbucket + nchain) * shdr->sh_entsize));
+            idx, section_name (ebl, idx), (long int) shdr->sh_size,
+            (long int) ((2 + nbucket + nchain) * sizeof (Elf64_Xword)));
+      return;
+    }
 
   size_t maxidx = nchain;
 
@@ -2288,10 +2294,12 @@ section [%2d] '%s': hash table not for dynamic symbol table\n"),
 section [%2d] '%s': invalid sh_link symbol table section index [%2d]\n"),
           idx, section_name (ebl, idx), shdr->sh_link);
 
-  if (shdr->sh_entsize != (tag == SHT_GNU_HASH
+  size_t expect_entsize = (tag == SHT_GNU_HASH
                           ? (gelf_getclass (ebl->elf) == ELFCLASS32
                              ? sizeof (Elf32_Word) : 0)
-                          : (size_t) ebl_sysvhash_entrysize (ebl)))
+                          : (size_t) ebl_sysvhash_entrysize (ebl));
+
+  if (shdr->sh_entsize != expect_entsize)
     ERROR (gettext ("\
 section [%2d] '%s': hash table entry size incorrect\n"),
           idx, section_name (ebl, idx));
@@ -2300,7 +2308,7 @@ section [%2d] '%s': hash table entry size incorrect\n"),
     ERROR (gettext ("section [%2d] '%s': not marked to be allocated\n"),
           idx, section_name (ebl, idx));
 
-  if (shdr->sh_size < (tag == SHT_GNU_HASH ? 4 : 2) * (shdr->sh_entsize ?: 4))
+  if (shdr->sh_size < (tag == SHT_GNU_HASH ? 4 : 2) * (expect_entsize ?: 4))
     {
       ERROR (gettext ("\
 section [%2d] '%s': hash table has not even room for initial administrative entries\n"),