readelf: memory leaks in process_dynamic_section
This fixes some code that assumed only one PT_LOAD would contain DT_SYMTAB. Which is normally the case, but fuzzers thoroughly mess with object files. * readelf.c (get_num_dynamic_syms): Check for nbuckets and nchains non-zero. (process_dynamic_section): Call get_num_dynamic_syms once rather than in segment loop. Break out of segment loop on a successful load of dynamic symbols. Formatting. (process_object): Return error status from process_dynamic_section.
This commit is contained in:
parent
5e5bbc7e79
commit
2482f30615
@ -1,3 +1,12 @@
|
|||||||
|
2020-04-24 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
|
* readelf.c (get_num_dynamic_syms): Check for nbuckets and nchains
|
||||||
|
non-zero.
|
||||||
|
(process_dynamic_section): Call get_num_dynamic_syms once rather
|
||||||
|
than in segment loop. Break out of segment loop on a successful
|
||||||
|
load of dynamic symbols. Formatting.
|
||||||
|
(process_object): Return error status from process_dynamic_section.
|
||||||
|
|
||||||
2020-04-23 Anton Kolesov <anton.kolesov@synopsys.com>
|
2020-04-23 Anton Kolesov <anton.kolesov@synopsys.com>
|
||||||
|
|
||||||
* elf-bfd.h (elfcore_write_arc_v2): Add prototype.
|
* elf-bfd.h (elfcore_write_arc_v2): Add prototype.
|
||||||
|
@ -9993,14 +9993,16 @@ get_num_dynamic_syms (Filedata * filedata)
|
|||||||
filedata->nbuckets = byte_get (nb, hash_ent_size);
|
filedata->nbuckets = byte_get (nb, hash_ent_size);
|
||||||
filedata->nchains = byte_get (nc, hash_ent_size);
|
filedata->nchains = byte_get (nc, hash_ent_size);
|
||||||
|
|
||||||
filedata->buckets = get_dynamic_data (filedata, filedata->nbuckets,
|
if (filedata->nbuckets != 0 && filedata->nchains != 0)
|
||||||
hash_ent_size);
|
{
|
||||||
filedata->chains = get_dynamic_data (filedata, filedata->nchains,
|
filedata->buckets = get_dynamic_data (filedata, filedata->nbuckets,
|
||||||
hash_ent_size);
|
hash_ent_size);
|
||||||
|
filedata->chains = get_dynamic_data (filedata, filedata->nchains,
|
||||||
if (filedata->buckets != NULL && filedata->chains != NULL)
|
hash_ent_size);
|
||||||
num_of_syms = filedata->nchains;
|
|
||||||
|
|
||||||
|
if (filedata->buckets != NULL && filedata->chains != NULL)
|
||||||
|
num_of_syms = filedata->nchains;
|
||||||
|
}
|
||||||
no_hash:
|
no_hash:
|
||||||
if (num_of_syms == 0)
|
if (num_of_syms == 0)
|
||||||
{
|
{
|
||||||
@ -10243,6 +10245,8 @@ process_dynamic_section (Filedata * filedata)
|
|||||||
/* Find the appropriate symbol table. */
|
/* Find the appropriate symbol table. */
|
||||||
if (filedata->dynamic_symbols == NULL || do_histogram)
|
if (filedata->dynamic_symbols == NULL || do_histogram)
|
||||||
{
|
{
|
||||||
|
unsigned long num_of_syms;
|
||||||
|
|
||||||
for (entry = filedata->dynamic_section;
|
for (entry = filedata->dynamic_section;
|
||||||
entry < filedata->dynamic_section + filedata->dynamic_nent;
|
entry < filedata->dynamic_section + filedata->dynamic_nent;
|
||||||
++entry)
|
++entry)
|
||||||
@ -10262,64 +10266,65 @@ process_dynamic_section (Filedata * filedata)
|
|||||||
filedata->dynamic_info_DT_GNU_HASH = entry->d_un.d_val;
|
filedata->dynamic_info_DT_GNU_HASH = entry->d_un.d_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filedata->dynamic_info[DT_SYMTAB]
|
num_of_syms = get_num_dynamic_syms (filedata);
|
||||||
|
|
||||||
|
if (num_of_syms != 0
|
||||||
|
&& filedata->dynamic_symbols == NULL
|
||||||
|
&& filedata->dynamic_info[DT_SYMTAB]
|
||||||
&& filedata->dynamic_info[DT_SYMENT])
|
&& filedata->dynamic_info[DT_SYMENT])
|
||||||
{
|
{
|
||||||
Elf_Internal_Phdr *seg;
|
Elf_Internal_Phdr *seg;
|
||||||
bfd_vma vma = filedata->dynamic_info[DT_SYMTAB];
|
bfd_vma vma = filedata->dynamic_info[DT_SYMTAB];
|
||||||
|
|
||||||
if (! get_program_headers (filedata))
|
if (! get_program_headers (filedata))
|
||||||
{
|
{
|
||||||
error (_("Cannot interpret virtual addresses without program headers.\n"));
|
error (_("Cannot interpret virtual addresses "
|
||||||
return FALSE;
|
"without program headers.\n"));
|
||||||
}
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
for (seg = filedata->program_headers;
|
for (seg = filedata->program_headers;
|
||||||
seg < filedata->program_headers + filedata->file_header.e_phnum;
|
seg < filedata->program_headers + filedata->file_header.e_phnum;
|
||||||
++seg)
|
++seg)
|
||||||
{
|
{
|
||||||
unsigned long num_of_syms;
|
if (seg->p_type != PT_LOAD)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (seg->p_type != PT_LOAD)
|
if (seg->p_offset + seg->p_filesz > filedata->file_size)
|
||||||
continue;
|
{
|
||||||
|
/* See PR 21379 for a reproducer. */
|
||||||
|
error (_("Invalid PT_LOAD entry\n"));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if ((seg->p_offset + seg->p_filesz)
|
if (vma >= (seg->p_vaddr & -seg->p_align)
|
||||||
> filedata->file_size)
|
&& vma < seg->p_vaddr + seg->p_filesz)
|
||||||
{
|
{
|
||||||
/* See PR 21379 for a reproducer. */
|
/* Since we do not know how big the symbol table is,
|
||||||
error (_("Invalid PT_LOAD entry\n"));
|
we default to reading in up to the end of PT_LOAD
|
||||||
return FALSE;
|
segment and processing that. This is overkill, I
|
||||||
}
|
know, but it should work. */
|
||||||
|
Elf_Internal_Shdr section;
|
||||||
if (vma >= (seg->p_vaddr & -seg->p_align)
|
section.sh_offset = (vma - seg->p_vaddr
|
||||||
&& vma <= seg->p_vaddr + seg->p_filesz
|
+ seg->p_offset);
|
||||||
&& (num_of_syms = get_num_dynamic_syms (filedata)) != 0
|
section.sh_size = (num_of_syms
|
||||||
&& filedata->dynamic_symbols == NULL)
|
* filedata->dynamic_info[DT_SYMENT]);
|
||||||
{
|
section.sh_entsize = filedata->dynamic_info[DT_SYMENT];
|
||||||
/* Since we do not know how big the symbol table is,
|
section.sh_name = filedata->string_table_length;
|
||||||
we default to reading in up to the end of PT_LOAD
|
filedata->dynamic_symbols
|
||||||
segment and processing that. This is overkill, I
|
= GET_ELF_SYMBOLS (filedata, §ion,
|
||||||
know, but it should work. */
|
&filedata->num_dynamic_syms);
|
||||||
Elf_Internal_Shdr section;
|
if (filedata->dynamic_symbols == NULL
|
||||||
section.sh_offset = (vma - seg->p_vaddr
|
|| filedata->num_dynamic_syms != num_of_syms)
|
||||||
+ seg->p_offset);
|
{
|
||||||
section.sh_size = (num_of_syms
|
error (_("Corrupt DT_SYMTAB dynamic entry\n"));
|
||||||
* filedata->dynamic_info[DT_SYMENT]);
|
return FALSE;
|
||||||
section.sh_entsize = filedata->dynamic_info[DT_SYMENT];
|
}
|
||||||
section.sh_name = filedata->string_table_length;
|
break;
|
||||||
filedata->dynamic_symbols
|
}
|
||||||
= GET_ELF_SYMBOLS (filedata, §ion,
|
}
|
||||||
&filedata->num_dynamic_syms);
|
}
|
||||||
if (filedata->dynamic_symbols == NULL
|
}
|
||||||
|| filedata->num_dynamic_syms != num_of_syms)
|
|
||||||
{
|
|
||||||
error (_("Corrupt DT_SYMTAB dynamic entry\n"));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Similarly find a string table. */
|
/* Similarly find a string table. */
|
||||||
if (filedata->dynamic_strings == NULL)
|
if (filedata->dynamic_strings == NULL)
|
||||||
@ -10403,14 +10408,17 @@ process_dynamic_section (Filedata * filedata)
|
|||||||
filedata->dynamic_syminfo = (Elf_Internal_Syminfo *) malloc (syminsz);
|
filedata->dynamic_syminfo = (Elf_Internal_Syminfo *) malloc (syminsz);
|
||||||
if (filedata->dynamic_syminfo == NULL)
|
if (filedata->dynamic_syminfo == NULL)
|
||||||
{
|
{
|
||||||
error (_("Out of memory allocating %lu byte for dynamic symbol info\n"),
|
error (_("Out of memory allocating %lu bytes "
|
||||||
|
"for dynamic symbol info\n"),
|
||||||
(unsigned long) syminsz);
|
(unsigned long) syminsz);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
filedata->dynamic_syminfo_nent = syminsz / sizeof (Elf_External_Syminfo);
|
filedata->dynamic_syminfo_nent
|
||||||
|
= syminsz / sizeof (Elf_External_Syminfo);
|
||||||
for (syminfo = filedata->dynamic_syminfo, extsym = extsyminfo;
|
for (syminfo = filedata->dynamic_syminfo, extsym = extsyminfo;
|
||||||
syminfo < filedata->dynamic_syminfo + filedata->dynamic_syminfo_nent;
|
syminfo < (filedata->dynamic_syminfo
|
||||||
|
+ filedata->dynamic_syminfo_nent);
|
||||||
++syminfo, ++extsym)
|
++syminfo, ++extsym)
|
||||||
{
|
{
|
||||||
syminfo->si_boundto = BYTE_GET (extsym->si_boundto);
|
syminfo->si_boundto = BYTE_GET (extsym->si_boundto);
|
||||||
@ -20120,7 +20128,7 @@ process_object (Filedata * filedata)
|
|||||||
{
|
{
|
||||||
bfd_boolean have_separate_files;
|
bfd_boolean have_separate_files;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
bfd_boolean res = TRUE;
|
bfd_boolean res;
|
||||||
|
|
||||||
if (! get_file_header (filedata))
|
if (! get_file_header (filedata))
|
||||||
{
|
{
|
||||||
@ -20176,10 +20184,9 @@ process_object (Filedata * filedata)
|
|||||||
/* Without loaded section groups we cannot process unwind. */
|
/* Without loaded section groups we cannot process unwind. */
|
||||||
do_unwind = FALSE;
|
do_unwind = FALSE;
|
||||||
|
|
||||||
if (process_program_headers (filedata))
|
res = process_program_headers (filedata);
|
||||||
process_dynamic_section (filedata);
|
if (res)
|
||||||
else
|
res = process_dynamic_section (filedata);
|
||||||
res = FALSE;
|
|
||||||
|
|
||||||
if (! process_relocs (filedata))
|
if (! process_relocs (filedata))
|
||||||
res = FALSE;
|
res = FALSE;
|
||||||
|
Loading…
Reference in New Issue
Block a user