From be22c732bf873e0c7e8a08564c97cafdfcf153bb Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Thu, 14 Mar 2019 14:45:32 +0000 Subject: [PATCH] Fix illegal memory access parsing a corrupt ELF file. PR 24332 * elflink.c (elf_link_add_object_symbols): Add new local variable extversym_end. Initialise it to point to the end of the version symbol table, if present. Check it when initialising and updating the ever pointer. --- bfd/ChangeLog | 8 ++++++++ bfd/elflink.c | 29 ++++++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 540f7373cab..447eb707c87 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,11 @@ +2019-03-14 Nick Clifton + + PR 24332 + * elflink.c (elf_link_add_object_symbols): Add new local variable + extversym_end. Initialise it to point to the end of the version + symbol table, if present. Check it when initialising and updating + the ever pointer. + 2019-03-13 Sudakshina Das * elfnn-aarch64.c (PLT_PAC_ENTRY_SIZE, PLT_PAC_SMALL_ENTRY_SIZE): New. diff --git a/bfd/elflink.c b/bfd/elflink.c index e50c0e4b38e..3ac58daafda 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -3872,6 +3872,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) struct elf_link_hash_entry **sym_hash; bfd_boolean dynamic; Elf_External_Versym *extversym = NULL; + Elf_External_Versym *extversym_end = NULL; Elf_External_Versym *ever; struct elf_link_hash_entry *weaks; struct elf_link_hash_entry **nondeflt_vers = NULL; @@ -4297,13 +4298,14 @@ error_free_dyn: Elf_Internal_Shdr *versymhdr; versymhdr = &elf_tdata (abfd)->dynversym_hdr; - extversym = (Elf_External_Versym *) bfd_malloc (versymhdr->sh_size); + amt = versymhdr->sh_size; + extversym = (Elf_External_Versym *) bfd_malloc (amt); if (extversym == NULL) goto error_free_sym; - amt = versymhdr->sh_size; if (bfd_seek (abfd, versymhdr->sh_offset, SEEK_SET) != 0 || bfd_bread (extversym, amt, abfd) != amt) goto error_free_vers; + extversym_end = extversym + (amt / sizeof (* extversym)); } } @@ -4378,7 +4380,20 @@ error_free_dyn: } weaks = NULL; - ever = extversym != NULL ? extversym + extsymoff : NULL; + if (extversym == NULL) + ever = NULL; + else if (extversym + extsymoff < extversym_end) + ever = extversym + extsymoff; + else + { + /* xgettext:c-format */ + _bfd_error_handler (_("%pB: invalid version offset %lx (max %lx)"), + abfd, (long) extsymoff, + (long) (extversym_end - extversym) / sizeof (* extversym)); + bfd_set_error (bfd_error_bad_value); + goto error_free_vers; + } + for (isym = isymbuf, isymend = isymbuf + extsymcount; isym < isymend; isym++, sym_hash++, ever = (ever != NULL ? ever + 1 : NULL)) @@ -4562,6 +4577,14 @@ error_free_dyn: else iver.vs_vers = 0; } + else if (ever >= extversym_end) + { + /* xgettext:c-format */ + _bfd_error_handler (_("%pB: not enough version information"), + abfd); + bfd_set_error (bfd_error_bad_value); + goto error_free_vers; + } else _bfd_elf_swap_versym_in (abfd, ever, &iver); -- 2.30.2