summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Wielaard <mark@klomp.org>2018-10-19 15:01:29 +0200
committerMark Wielaard <mark@klomp.org>2018-10-20 00:13:10 +0200
commit1e7c230b277b6eb82577a3bc4b56ca291c28964d (patch)
treec49c147eef876edee8ef5fd4592a104f2bfa286e
parent22d2d082d57a7470fadc0eae67179553f4919209 (diff)
Check sh_entsize is not zero.
There were some recent bug reports where we trusted the ELF section header to be sane and divided the sh_size by the sh_entsize to get the number of objects in the section. This would cause a divide by zero if the file was corrupt and the sh_entsize was zero. Add checks for any such code. Signed-off-by: Mark Wielaard <mark@klomp.org>
-rw-r--r--libasm/ChangeLog4
-rw-r--r--libasm/disasm_cb.c2
-rw-r--r--libdwfl/ChangeLog4
-rw-r--r--libdwfl/dwfl_module_getdwarf.c2
-rw-r--r--src/ChangeLog7
-rw-r--r--src/unstrip.c27
6 files changed, 45 insertions, 1 deletions
diff --git a/libasm/ChangeLog b/libasm/ChangeLog
index 2efd85fa..92dfd729 100644
--- a/libasm/ChangeLog
+++ b/libasm/ChangeLog
@@ -1,3 +1,7 @@
+2018-10-19 Mark Wielaard <mark@klomp.org>
+
+ * disasm_cb.c (read_symtab_exec): Check sh_entsize is not zero.
+
2018-07-04 Ross Burton <ross.burton@intel.com>
* asm_end.c: Remove error.h include.
diff --git a/libasm/disasm_cb.c b/libasm/disasm_cb.c
index cf278c71..80f8b25b 100644
--- a/libasm/disasm_cb.c
+++ b/libasm/disasm_cb.c
@@ -93,6 +93,8 @@ read_symtab_exec (DisasmCtx_t *ctx)
xndxdata = elf_getdata (elf_getscn (ctx->elf, xndxscnidx), NULL);
/* Iterate over all symbols. Add all defined symbols. */
+ if (shdr->sh_entsize == 0)
+ continue;
int nsyms = shdr->sh_size / shdr->sh_entsize;
for (int cnt = 1; cnt < nsyms; ++cnt)
{
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 2e7efd45..6c333d83 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,7 @@
+2018-10-19 Mark Wielaard <mark@klomp.org>
+
+ * dwfl_module_getdwarf.c (find_aux_sym): Check sh_entsize is not zero.
+
2018-10-14 Mark Wielaard <mark@klomp.org>
* dwfl_segment_report_module.c (read_portion): Check requested
diff --git a/libdwfl/dwfl_module_getdwarf.c b/libdwfl/dwfl_module_getdwarf.c
index af6838a6..56e61054 100644
--- a/libdwfl/dwfl_module_getdwarf.c
+++ b/libdwfl/dwfl_module_getdwarf.c
@@ -1007,6 +1007,8 @@ find_aux_sym (Dwfl_Module *mod __attribute__ ((unused)),
switch (shdr->sh_type)
{
case SHT_SYMTAB:
+ if (shdr->sh_entsize == 0)
+ return;
minisymtab = true;
*aux_symscn = scn;
*aux_strshndx = shdr->sh_link;
diff --git a/src/ChangeLog b/src/ChangeLog
index a6ab0931..0cbcf80c 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,10 @@
+2018-10-19 Mark Wielaard <mark@klomp.org>
+
+ * dwfl_module_getdwarf.c (adjust_relocs): Check sh_entsize is not
+ zero.
+ (add_new_section_symbols): Likewise.
+ (copy_elided_sections): Likewise.
+
2018-10-18 Mark Wielaard <mark@klomp.org>
* size.c (handle_ar): Only close elf if prefix was NULL.
diff --git a/src/unstrip.c b/src/unstrip.c
index 2cfd3b37..32da89d7 100644
--- a/src/unstrip.c
+++ b/src/unstrip.c
@@ -446,6 +446,9 @@ adjust_relocs (Elf_Scn *outscn, Elf_Scn *inscn, const GElf_Shdr *shdr,
switch (shdr->sh_type)
{
case SHT_REL:
+ if (shdr->sh_entsize == 0)
+ error (EXIT_FAILURE, 0, "REL section cannot have zero sh_entsize");
+
for (size_t i = 0; i < shdr->sh_size / shdr->sh_entsize; ++i)
{
GElf_Rel rel_mem;
@@ -457,6 +460,9 @@ adjust_relocs (Elf_Scn *outscn, Elf_Scn *inscn, const GElf_Shdr *shdr,
break;
case SHT_RELA:
+ if (shdr->sh_entsize == 0)
+ error (EXIT_FAILURE, 0, "RELA section cannot have zero sh_entsize");
+
for (size_t i = 0; i < shdr->sh_size / shdr->sh_entsize; ++i)
{
GElf_Rela rela_mem;
@@ -483,6 +489,10 @@ adjust_relocs (Elf_Scn *outscn, Elf_Scn *inscn, const GElf_Shdr *shdr,
case SHT_HASH:
/* We must expand the table and rejigger its contents. */
{
+ if (shdr->sh_entsize == 0)
+ error (EXIT_FAILURE, 0, "HASH section cannot have zero sh_entsize");
+ if (symshdr->sh_entsize == 0)
+ error (EXIT_FAILURE, 0, "Symbol table cannot have zero sh_entsize");
const size_t nsym = symshdr->sh_size / symshdr->sh_entsize;
const size_t onent = shdr->sh_size / shdr->sh_entsize;
assert (data->d_size == shdr->sh_size);
@@ -538,6 +548,11 @@ adjust_relocs (Elf_Scn *outscn, Elf_Scn *inscn, const GElf_Shdr *shdr,
case SHT_GNU_versym:
/* We must expand the table and move its elements around. */
{
+ if (shdr->sh_entsize == 0)
+ error (EXIT_FAILURE, 0,
+ "GNU_versym section cannot have zero sh_entsize");
+ if (symshdr->sh_entsize == 0)
+ error (EXIT_FAILURE, 0, "Symbol table cannot have zero sh_entsize");
const size_t nent = symshdr->sh_size / symshdr->sh_entsize;
const size_t onent = shdr->sh_size / shdr->sh_entsize;
assert (nent >= onent);
@@ -603,6 +618,8 @@ add_new_section_symbols (Elf_Scn *old_symscn, size_t old_shnum,
GElf_Shdr shdr_mem;
GElf_Shdr *shdr = gelf_getshdr (symscn, &shdr_mem);
ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
+ if (shdr->sh_entsize == 0)
+ error (EXIT_FAILURE, 0, "Symbol table section cannot have zero sh_entsize");
const size_t nsym = shdr->sh_size / shdr->sh_entsize;
size_t symndx_map[nsym - 1];
@@ -1671,6 +1688,9 @@ more sections in stripped file than debug file -- arguments reversed?"));
Elf_Data *shndxdata = NULL; /* XXX */
+ if (shdr_mem.sh_entsize == 0)
+ error (EXIT_FAILURE, 0,
+ "SYMTAB section cannot have zero sh_entsize");
for (size_t i = 1; i < shdr_mem.sh_size / shdr_mem.sh_entsize; ++i)
{
GElf_Sym sym_mem;
@@ -1736,11 +1756,16 @@ more sections in stripped file than debug file -- arguments reversed?"));
/* Merge the stripped file's symbol table into the unstripped one. */
const size_t stripped_nsym = (stripped_symtab == NULL ? 1
: (stripped_symtab->shdr.sh_size
- / stripped_symtab->shdr.sh_entsize));
+ / (stripped_symtab->shdr.sh_entsize == 0
+ ? 1
+ : stripped_symtab->shdr.sh_entsize)));
GElf_Shdr shdr_mem;
GElf_Shdr *shdr = gelf_getshdr (unstripped_symtab, &shdr_mem);
ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
+ if (shdr->sh_entsize == 0)
+ error (EXIT_FAILURE, 0,
+ "unstripped SYMTAB section cannot have zero sh_entsize");
const size_t unstripped_nsym = shdr->sh_size / shdr->sh_entsize;
/* First collect all the symbols from both tables. */