Avoid allocating over-large buffers when parsing corrupt binaries.
PR binutils/17512 * coffgen.c (_bfd_coff_get_external_symbols): Do not try to load a symbol table bigger than the file. * elf.c (bfd_elf_get_str_section): Do not try to load a string table bigger than the file. * readelf.c (process_program_headers): Avoid memory exhaustion due to corrupt values in a dynamis segment header. (get_32bit_elf_symbols): Do not attempt to read an over-large section. (get_64bit_elf_symbols): Likewise.
This commit is contained in:
parent
fe06005387
commit
f54498b457
5 changed files with 55 additions and 4 deletions
|
@ -1,3 +1,11 @@
|
||||||
|
2014-10-31 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
|
PR binutils/17512
|
||||||
|
* coffgen.c (_bfd_coff_get_external_symbols): Do not try to load a
|
||||||
|
symbol table bigger than the file.
|
||||||
|
* elf.c (bfd_elf_get_str_section): Do not try to load a string
|
||||||
|
table bigger than the file.
|
||||||
|
|
||||||
2014-10-30 Nick Clifton <nickc@redhat.com>
|
2014-10-30 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
PR binutils/17512
|
PR binutils/17512
|
||||||
|
|
|
@ -1616,6 +1616,11 @@ _bfd_coff_get_external_symbols (bfd *abfd)
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
/* PR binutils/17512: Do not even try to load
|
||||||
|
a symbol table bigger than the entire file... */
|
||||||
|
if (size >= (bfd_size_type) bfd_get_size (abfd))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
syms = bfd_malloc (size);
|
syms = bfd_malloc (size);
|
||||||
if (syms == NULL)
|
if (syms == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
|
@ -294,6 +294,11 @@ bfd_elf_get_str_section (bfd *abfd, unsigned int shindex)
|
||||||
offset = i_shdrp[shindex]->sh_offset;
|
offset = i_shdrp[shindex]->sh_offset;
|
||||||
shstrtabsize = i_shdrp[shindex]->sh_size;
|
shstrtabsize = i_shdrp[shindex]->sh_size;
|
||||||
|
|
||||||
|
/* PR binutils/17512: Do not even try to load
|
||||||
|
a string table bigger than the entire file... */
|
||||||
|
if (shstrtabsize >= (bfd_size_type) bfd_get_size (abfd))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
/* Allocate and clear an extra byte at the end, to prevent crashes
|
/* Allocate and clear an extra byte at the end, to prevent crashes
|
||||||
in case the string table is not terminated. */
|
in case the string table is not terminated. */
|
||||||
if (shstrtabsize + 1 <= 1
|
if (shstrtabsize + 1 <= 1
|
||||||
|
|
|
@ -1,3 +1,12 @@
|
||||||
|
2014-10-31 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
|
PR binutils/17512
|
||||||
|
* readelf.c (process_program_headers): Avoid memory exhaustion due
|
||||||
|
to corrupt values in a dynamis segment header.
|
||||||
|
(get_32bit_elf_symbols): Do not attempt to read an over-large
|
||||||
|
section.
|
||||||
|
(get_64bit_elf_symbols): Likewise.
|
||||||
|
|
||||||
2014-10-31 Nick Clifton <nickc@redhat.com>
|
2014-10-31 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
* strings.c: Add new command line option --data to only scan the
|
* strings.c: Add new command line option --data to only scan the
|
||||||
|
|
|
@ -167,6 +167,7 @@
|
||||||
char * program_name = "readelf";
|
char * program_name = "readelf";
|
||||||
static long archive_file_offset;
|
static long archive_file_offset;
|
||||||
static unsigned long archive_file_size;
|
static unsigned long archive_file_size;
|
||||||
|
static bfd_size_type current_file_size;
|
||||||
static unsigned long dynamic_addr;
|
static unsigned long dynamic_addr;
|
||||||
static bfd_size_type dynamic_size;
|
static bfd_size_type dynamic_size;
|
||||||
static unsigned int dynamic_nent;
|
static unsigned int dynamic_nent;
|
||||||
|
@ -4341,6 +4342,9 @@ process_program_headers (FILE * file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (do_segments)
|
||||||
|
putc ('\n', stdout);
|
||||||
|
|
||||||
switch (segment->p_type)
|
switch (segment->p_type)
|
||||||
{
|
{
|
||||||
case PT_DYNAMIC:
|
case PT_DYNAMIC:
|
||||||
|
@ -4351,6 +4355,12 @@ process_program_headers (FILE * file)
|
||||||
section in the DYNAMIC segment. */
|
section in the DYNAMIC segment. */
|
||||||
dynamic_addr = segment->p_offset;
|
dynamic_addr = segment->p_offset;
|
||||||
dynamic_size = segment->p_filesz;
|
dynamic_size = segment->p_filesz;
|
||||||
|
/* PR binutils/17512: Avoid corrupt dynamic section info in the segment. */
|
||||||
|
if (dynamic_addr + dynamic_size >= current_file_size)
|
||||||
|
{
|
||||||
|
error (_("the dynamic segment offset + size exceeds the size of the file\n"));
|
||||||
|
dynamic_addr = dynamic_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Try to locate the .dynamic section. If there is
|
/* Try to locate the .dynamic section. If there is
|
||||||
a section header table, we can easily locate it. */
|
a section header table, we can easily locate it. */
|
||||||
|
@ -4404,14 +4414,11 @@ process_program_headers (FILE * file)
|
||||||
error (_("Unable to read program interpreter name\n"));
|
error (_("Unable to read program interpreter name\n"));
|
||||||
|
|
||||||
if (do_segments)
|
if (do_segments)
|
||||||
printf (_("\n [Requesting program interpreter: %s]"),
|
printf (_(" [Requesting program interpreter: %s]\n"),
|
||||||
program_interpreter);
|
program_interpreter);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (do_segments)
|
|
||||||
putc ('\n', stdout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (do_segments && section_headers != NULL && string_table != NULL)
|
if (do_segments && section_headers != NULL && string_table != NULL)
|
||||||
|
@ -4580,6 +4587,13 @@ get_32bit_elf_symbols (FILE * file,
|
||||||
goto exit_point;
|
goto exit_point;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (section->sh_size > current_file_size)
|
||||||
|
{
|
||||||
|
error (_("Section %s has an invalid sh_size of 0x%lx\n"),
|
||||||
|
SECTION_NAME (section), section->sh_size);
|
||||||
|
goto exit_point;
|
||||||
|
}
|
||||||
|
|
||||||
number = section->sh_size / section->sh_entsize;
|
number = section->sh_size / section->sh_entsize;
|
||||||
|
|
||||||
if (number * sizeof (Elf32_External_Sym) > section->sh_size + 1)
|
if (number * sizeof (Elf32_External_Sym) > section->sh_size + 1)
|
||||||
|
@ -4660,6 +4674,13 @@ get_64bit_elf_symbols (FILE * file,
|
||||||
goto exit_point;
|
goto exit_point;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (section->sh_size > current_file_size)
|
||||||
|
{
|
||||||
|
error (_("Section %s has an invalid sh_size of 0x%lx\n"),
|
||||||
|
SECTION_NAME (section), section->sh_size);
|
||||||
|
goto exit_point;
|
||||||
|
}
|
||||||
|
|
||||||
number = section->sh_size / section->sh_entsize;
|
number = section->sh_size / section->sh_entsize;
|
||||||
|
|
||||||
if (number * sizeof (Elf64_External_Sym) > section->sh_size + 1)
|
if (number * sizeof (Elf64_External_Sym) > section->sh_size + 1)
|
||||||
|
@ -14886,6 +14907,8 @@ process_file (char * file_name)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
current_file_size = (bfd_size_type) statbuf.st_size;
|
||||||
|
|
||||||
if (memcmp (armag, ARMAG, SARMAG) == 0)
|
if (memcmp (armag, ARMAG, SARMAG) == 0)
|
||||||
ret = process_archive (file_name, file, FALSE);
|
ret = process_archive (file_name, file, FALSE);
|
||||||
else if (memcmp (armag, ARMAGT, SARMAG) == 0)
|
else if (memcmp (armag, ARMAGT, SARMAG) == 0)
|
||||||
|
@ -14903,6 +14926,7 @@ process_file (char * file_name)
|
||||||
|
|
||||||
fclose (file);
|
fclose (file);
|
||||||
|
|
||||||
|
current_file_size = 0;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue