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)

View File

@ -896,7 +896,12 @@ _bfd_elf_setup_sections (bfd *abfd)
n_elt = shdr->sh_size / 4;
while (--n_elt != 0)
if ((++idx)->shdr->bfd_section)
{
++ 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)
@ -922,6 +927,8 @@ _bfd_elf_setup_sections (bfd *abfd)
result = FALSE;
}
}
}
return result;
}
@ -9883,39 +9890,45 @@ 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;
}
/* Extract size of pr_reg from pr_gregsetsz. */
if (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS32)
size = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + offset);
else
size = bfd_h_get_64 (abfd, (bfd_byte *) note->descdata + offset);
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);
offset += 4 * 2;
}
else
{
size = bfd_h_get_64 (abfd, (bfd_byte *) note->descdata + offset);
offset += 8 * 2;
}
/* Skip over pr_osreldate. */
offset += 4;
@ -9935,6 +9948,10 @@ elfcore_grok_freebsd_prstatus (bfd *abfd, Elf_Internal_Note *note)
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);