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:
Nick Clifton
2017-08-08 13:20:02 +01:00
parent 1fea592a7d
commit 24d3e51bf0
3 changed files with 80 additions and 47 deletions

View File

@ -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>
PR 21017

View File

@ -468,6 +468,12 @@ _bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr)
if (section_len > len)
section_len = 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;
namelen = strnlen ((char *) p, section_len) + 1;
if (namelen == 0 || namelen >= section_len)

111
bfd/elf.c
View File

@ -896,32 +896,39 @@ _bfd_elf_setup_sections (bfd *abfd)
n_elt = shdr->sh_size / 4;
while (--n_elt != 0)
if ((++idx)->shdr->bfd_section)
elf_sec_group (idx->shdr->bfd_section) = shdr->bfd_section;
else if (idx->shdr->sh_type == SHT_RELA
|| idx->shdr->sh_type == SHT_REL)
/* We won't include relocation sections in section groups in
output object files. We adjust the group section size here
so that relocatable link will work correctly when
relocation sections are in section group in input object
files. */
shdr->bfd_section->size -= 4;
else
{
/* There are some unknown sections in the group. */
_bfd_error_handler
/* xgettext:c-format */
(_("%B: unknown type [%#x] section `%s' in group [%A]"),
abfd,
idx->shdr->sh_type,
bfd_elf_string_from_elf_section (abfd,
(elf_elfheader (abfd)
->e_shstrndx),
idx->shdr->sh_name),
shdr->bfd_section);
result = FALSE;
}
{
++ idx;
if (idx->shdr == NULL)
continue;
else if (idx->shdr->bfd_section)
elf_sec_group (idx->shdr->bfd_section) = shdr->bfd_section;
else if (idx->shdr->sh_type == SHT_RELA
|| idx->shdr->sh_type == SHT_REL)
/* We won't include relocation sections in section groups in
output object files. We adjust the group section size here
so that relocatable link will work correctly when
relocation sections are in section group in input object
files. */
shdr->bfd_section->size -= 4;
else
{
/* There are some unknown sections in the group. */
_bfd_error_handler
/* xgettext:c-format */
(_("%B: unknown type [%#x] section `%s' in group [%A]"),
abfd,
idx->shdr->sh_type,
bfd_elf_string_from_elf_section (abfd,
(elf_elfheader (abfd)
->e_shstrndx),
idx->shdr->sh_name),
shdr->bfd_section);
result = FALSE;
}
}
}
return result;
}
@ -8954,7 +8961,7 @@ elfcore_maybe_make_sect (bfd *abfd, char *name, asection *sect)
such a section already exists.
- For the multi-threaded case, a section named "NAME/PID", where
PID is elfcore_make_pid (abfd).
Both pseudosections have identical contents. */
Both pseudosections have identical contents. */
bfd_boolean
_bfd_elfcore_make_pseudosection (bfd *abfd,
char *name,
@ -9883,58 +9890,68 @@ elfcore_grok_freebsd_prstatus (bfd *abfd, Elf_Internal_Note *note)
{
size_t offset;
size_t size;
size_t min_size;
/* Check for version 1 in pr_version. */
if (bfd_h_get_32 (abfd, (bfd_byte *) note->descdata) != 1)
return FALSE;
offset = 4;
/* Skip over pr_statussz. */
/* Compute offset of pr_getregsz, skipping over pr_statussz.
Also compute minimum size of this note. */
switch (elf_elfheader (abfd)->e_ident[EI_CLASS])
{
case ELFCLASS32:
offset += 4;
offset = 4 + 4;
min_size = offset + (4 * 2) + 4 + 4 + 4;
break;
case ELFCLASS64:
offset += 4; /* Padding before pr_statussz. */
offset += 8;
offset = 4 + 4 + 8; /* Includes padding before pr_statussz. */
min_size = offset + (8 * 2) + 4 + 4 + 4 + 4;
break;
default:
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. */
/* Skip over pr_gregsetsz and pr_fpregsetsz. */
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
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. */
if (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS32)
offset += 4 * 2;
else
offset += 8 * 2;
/* Skip over pr_osreldate. */
/* Skip over pr_osreldate. */
offset += 4;
/* Read signal from pr_cursig. */
/* Read signal from pr_cursig. */
if (elf_tdata (abfd)->core->signal == 0)
elf_tdata (abfd)->core->signal
= bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + offset);
offset += 4;
/* Read TID from pr_pid. */
/* Read TID from pr_pid. */
elf_tdata (abfd)->core->lwpid
= bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + offset);
offset += 4;
/* Padding before pr_reg. */
/* Padding before pr_reg. */
if (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64)
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. */
return _bfd_elfcore_make_pseudosection (abfd, ".reg",
size, note->descpos + offset);