From: Alan Modra Date: Tue, 19 May 2020 22:25:56 +0000 (+0930) Subject: PR26011, excessive memory allocation with fuzzed reloc sections X-Git-Url: http://git.efficios.com/?a=commitdiff_plain;h=3c568b8afab512d12eb5adcf304e505b1bce644d;hp=c7e976792002c6a2810f9bb6cc3ad210514eb650;p=deliverable%2Fbinutils-gdb.git PR26011, excessive memory allocation with fuzzed reloc sections Check sizes early, before users of slurp_relocs allocate buffers for the swapped in relocs. PR 26011 * elf.c (_bfd_elf_get_reloc_upper_bound): Sanity check reloc section size against file size. (_bfd_elf_get_dynamic_reloc_upper_bound): Likewise. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index cb168f1768..6d3673d14c 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,10 @@ +2020-05-20 Alan Modra + + PR 26011 + * elf.c (_bfd_elf_get_reloc_upper_bound): Sanity check reloc + section size against file size. + (_bfd_elf_get_dynamic_reloc_upper_bound): Likewise. + 2020-05-19 Gunther Nikl PR 26005 diff --git a/bfd/elf.c b/bfd/elf.c index 40943781bc..0211970991 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -8508,9 +8508,23 @@ _bfd_elf_get_dynamic_symtab_upper_bound (bfd *abfd) } long -_bfd_elf_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED, - sec_ptr asect) +_bfd_elf_get_reloc_upper_bound (bfd *abfd, sec_ptr asect) { + if (asect->reloc_count != 0) + { + /* Sanity check reloc section size. */ + struct bfd_elf_section_data *d = elf_section_data (asect); + Elf_Internal_Shdr *rel_hdr = &d->this_hdr; + bfd_size_type ext_rel_size = rel_hdr->sh_size; + ufile_ptr filesize = bfd_get_file_size (abfd); + + if (filesize != 0 && ext_rel_size > filesize) + { + bfd_set_error (bfd_error_file_truncated); + return -1; + } + } + #if SIZEOF_LONG == SIZEOF_INT if (asect->reloc_count >= LONG_MAX / sizeof (arelent *)) { @@ -8576,7 +8590,7 @@ _bfd_elf_canonicalize_dynamic_symtab (bfd *abfd, long _bfd_elf_get_dynamic_reloc_upper_bound (bfd *abfd) { - bfd_size_type count; + bfd_size_type count, ext_rel_size; asection *s; if (elf_dynsymtab (abfd) == 0) @@ -8586,11 +8600,18 @@ _bfd_elf_get_dynamic_reloc_upper_bound (bfd *abfd) } count = 1; + ext_rel_size = 0; for (s = abfd->sections; s != NULL; s = s->next) if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd) && (elf_section_data (s)->this_hdr.sh_type == SHT_REL || elf_section_data (s)->this_hdr.sh_type == SHT_RELA)) { + ext_rel_size += s->size; + if (ext_rel_size < s->size) + { + bfd_set_error (bfd_error_file_truncated); + return -1; + } count += s->size / elf_section_data (s)->this_hdr.sh_entsize; if (count > LONG_MAX / sizeof (arelent *)) { @@ -8598,6 +8619,16 @@ _bfd_elf_get_dynamic_reloc_upper_bound (bfd *abfd) return -1; } } + if (count > 1) + { + /* Sanity check reloc section sizes. */ + ufile_ptr filesize = bfd_get_file_size (abfd); + if (filesize != 0 && ext_rel_size > filesize) + { + bfd_set_error (bfd_error_file_truncated); + return -1; + } + } return count * sizeof (arelent *); }