commit ca4cf9b9c622a5695e01f7f5815a7382a31fcf51 Author: Nick Clifton Date: Mon Jul 24 13:49:22 2017 +0100 Fix address violation errors parsing corrupt binary files. PR 21813 binutils* rddbg.c (read_symbol_stabs_debugging_info): Check for an empty string whilst concatenating symbol names. bfd * mach-o.c (bfd_mach_o_canonicalize_relocs): Pass the base address of the relocs to the canonicalize_one_reloc routine. * mach-o.h (struct bfd_mach_o_backend_data): Update the prototype for the _bfd_mach_o_canonicalize_one_reloc field. * mach-o-arm.c (bfd_mach_o_arm_canonicalize_one_reloc): Add res_base parameter. Use to check for corrupt pair relocs. * mach-o-aarch64.c (bfd_mach_o_arm64_canonicalize_one_reloc): Likewise. * mach-o-i386.c (bfd_mach_o_i386_canonicalize_one_reloc): Likewise. * mach-o-x86-64.c (bfd_mach_o_x86_64_canonicalize_one_reloc): Likewise. * vms-alpha.c (_bfd_vms_slurp_eihd): Make sure that there is enough data in the record before attempting to parse it. (_bfd_vms_slurp_eeom): Likewise. (_bfd_vms_slurp_egsd): Check for an invalid section index. (image_set_ptr): Likewise. (alpha_vms_slurp_relocs): Likewise. (alpha_vms_object_p): Check for a truncated record. Upstream-Status: Backport CVE: CVE-2017-12450, CVE-2017-12452, CVE-2017-12453, CVE-2017-12454, CVE-2017-12456 Signed-off-by: Thiruvadi Rajaraman Index: git/bfd/mach-o-aarch64.c =================================================================== --- git.orig/bfd/mach-o-aarch64.c 2017-08-31 19:17:51.264385450 +0530 +++ git/bfd/mach-o-aarch64.c 2017-08-31 19:18:02.620442777 +0530 @@ -147,9 +147,11 @@ }; static bfd_boolean -bfd_mach_o_arm64_canonicalize_one_reloc (bfd *abfd, - struct mach_o_reloc_info_external *raw, - arelent *res, asymbol **syms) +bfd_mach_o_arm64_canonicalize_one_reloc (bfd * abfd, + struct mach_o_reloc_info_external * raw, + arelent * res, + asymbol ** syms, + arelent * res_base ATTRIBUTE_UNUSED) { bfd_mach_o_reloc_info reloc; Index: git/bfd/mach-o-i386.c =================================================================== --- git.orig/bfd/mach-o-i386.c 2017-08-31 19:17:51.264385450 +0530 +++ git/bfd/mach-o-i386.c 2017-08-31 19:18:02.620442777 +0530 @@ -112,9 +112,11 @@ }; static bfd_boolean -bfd_mach_o_i386_canonicalize_one_reloc (bfd *abfd, - struct mach_o_reloc_info_external *raw, - arelent *res, asymbol **syms) +bfd_mach_o_i386_canonicalize_one_reloc (bfd * abfd, + struct mach_o_reloc_info_external * raw, + arelent * res, + asymbol ** syms, + arelent * res_base) { bfd_mach_o_reloc_info reloc; @@ -126,6 +128,9 @@ switch (reloc.r_type) { case BFD_MACH_O_GENERIC_RELOC_PAIR: + /* PR 21813: Check for a corrupt PAIR reloc at the start. */ + if (res == res_base) + return FALSE; if (reloc.r_length == 2) { res->howto = &i386_howto_table[7]; @@ -391,9 +396,9 @@ { NULL, NULL } }; -#define bfd_mach_o_canonicalize_one_reloc bfd_mach_o_i386_canonicalize_one_reloc -#define bfd_mach_o_swap_reloc_out bfd_mach_o_i386_swap_reloc_out -#define bfd_mach_o_print_thread bfd_mach_o_i386_print_thread +#define bfd_mach_o_canonicalize_one_reloc bfd_mach_o_i386_canonicalize_one_reloc +#define bfd_mach_o_swap_reloc_out bfd_mach_o_i386_swap_reloc_out +#define bfd_mach_o_print_thread bfd_mach_o_i386_print_thread #define bfd_mach_o_tgt_seg_table mach_o_i386_segsec_names_xlat #define bfd_mach_o_section_type_valid_for_tgt NULL Index: git/bfd/mach-o-x86-64.c =================================================================== --- git.orig/bfd/mach-o-x86-64.c 2017-08-31 19:17:51.264385450 +0530 +++ git/bfd/mach-o-x86-64.c 2017-08-31 19:18:02.620442777 +0530 @@ -120,9 +120,11 @@ }; static bfd_boolean -bfd_mach_o_x86_64_canonicalize_one_reloc (bfd *abfd, - struct mach_o_reloc_info_external *raw, - arelent *res, asymbol **syms) +bfd_mach_o_x86_64_canonicalize_one_reloc (bfd * abfd, + struct mach_o_reloc_info_external * raw, + arelent * res, + asymbol ** syms, + arelent * res_base ATTRIBUTE_UNUSED) { bfd_mach_o_reloc_info reloc; Index: git/bfd/mach-o.c =================================================================== --- git.orig/bfd/mach-o.c 2017-08-31 19:18:02.440441869 +0530 +++ git/bfd/mach-o.c 2017-08-31 19:18:02.620442777 +0530 @@ -1496,7 +1496,7 @@ for (i = 0; i < count; i++) { if (!(*bed->_bfd_mach_o_canonicalize_one_reloc)(abfd, &native_relocs[i], - &res[i], syms)) + &res[i], syms, res)) goto err; } free (native_relocs); Index: git/bfd/mach-o.h =================================================================== --- git.orig/bfd/mach-o.h 2017-08-31 19:17:51.264385450 +0530 +++ git/bfd/mach-o.h 2017-08-31 19:18:02.620442777 +0530 @@ -746,7 +746,7 @@ enum bfd_architecture arch; bfd_vma page_size; bfd_boolean (*_bfd_mach_o_canonicalize_one_reloc) - (bfd *, struct mach_o_reloc_info_external *, arelent *, asymbol **); + (bfd *, struct mach_o_reloc_info_external *, arelent *, asymbol **, arelent *); bfd_boolean (*_bfd_mach_o_swap_reloc_out)(arelent *, bfd_mach_o_reloc_info *); bfd_boolean (*_bfd_mach_o_print_thread)(bfd *, bfd_mach_o_thread_flavour *, void *, char *); Index: git/bfd/ChangeLog =================================================================== --- git.orig/bfd/ChangeLog 2017-08-31 19:18:02.564442494 +0530 +++ git/bfd/ChangeLog 2017-08-31 19:18:02.620442777 +0530 @@ -11,6 +11,30 @@ of end pointer. (evax_bfd_print_emh): Check for invalid string lengths. + 2017-07-24 Nick Clifton + + PR 21813 + * mach-o.c (bfd_mach_o_canonicalize_relocs): Pass the base address + of the relocs to the canonicalize_one_reloc routine. + * mach-o.h (struct bfd_mach_o_backend_data): Update the prototype + for the _bfd_mach_o_canonicalize_one_reloc field. + * mach-o-arm.c (bfd_mach_o_arm_canonicalize_one_reloc): Add + res_base parameter. Use to check for corrupt pair relocs. + * mach-o-aarch64.c (bfd_mach_o_arm64_canonicalize_one_reloc): + Likewise. + * mach-o-i386.c (bfd_mach_o_i386_canonicalize_one_reloc): + Likewise. + * mach-o-x86-64.c (bfd_mach_o_x86_64_canonicalize_one_reloc): + Likewise. + + * vms-alpha.c (_bfd_vms_slurp_eihd): Make sure that there is + enough data in the record before attempting to parse it. + (_bfd_vms_slurp_eeom): Likewise. + + (_bfd_vms_slurp_egsd): Check for an invalid section index. + (image_set_ptr): Likewise. + (alpha_vms_slurp_relocs): Likewise. + 2017-07-19 Nick Clifton PR 21786 Index: git/bfd/mach-o-arm.c =================================================================== --- git.orig/bfd/mach-o-arm.c 2017-08-31 19:17:51.264385450 +0530 +++ git/bfd/mach-o-arm.c 2017-08-31 19:18:02.620442777 +0530 @@ -30,7 +30,7 @@ #define bfd_mach_o_mkobject bfd_mach_o_arm_mkobject #define bfd_mach_o_canonicalize_one_reloc bfd_mach_o_arm_canonicalize_one_reloc -#define bfd_mach_o_swap_reloc_out NULL +#define bfd_mach_o_swap_reloc_out NULL #define bfd_mach_o_bfd_reloc_type_lookup bfd_mach_o_arm_bfd_reloc_type_lookup #define bfd_mach_o_bfd_reloc_name_lookup bfd_mach_o_arm_bfd_reloc_name_lookup @@ -147,9 +147,11 @@ }; static bfd_boolean -bfd_mach_o_arm_canonicalize_one_reloc (bfd *abfd, - struct mach_o_reloc_info_external *raw, - arelent *res, asymbol **syms) +bfd_mach_o_arm_canonicalize_one_reloc (bfd * abfd, + struct mach_o_reloc_info_external * raw, + arelent * res, + asymbol ** syms, + arelent * res_base) { bfd_mach_o_reloc_info reloc; @@ -161,6 +163,9 @@ switch (reloc.r_type) { case BFD_MACH_O_ARM_RELOC_PAIR: + /* PR 21813: Check for a corrupt PAIR reloc at the start. */ + if (res == res_base) + return FALSE; if (reloc.r_length == 2) { res->howto = &arm_howto_table[7]; Index: git/bfd/vms-alpha.c =================================================================== --- git.orig/bfd/vms-alpha.c 2017-08-31 19:18:02.556442454 +0530 +++ git/bfd/vms-alpha.c 2017-08-31 19:20:56.233322607 +0530 @@ -473,6 +473,14 @@ vms_debug2 ((8, "_bfd_vms_slurp_eihd\n")); + /* PR 21813: Check for an undersized record. */ + if (PRIV (recrd.buf_size) < sizeof (* eihd)) + { + _bfd_error_handler (_("Corrupt EIHD record - size is too small")); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + size = bfd_getl32 (eihd->size); imgtype = bfd_getl32 (eihd->imgtype); @@ -1255,19 +1263,39 @@ if (old_flags & EGSY__V_DEF) { struct vms_esdf *esdf = (struct vms_esdf *)vms_rec; + long psindx; entry->value = bfd_getl64 (esdf->value); if (PRIV (sections) == NULL) return FALSE; - entry->section = PRIV (sections)[bfd_getl32 (esdf->psindx)]; + + psindx = bfd_getl32 (esdf->psindx); + /* PR 21813: Check for an out of range index. */ + if (psindx < 0 || psindx >= (int) PRIV (section_count)) + { + _bfd_error_handler (_("Corrupt EGSD record: its psindx field is too big (%#lx)"), + psindx); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + entry->section = PRIV (sections)[psindx]; if (old_flags & EGSY__V_NORM) { PRIV (norm_sym_count)++; entry->code_value = bfd_getl64 (esdf->code_address); - entry->code_section = - PRIV (sections)[bfd_getl32 (esdf->ca_psindx)]; + psindx = bfd_getl32 (esdf->ca_psindx); + /* PR 21813: Check for an out of range index. */ + if (psindx < 0 || psindx >= (int) PRIV (section_count)) + { + _bfd_error_handler (_("Corrupt EGSD record: its psindx field is too big (%#lx)"), + psindx); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + entry->code_section = PRIV (sections)[psindx]; + } } } @@ -1294,9 +1322,20 @@ if (old_flags & EGSY__V_REL) { + long psindx; + if (PRIV (sections) == NULL) return FALSE; - entry->section = PRIV (sections)[bfd_getl32 (egst->psindx)]; + psindx = bfd_getl32 (egst->psindx); + /* PR 21813: Check for an out of range index. */ + if (psindx < 0 || psindx >= (int) PRIV (section_count)) + { + _bfd_error_handler (_("Corrupt EGSD record: its psindx field is too big (%#lx)"), + psindx); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + entry->section = PRIV (sections)[psindx]; } else entry->section = bfd_abs_section_ptr; @@ -1387,6 +1426,10 @@ if (PRIV (sections) == NULL) return; + + if (sect < 0 || sect >= (int) PRIV (section_count)) + return; + sec = PRIV (sections)[sect]; if (info) @@ -2360,6 +2403,14 @@ vms_debug2 ((2, "EEOM\n")); + /* PR 21813: Check for an undersized record. */ + if (PRIV (recrd.buf_size) < sizeof (* eeom)) + { + _bfd_error_handler (_("Corrupt EEOM record - size is too small")); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + PRIV (eom_data).eom_l_total_lps = bfd_getl32 (eeom->total_lps); PRIV (eom_data).eom_w_comcod = bfd_getl16 (eeom->comcod); if (PRIV (eom_data).eom_w_comcod > 1) @@ -2540,6 +2591,10 @@ PRIV (recrd.buf_size) = PRIV (recrd.rec_size); } + /* PR 21813: Check for a truncated record. */ + if (PRIV (recrd.rec_size < test_len)) + goto error_ret; + /* Read the remaining record. */ remaining = PRIV (recrd.rec_size) - test_len; to_read = MIN (VMS_BLOCK_SIZE - test_len, remaining); @@ -5074,7 +5129,7 @@ } else if (cur_psidx >= 0) { - if (PRIV (sections) == NULL) + if (PRIV (sections) == NULL || cur_psidx >= (int) PRIV (section_count)) return FALSE; reloc->sym_ptr_ptr = PRIV (sections)[cur_psidx]->symbol_ptr_ptr; Index: git/binutils/ChangeLog =================================================================== --- git.orig/binutils/ChangeLog 2017-08-31 19:18:01.816438718 +0530 +++ git/binutils/ChangeLog 2017-08-31 19:18:02.624442798 +0530 @@ -1,3 +1,9 @@ +2017-07-24 Nick Clifton + + PR 21813 + * rddbg.c (read_symbol_stabs_debugging_info): Check for an empty + string whilst concatenating symbol names. + 2017-02-14 Nick Clifton PR binutils/21157 Index: git/binutils/rddbg.c =================================================================== --- git.orig/binutils/rddbg.c 2017-08-31 19:17:51.596387126 +0530 +++ git/binutils/rddbg.c 2017-08-31 19:18:02.624442798 +0530 @@ -300,7 +300,8 @@ s = i.name; f = NULL; - while (s[strlen (s) - 1] == '\\' + while (strlen (s) > 0 + && s[strlen (s) - 1] == '\\' && ps + 1 < symend) { char *sc, *n;