mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-07-31 22:04:12 +08:00
PR binutils/11889
* readelf.c (get_32bit_elf_symbols): Check for a corrupt sh_entsize. (get_64bit_elf_symbols): Likewise. (process_symbol_table): Likewise. (process_section_groups): Check for corrupt headers. (process_version_sections): Check for corrupt indicies. (process_corefile_note_segment): Likewise.
This commit is contained in:
@ -1,3 +1,14 @@
|
|||||||
|
2010-08-13 Dan Rosenberg <dan.j.rosenberg@gmail.com>
|
||||||
|
|
||||||
|
PR binutils/11889
|
||||||
|
* readelf.c (get_32bit_elf_symbols): Check for a corrupt
|
||||||
|
sh_entsize.
|
||||||
|
(get_64bit_elf_symbols): Likewise.
|
||||||
|
(process_symbol_table): Likewise.
|
||||||
|
(process_section_groups): Check for corrupt headers.
|
||||||
|
(process_version_sections): Check for corrupt indicies.
|
||||||
|
(process_corefile_note_segment): Likewise.
|
||||||
|
|
||||||
2010-08-13 Nathan Sidwell <nathan@codesourcery.com>
|
2010-08-13 Nathan Sidwell <nathan@codesourcery.com>
|
||||||
|
|
||||||
* readelf.c (get_machine_flags): Detect CF ISA C and EMAC_B
|
* readelf.c (get_machine_flags): Detect CF ISA C and EMAC_B
|
||||||
|
@ -4046,15 +4046,30 @@ static Elf_Internal_Sym *
|
|||||||
get_32bit_elf_symbols (FILE * file, Elf_Internal_Shdr * section)
|
get_32bit_elf_symbols (FILE * file, Elf_Internal_Shdr * section)
|
||||||
{
|
{
|
||||||
unsigned long number;
|
unsigned long number;
|
||||||
Elf32_External_Sym * esyms;
|
Elf32_External_Sym * esyms = NULL;
|
||||||
Elf_External_Sym_Shndx * shndx;
|
Elf_External_Sym_Shndx * shndx;
|
||||||
Elf_Internal_Sym * isyms;
|
Elf_Internal_Sym * isyms = NULL;
|
||||||
Elf_Internal_Sym * psym;
|
Elf_Internal_Sym * psym;
|
||||||
unsigned int j;
|
unsigned int j;
|
||||||
|
|
||||||
|
/* Run some sanity checks first. */
|
||||||
|
if (section->sh_entsize == 0)
|
||||||
|
{
|
||||||
|
error (_("sh_entsize is zero\n"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
number = section->sh_size / section->sh_entsize;
|
||||||
|
|
||||||
|
if (number * sizeof (Elf32_External_Sym) > section->sh_size + 1)
|
||||||
|
{
|
||||||
|
error (_("Invalid sh_entsize\n"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
esyms = (Elf32_External_Sym *) get_data (NULL, file, section->sh_offset, 1,
|
esyms = (Elf32_External_Sym *) get_data (NULL, file, section->sh_offset, 1,
|
||||||
section->sh_size, _("symbols"));
|
section->sh_size, _("symbols"));
|
||||||
if (!esyms)
|
if (esyms == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
shndx = NULL;
|
shndx = NULL;
|
||||||
@ -4066,28 +4081,19 @@ get_32bit_elf_symbols (FILE * file, Elf_Internal_Shdr * section)
|
|||||||
symtab_shndx_hdr->sh_offset,
|
symtab_shndx_hdr->sh_offset,
|
||||||
1, symtab_shndx_hdr->sh_size,
|
1, symtab_shndx_hdr->sh_size,
|
||||||
_("symtab shndx"));
|
_("symtab shndx"));
|
||||||
if (!shndx)
|
if (shndx == NULL)
|
||||||
{
|
goto exit_point;
|
||||||
free (esyms);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
number = section->sh_size / section->sh_entsize;
|
|
||||||
isyms = (Elf_Internal_Sym *) cmalloc (number, sizeof (Elf_Internal_Sym));
|
isyms = (Elf_Internal_Sym *) cmalloc (number, sizeof (Elf_Internal_Sym));
|
||||||
|
|
||||||
if (isyms == NULL)
|
if (isyms == NULL)
|
||||||
{
|
{
|
||||||
error (_("Out of memory\n"));
|
error (_("Out of memory\n"));
|
||||||
if (shndx)
|
goto exit_point;
|
||||||
free (shndx);
|
|
||||||
free (esyms);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (j = 0, psym = isyms;
|
for (j = 0, psym = isyms; j < number; j++, psym++)
|
||||||
j < number;
|
|
||||||
j++, psym++)
|
|
||||||
{
|
{
|
||||||
psym->st_name = BYTE_GET (esyms[j].st_name);
|
psym->st_name = BYTE_GET (esyms[j].st_name);
|
||||||
psym->st_value = BYTE_GET (esyms[j].st_value);
|
psym->st_value = BYTE_GET (esyms[j].st_value);
|
||||||
@ -4102,8 +4108,10 @@ get_32bit_elf_symbols (FILE * file, Elf_Internal_Shdr * section)
|
|||||||
psym->st_other = BYTE_GET (esyms[j].st_other);
|
psym->st_other = BYTE_GET (esyms[j].st_other);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exit_point:
|
||||||
if (shndx)
|
if (shndx)
|
||||||
free (shndx);
|
free (shndx);
|
||||||
|
if (esyms)
|
||||||
free (esyms);
|
free (esyms);
|
||||||
|
|
||||||
return isyms;
|
return isyms;
|
||||||
@ -4119,6 +4127,21 @@ get_64bit_elf_symbols (FILE * file, Elf_Internal_Shdr * section)
|
|||||||
Elf_Internal_Sym * psym;
|
Elf_Internal_Sym * psym;
|
||||||
unsigned int j;
|
unsigned int j;
|
||||||
|
|
||||||
|
/* Run some sanity checks first. */
|
||||||
|
if (section->sh_entsize == 0)
|
||||||
|
{
|
||||||
|
error (_("sh_entsize is zero\n"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
number = section->sh_size / section->sh_entsize;
|
||||||
|
|
||||||
|
if (number * sizeof (Elf64_External_Sym) > section->sh_size + 1)
|
||||||
|
{
|
||||||
|
error (_("Invalid sh_entsize\n"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
esyms = (Elf64_External_Sym *) get_data (NULL, file, section->sh_offset, 1,
|
esyms = (Elf64_External_Sym *) get_data (NULL, file, section->sh_offset, 1,
|
||||||
section->sh_size, _("symbols"));
|
section->sh_size, _("symbols"));
|
||||||
if (!esyms)
|
if (!esyms)
|
||||||
@ -4140,7 +4163,6 @@ get_64bit_elf_symbols (FILE * file, Elf_Internal_Shdr * section)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
number = section->sh_size / section->sh_entsize;
|
|
||||||
isyms = (Elf_Internal_Sym *) cmalloc (number, sizeof (Elf_Internal_Sym));
|
isyms = (Elf_Internal_Sym *) cmalloc (number, sizeof (Elf_Internal_Sym));
|
||||||
|
|
||||||
if (isyms == NULL)
|
if (isyms == NULL)
|
||||||
@ -4965,6 +4987,12 @@ process_section_groups (FILE * file)
|
|||||||
symtab = GET_ELF_SYMBOLS (file, symtab_sec);
|
symtab = GET_ELF_SYMBOLS (file, symtab_sec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (symtab == NULL)
|
||||||
|
{
|
||||||
|
error (_("Corrupt header in group section `%s'\n"), name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
sym = symtab + section->sh_info;
|
sym = symtab + section->sh_info;
|
||||||
|
|
||||||
if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
|
if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
|
||||||
@ -6440,7 +6468,6 @@ decode_arm_unwind (struct arm_unw_aux_info *aux,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
per_index = (word >> 24) & 0x7f;
|
per_index = (word >> 24) & 0x7f;
|
||||||
if (per_index != 0 && per_index != 1 && per_index != 2)
|
if (per_index != 0 && per_index != 1 && per_index != 2)
|
||||||
{
|
{
|
||||||
@ -7773,6 +7800,10 @@ process_version_sections (FILE * file)
|
|||||||
int j;
|
int j;
|
||||||
int isum;
|
int isum;
|
||||||
|
|
||||||
|
/* Check for negative or very large indicies. */
|
||||||
|
if ((unsigned char *) edefs + idx < (unsigned char *) edefs)
|
||||||
|
break;
|
||||||
|
|
||||||
vstart = ((char *) edefs) + idx;
|
vstart = ((char *) edefs) + idx;
|
||||||
if (vstart + sizeof (*edef) > endbuf)
|
if (vstart + sizeof (*edef) > endbuf)
|
||||||
break;
|
break;
|
||||||
@ -7793,6 +7824,11 @@ process_version_sections (FILE * file)
|
|||||||
printf (_(" Index: %d Cnt: %d "),
|
printf (_(" Index: %d Cnt: %d "),
|
||||||
ent.vd_ndx, ent.vd_cnt);
|
ent.vd_ndx, ent.vd_cnt);
|
||||||
|
|
||||||
|
/* Check for overflow. */
|
||||||
|
if ((unsigned char *)(vstart + ent.vd_aux) < (unsigned char *) vstart
|
||||||
|
|| (unsigned char *)(vstart + ent.vd_aux) > (unsigned char *) endbuf)
|
||||||
|
break;
|
||||||
|
|
||||||
vstart += ent.vd_aux;
|
vstart += ent.vd_aux;
|
||||||
|
|
||||||
eaux = (Elf_External_Verdaux *) vstart;
|
eaux = (Elf_External_Verdaux *) vstart;
|
||||||
@ -7809,6 +7845,11 @@ process_version_sections (FILE * file)
|
|||||||
|
|
||||||
for (j = 1; j < ent.vd_cnt; j++)
|
for (j = 1; j < ent.vd_cnt; j++)
|
||||||
{
|
{
|
||||||
|
/* Check for overflow. */
|
||||||
|
if ((unsigned char *)(vstart + aux.vda_next) < (unsigned char *) vstart
|
||||||
|
|| (unsigned char *)(vstart + aux.vda_next) > (unsigned char *) endbuf)
|
||||||
|
break;
|
||||||
|
|
||||||
isum += aux.vda_next;
|
isum += aux.vda_next;
|
||||||
vstart += aux.vda_next;
|
vstart += aux.vda_next;
|
||||||
|
|
||||||
@ -7826,11 +7867,13 @@ process_version_sections (FILE * file)
|
|||||||
printf (_(" %#06x: Parent %d, name index: %ld\n"),
|
printf (_(" %#06x: Parent %d, name index: %ld\n"),
|
||||||
isum, j, aux.vda_name);
|
isum, j, aux.vda_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (j < ent.vd_cnt)
|
if (j < ent.vd_cnt)
|
||||||
printf (_(" Version def aux past end of section\n"));
|
printf (_(" Version def aux past end of section\n"));
|
||||||
|
|
||||||
idx += ent.vd_next;
|
idx += ent.vd_next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cnt < section->sh_info)
|
if (cnt < section->sh_info)
|
||||||
printf (_(" Version definition past end of section\n"));
|
printf (_(" Version definition past end of section\n"));
|
||||||
|
|
||||||
@ -7874,6 +7917,9 @@ process_version_sections (FILE * file)
|
|||||||
int isum;
|
int isum;
|
||||||
char * vstart;
|
char * vstart;
|
||||||
|
|
||||||
|
if ((unsigned char *) eneed + idx < (unsigned char *) eneed)
|
||||||
|
break;
|
||||||
|
|
||||||
vstart = ((char *) eneed) + idx;
|
vstart = ((char *) eneed) + idx;
|
||||||
if (vstart + sizeof (*entry) > endbuf)
|
if (vstart + sizeof (*entry) > endbuf)
|
||||||
break;
|
break;
|
||||||
@ -7895,6 +7941,11 @@ process_version_sections (FILE * file)
|
|||||||
|
|
||||||
printf (_(" Cnt: %d\n"), ent.vn_cnt);
|
printf (_(" Cnt: %d\n"), ent.vn_cnt);
|
||||||
|
|
||||||
|
/* Check for overflow. */
|
||||||
|
if ((unsigned char *)(vstart + ent.vn_aux) < (unsigned char *) vstart
|
||||||
|
|| (unsigned char *)(vstart + ent.vn_aux) > (unsigned char *) endbuf)
|
||||||
|
break;
|
||||||
|
|
||||||
vstart += ent.vn_aux;
|
vstart += ent.vn_aux;
|
||||||
|
|
||||||
for (j = 0, isum = idx + ent.vn_aux; j < ent.vn_cnt; ++j)
|
for (j = 0, isum = idx + ent.vn_aux; j < ent.vn_cnt; ++j)
|
||||||
@ -7922,6 +7973,11 @@ process_version_sections (FILE * file)
|
|||||||
printf (_(" Flags: %s Version: %d\n"),
|
printf (_(" Flags: %s Version: %d\n"),
|
||||||
get_ver_flags (aux.vna_flags), aux.vna_other);
|
get_ver_flags (aux.vna_flags), aux.vna_other);
|
||||||
|
|
||||||
|
/* Check for overflow. */
|
||||||
|
if ((unsigned char *)(vstart + aux.vna_next) < (unsigned char *) vstart
|
||||||
|
|| (unsigned char *)(vstart + aux.vna_next) > (unsigned char *) endbuf)
|
||||||
|
break;
|
||||||
|
|
||||||
isum += aux.vna_next;
|
isum += aux.vna_next;
|
||||||
vstart += aux.vna_next;
|
vstart += aux.vna_next;
|
||||||
}
|
}
|
||||||
@ -7961,6 +8017,8 @@ process_version_sections (FILE * file)
|
|||||||
found = 1;
|
found = 1;
|
||||||
|
|
||||||
symbols = GET_ELF_SYMBOLS (file, link_section);
|
symbols = GET_ELF_SYMBOLS (file, link_section);
|
||||||
|
if (symbols == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
string_sec = section_headers + link_section->sh_link;
|
string_sec = section_headers + link_section->sh_link;
|
||||||
|
|
||||||
@ -8022,6 +8080,16 @@ process_version_sections (FILE * file)
|
|||||||
nn = printf ("%4x%c", data[cnt + j] & VERSYM_VERSION,
|
nn = printf ("%4x%c", data[cnt + j] & VERSYM_VERSION,
|
||||||
data[cnt + j] & VERSYM_HIDDEN ? 'h' : ' ');
|
data[cnt + j] & VERSYM_HIDDEN ? 'h' : ' ');
|
||||||
|
|
||||||
|
/* If this index value is greater than the size of the symbols
|
||||||
|
array, break to avoid an out-of-bounds read, */
|
||||||
|
if ((unsigned long)(cnt + j) >=
|
||||||
|
((unsigned long)link_section->sh_size /
|
||||||
|
(unsigned long)link_section->sh_entsize))
|
||||||
|
{
|
||||||
|
warn (_("invalid index into symbol array\n"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
check_def = 1;
|
check_def = 1;
|
||||||
check_need = 1;
|
check_need = 1;
|
||||||
if (symbols[cnt + j].st_shndx >= elf_header.e_shnum
|
if (symbols[cnt + j].st_shndx >= elf_header.e_shnum
|
||||||
@ -8729,9 +8797,17 @@ process_symbol_table (FILE * file)
|
|||||||
&& section->sh_type == SHT_SYMTAB))
|
&& section->sh_type == SHT_SYMTAB))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (section->sh_entsize == 0)
|
||||||
|
{
|
||||||
|
printf (_("\nSymbol table '%s' has a sh_entsize of zero!\n"),
|
||||||
|
SECTION_NAME (section));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
printf (_("\nSymbol table '%s' contains %lu entries:\n"),
|
printf (_("\nSymbol table '%s' contains %lu entries:\n"),
|
||||||
SECTION_NAME (section),
|
SECTION_NAME (section),
|
||||||
(unsigned long) (section->sh_size / section->sh_entsize));
|
(unsigned long) (section->sh_size / section->sh_entsize));
|
||||||
|
|
||||||
if (is_32bit_elf)
|
if (is_32bit_elf)
|
||||||
printf (_(" Num: Value Size Type Bind Vis Ndx Name\n"));
|
printf (_(" Num: Value Size Type Bind Vis Ndx Name\n"));
|
||||||
else
|
else
|
||||||
@ -11825,7 +11901,7 @@ process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length)
|
|||||||
|
|
||||||
pnotes = (Elf_External_Note *) get_data (NULL, file, offset, 1, length,
|
pnotes = (Elf_External_Note *) get_data (NULL, file, offset, 1, length,
|
||||||
_("notes"));
|
_("notes"));
|
||||||
if (!pnotes)
|
if (pnotes == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
external = pnotes;
|
external = pnotes;
|
||||||
@ -11849,7 +11925,8 @@ process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length)
|
|||||||
|
|
||||||
next = (Elf_External_Note *) (inote.descdata + align_power (inote.descsz, 2));
|
next = (Elf_External_Note *) (inote.descdata + align_power (inote.descsz, 2));
|
||||||
|
|
||||||
if (((char *) next) > (((char *) pnotes) + length))
|
if ( ((char *) next > ((char *) pnotes) + length)
|
||||||
|
|| ((char *) next < (char *) pnotes))
|
||||||
{
|
{
|
||||||
warn (_("corrupt note found at offset %lx into core notes\n"),
|
warn (_("corrupt note found at offset %lx into core notes\n"),
|
||||||
(unsigned long) ((char *) external - (char *) pnotes));
|
(unsigned long) ((char *) external - (char *) pnotes));
|
||||||
@ -11860,6 +11937,17 @@ process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length)
|
|||||||
|
|
||||||
external = next;
|
external = next;
|
||||||
|
|
||||||
|
/* Prevent out-of-bounds indexing. */
|
||||||
|
if (inote.namedata + inote.namesz >= (char *) pnotes + length
|
||||||
|
|| inote.namedata + inote.namesz < inote.namedata)
|
||||||
|
{
|
||||||
|
warn (_("corrupt note found at offset %lx into core notes\n"),
|
||||||
|
(unsigned long) ((char *) external - (char *) pnotes));
|
||||||
|
warn (_(" type: %lx, namesize: %08lx, descsize: %08lx\n"),
|
||||||
|
inote.type, inote.namesz, inote.descsz);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Verify that name is null terminated. It appears that at least
|
/* Verify that name is null terminated. It appears that at least
|
||||||
one version of Linux (RedHat 6.0) generates corefiles that don't
|
one version of Linux (RedHat 6.0) generates corefiles that don't
|
||||||
comply with the ELF spec by failing to include the null byte in
|
comply with the ELF spec by failing to include the null byte in
|
||||||
|
Reference in New Issue
Block a user