From 3a551c7a1b80fca579461774860574eabfd7f18f Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Sun, 16 Dec 2018 23:02:50 +1030 Subject: [PATCH] PR23994, libbfd integer overflow PR 23994 * aoutx.h: Include limits.h. (get_reloc_upper_bound): Detect long overflow and return a file too big error if it occurs. * elf.c: Include limits.h. (_bfd_elf_get_symtab_upper_bound): Detect long overflow and return a file too big error if it occurs. (_bfd_elf_get_dynamic_symtab_upper_bound): Likewise. (_bfd_elf_get_dynamic_reloc_upper_bound): Likewise. --- bfd/ChangeLog | 12 ++++++++++++ bfd/aoutx.h | 40 +++++++++++++++++++++------------------- bfd/elf.c | 32 ++++++++++++++++++++++++-------- 3 files changed, 57 insertions(+), 27 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 7ddcf7efa25..9e5717e89fb 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,15 @@ +2018-12-17 Alan Modra + + PR 23994 + * aoutx.h: Include limits.h. + (get_reloc_upper_bound): Detect long overflow and return a file + too big error if it occurs. + * elf.c: Include limits.h. + (_bfd_elf_get_symtab_upper_bound): Detect long overflow and return + a file too big error if it occurs. + (_bfd_elf_get_dynamic_symtab_upper_bound): Likewise. + (_bfd_elf_get_dynamic_reloc_upper_bound): Likewise. + 2018-12-14 H.J. Lu PR ld/23900 diff --git a/bfd/aoutx.h b/bfd/aoutx.h index 023843b0be4..78eaa9c5034 100644 --- a/bfd/aoutx.h +++ b/bfd/aoutx.h @@ -117,6 +117,7 @@ DESCRIPTION #define KEEPIT udata.i #include "sysdep.h" +#include #include "bfd.h" #include "safe-ctype.h" #include "bfdlink.h" @@ -2491,6 +2492,8 @@ NAME (aout, canonicalize_reloc) (bfd *abfd, long NAME (aout, get_reloc_upper_bound) (bfd *abfd, sec_ptr asect) { + bfd_size_type count; + if (bfd_get_format (abfd) != bfd_object) { bfd_set_error (bfd_error_invalid_operation); @@ -2498,26 +2501,25 @@ NAME (aout, get_reloc_upper_bound) (bfd *abfd, sec_ptr asect) } if (asect->flags & SEC_CONSTRUCTOR) - return sizeof (arelent *) * (asect->reloc_count + 1); - - if (asect == obj_datasec (abfd)) - return sizeof (arelent *) - * ((exec_hdr (abfd)->a_drsize / obj_reloc_entry_size (abfd)) - + 1); - - if (asect == obj_textsec (abfd)) - return sizeof (arelent *) - * ((exec_hdr (abfd)->a_trsize / obj_reloc_entry_size (abfd)) - + 1); - - if (asect == obj_bsssec (abfd)) - return sizeof (arelent *); - - if (asect == obj_bsssec (abfd)) - return 0; + count = asect->reloc_count; + else if (asect == obj_datasec (abfd)) + count = exec_hdr (abfd)->a_drsize / obj_reloc_entry_size (abfd); + else if (asect == obj_textsec (abfd)) + count = exec_hdr (abfd)->a_trsize / obj_reloc_entry_size (abfd); + else if (asect == obj_bsssec (abfd)) + count = 0; + else + { + bfd_set_error (bfd_error_invalid_operation); + return -1; + } - bfd_set_error (bfd_error_invalid_operation); - return -1; + if (count >= LONG_MAX / sizeof (arelent *)) + { + bfd_set_error (bfd_error_file_too_big); + return -1; + } + return (count + 1) * sizeof (arelent *); } long diff --git a/bfd/elf.c b/bfd/elf.c index 688429b73e4..b10dcd83c55 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -35,6 +35,7 @@ SECTION /* For sparc64-cross-sparc32. */ #define _SYSCALL32 #include "sysdep.h" +#include #include "bfd.h" #include "bfdlink.h" #include "libbfd.h" @@ -8215,11 +8216,16 @@ error_return: long _bfd_elf_get_symtab_upper_bound (bfd *abfd) { - long symcount; + bfd_size_type symcount; long symtab_size; Elf_Internal_Shdr *hdr = &elf_tdata (abfd)->symtab_hdr; symcount = hdr->sh_size / get_elf_backend_data (abfd)->s->sizeof_sym; + if (symcount >= LONG_MAX / sizeof (asymbol *)) + { + bfd_set_error (bfd_error_file_too_big); + return -1; + } symtab_size = (symcount + 1) * (sizeof (asymbol *)); if (symcount > 0) symtab_size -= sizeof (asymbol *); @@ -8230,7 +8236,7 @@ _bfd_elf_get_symtab_upper_bound (bfd *abfd) long _bfd_elf_get_dynamic_symtab_upper_bound (bfd *abfd) { - long symcount; + bfd_size_type symcount; long symtab_size; Elf_Internal_Shdr *hdr = &elf_tdata (abfd)->dynsymtab_hdr; @@ -8241,6 +8247,11 @@ _bfd_elf_get_dynamic_symtab_upper_bound (bfd *abfd) } symcount = hdr->sh_size / get_elf_backend_data (abfd)->s->sizeof_sym; + if (symcount >= LONG_MAX / sizeof (asymbol *)) + { + bfd_set_error (bfd_error_file_too_big); + return -1; + } symtab_size = (symcount + 1) * (sizeof (asymbol *)); if (symcount > 0) symtab_size -= sizeof (asymbol *); @@ -8310,7 +8321,7 @@ _bfd_elf_canonicalize_dynamic_symtab (bfd *abfd, long _bfd_elf_get_dynamic_reloc_upper_bound (bfd *abfd) { - long ret; + bfd_size_type count; asection *s; if (elf_dynsymtab (abfd) == 0) @@ -8319,15 +8330,20 @@ _bfd_elf_get_dynamic_reloc_upper_bound (bfd *abfd) return -1; } - ret = sizeof (arelent *); + count = 1; 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)) - ret += ((s->size / elf_section_data (s)->this_hdr.sh_entsize) - * sizeof (arelent *)); - - return ret; + { + count += s->size / elf_section_data (s)->this_hdr.sh_entsize; + if (count > LONG_MAX / sizeof (arelent *)) + { + bfd_set_error (bfd_error_file_too_big); + return -1; + } + } + return count * sizeof (arelent *); } /* Canonicalize the dynamic relocation entries. Note that we return the -- 2.30.2