mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-08-06 14:49:38 +08:00
Fix address violation problems when parsing corrupt ELF binaries.
PR 21916 * elf-attrs.c (_bfd_elf_parse_attributes): Complain about very small section lengths. * elf.c (_bfd_elf_setup_sections): Skip empty entries in the group table. (elfcore_grok_freebsd_prstatus): Add checks to make sure that there is enough data present in the note.
This commit is contained in:
@ -1,3 +1,13 @@
|
|||||||
|
2017-08-08 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
|
PR 21916
|
||||||
|
* elf-attrs.c (_bfd_elf_parse_attributes): Complain about very
|
||||||
|
small section lengths.
|
||||||
|
* elf.c (_bfd_elf_setup_sections): Skip empty entries in the group
|
||||||
|
table.
|
||||||
|
(elfcore_grok_freebsd_prstatus): Add checks to make sure that
|
||||||
|
there is enough data present in the note.
|
||||||
|
|
||||||
2017-08-08 Alan Modra <amodra@gmail.com>
|
2017-08-08 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
PR 21017
|
PR 21017
|
||||||
|
@ -468,6 +468,12 @@ _bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr)
|
|||||||
if (section_len > len)
|
if (section_len > len)
|
||||||
section_len = len;
|
section_len = len;
|
||||||
len -= section_len;
|
len -= section_len;
|
||||||
|
if (section_len <= 4)
|
||||||
|
{
|
||||||
|
_bfd_error_handler (_("%B: error: attribute section length too small: %ld"),
|
||||||
|
abfd, section_len);
|
||||||
|
break;
|
||||||
|
}
|
||||||
section_len -= 4;
|
section_len -= 4;
|
||||||
namelen = strnlen ((char *) p, section_len) + 1;
|
namelen = strnlen ((char *) p, section_len) + 1;
|
||||||
if (namelen == 0 || namelen >= section_len)
|
if (namelen == 0 || namelen >= section_len)
|
||||||
|
111
bfd/elf.c
111
bfd/elf.c
@ -896,32 +896,39 @@ _bfd_elf_setup_sections (bfd *abfd)
|
|||||||
n_elt = shdr->sh_size / 4;
|
n_elt = shdr->sh_size / 4;
|
||||||
|
|
||||||
while (--n_elt != 0)
|
while (--n_elt != 0)
|
||||||
if ((++idx)->shdr->bfd_section)
|
{
|
||||||
elf_sec_group (idx->shdr->bfd_section) = shdr->bfd_section;
|
++ idx;
|
||||||
else if (idx->shdr->sh_type == SHT_RELA
|
|
||||||
|| idx->shdr->sh_type == SHT_REL)
|
if (idx->shdr == NULL)
|
||||||
/* We won't include relocation sections in section groups in
|
continue;
|
||||||
output object files. We adjust the group section size here
|
else if (idx->shdr->bfd_section)
|
||||||
so that relocatable link will work correctly when
|
elf_sec_group (idx->shdr->bfd_section) = shdr->bfd_section;
|
||||||
relocation sections are in section group in input object
|
else if (idx->shdr->sh_type == SHT_RELA
|
||||||
files. */
|
|| idx->shdr->sh_type == SHT_REL)
|
||||||
shdr->bfd_section->size -= 4;
|
/* We won't include relocation sections in section groups in
|
||||||
else
|
output object files. We adjust the group section size here
|
||||||
{
|
so that relocatable link will work correctly when
|
||||||
/* There are some unknown sections in the group. */
|
relocation sections are in section group in input object
|
||||||
_bfd_error_handler
|
files. */
|
||||||
/* xgettext:c-format */
|
shdr->bfd_section->size -= 4;
|
||||||
(_("%B: unknown type [%#x] section `%s' in group [%A]"),
|
else
|
||||||
abfd,
|
{
|
||||||
idx->shdr->sh_type,
|
/* There are some unknown sections in the group. */
|
||||||
bfd_elf_string_from_elf_section (abfd,
|
_bfd_error_handler
|
||||||
(elf_elfheader (abfd)
|
/* xgettext:c-format */
|
||||||
->e_shstrndx),
|
(_("%B: unknown type [%#x] section `%s' in group [%A]"),
|
||||||
idx->shdr->sh_name),
|
abfd,
|
||||||
shdr->bfd_section);
|
idx->shdr->sh_type,
|
||||||
result = FALSE;
|
bfd_elf_string_from_elf_section (abfd,
|
||||||
}
|
(elf_elfheader (abfd)
|
||||||
|
->e_shstrndx),
|
||||||
|
idx->shdr->sh_name),
|
||||||
|
shdr->bfd_section);
|
||||||
|
result = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8954,7 +8961,7 @@ elfcore_maybe_make_sect (bfd *abfd, char *name, asection *sect)
|
|||||||
such a section already exists.
|
such a section already exists.
|
||||||
- For the multi-threaded case, a section named "NAME/PID", where
|
- For the multi-threaded case, a section named "NAME/PID", where
|
||||||
PID is elfcore_make_pid (abfd).
|
PID is elfcore_make_pid (abfd).
|
||||||
Both pseudosections have identical contents. */
|
Both pseudosections have identical contents. */
|
||||||
bfd_boolean
|
bfd_boolean
|
||||||
_bfd_elfcore_make_pseudosection (bfd *abfd,
|
_bfd_elfcore_make_pseudosection (bfd *abfd,
|
||||||
char *name,
|
char *name,
|
||||||
@ -9883,58 +9890,68 @@ elfcore_grok_freebsd_prstatus (bfd *abfd, Elf_Internal_Note *note)
|
|||||||
{
|
{
|
||||||
size_t offset;
|
size_t offset;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
size_t min_size;
|
||||||
|
|
||||||
/* Check for version 1 in pr_version. */
|
/* Compute offset of pr_getregsz, skipping over pr_statussz.
|
||||||
if (bfd_h_get_32 (abfd, (bfd_byte *) note->descdata) != 1)
|
Also compute minimum size of this note. */
|
||||||
return FALSE;
|
|
||||||
offset = 4;
|
|
||||||
|
|
||||||
/* Skip over pr_statussz. */
|
|
||||||
switch (elf_elfheader (abfd)->e_ident[EI_CLASS])
|
switch (elf_elfheader (abfd)->e_ident[EI_CLASS])
|
||||||
{
|
{
|
||||||
case ELFCLASS32:
|
case ELFCLASS32:
|
||||||
offset += 4;
|
offset = 4 + 4;
|
||||||
|
min_size = offset + (4 * 2) + 4 + 4 + 4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ELFCLASS64:
|
case ELFCLASS64:
|
||||||
offset += 4; /* Padding before pr_statussz. */
|
offset = 4 + 4 + 8; /* Includes padding before pr_statussz. */
|
||||||
offset += 8;
|
min_size = offset + (8 * 2) + 4 + 4 + 4 + 4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (note->descsz < min_size)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* Check for version 1 in pr_version. */
|
||||||
|
if (bfd_h_get_32 (abfd, (bfd_byte *) note->descdata) != 1)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
/* Extract size of pr_reg from pr_gregsetsz. */
|
/* Extract size of pr_reg from pr_gregsetsz. */
|
||||||
|
/* Skip over pr_gregsetsz and pr_fpregsetsz. */
|
||||||
if (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS32)
|
if (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS32)
|
||||||
size = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + offset);
|
{
|
||||||
|
size = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + offset);
|
||||||
|
offset += 4 * 2;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
size = bfd_h_get_64 (abfd, (bfd_byte *) note->descdata + offset);
|
{
|
||||||
|
size = bfd_h_get_64 (abfd, (bfd_byte *) note->descdata + offset);
|
||||||
|
offset += 8 * 2;
|
||||||
|
}
|
||||||
|
|
||||||
/* Skip over pr_gregsetsz and pr_fpregsetsz. */
|
/* Skip over pr_osreldate. */
|
||||||
if (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS32)
|
|
||||||
offset += 4 * 2;
|
|
||||||
else
|
|
||||||
offset += 8 * 2;
|
|
||||||
|
|
||||||
/* Skip over pr_osreldate. */
|
|
||||||
offset += 4;
|
offset += 4;
|
||||||
|
|
||||||
/* Read signal from pr_cursig. */
|
/* Read signal from pr_cursig. */
|
||||||
if (elf_tdata (abfd)->core->signal == 0)
|
if (elf_tdata (abfd)->core->signal == 0)
|
||||||
elf_tdata (abfd)->core->signal
|
elf_tdata (abfd)->core->signal
|
||||||
= bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + offset);
|
= bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + offset);
|
||||||
offset += 4;
|
offset += 4;
|
||||||
|
|
||||||
/* Read TID from pr_pid. */
|
/* Read TID from pr_pid. */
|
||||||
elf_tdata (abfd)->core->lwpid
|
elf_tdata (abfd)->core->lwpid
|
||||||
= bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + offset);
|
= bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + offset);
|
||||||
offset += 4;
|
offset += 4;
|
||||||
|
|
||||||
/* Padding before pr_reg. */
|
/* Padding before pr_reg. */
|
||||||
if (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64)
|
if (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64)
|
||||||
offset += 4;
|
offset += 4;
|
||||||
|
|
||||||
|
/* Make sure that there is enough data remaining in the note. */
|
||||||
|
if ((note->descsz - offset) < size)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
/* Make a ".reg/999" section and a ".reg" section. */
|
/* Make a ".reg/999" section and a ".reg" section. */
|
||||||
return _bfd_elfcore_make_pseudosection (abfd, ".reg",
|
return _bfd_elfcore_make_pseudosection (abfd, ".reg",
|
||||||
size, note->descpos + offset);
|
size, note->descpos + offset);
|
||||||
|
Reference in New Issue
Block a user