From 434f5cc914724ee009d204e828e488ed56bc09c5 Mon Sep 17 00:00:00 2001 From: suezzelur Date: Fri, 11 Aug 2017 12:53:27 -0700 Subject: [PATCH] Add patches for bintuils CVE-2017-12448 to -12459 Change-Id: Id5437a2991cef8f57c9781b05fcd2e0585dc504b Reviewed-on: http://photon-jenkins.eng.vmware.com:8082/3503 Tested-by: gerrit-photon Reviewed-by: Sharath George --- .gitignore | 1 + SPECS/binutils/CVE-2017-12448.patch | 20 ++ ...E-2017-12449_12455_12457_12458_12459.patch | 233 +++++++++++++ SPECS/binutils/CVE-2017-12450.patch | 29 ++ SPECS/binutils/CVE-2017-12451.patch | 289 ++++++++++++++++ .../CVE-2017-12452_12453_12454_12456.patch | 319 ++++++++++++++++++ SPECS/binutils/binutils.spec | 17 +- 7 files changed, 907 insertions(+), 1 deletion(-) create mode 100644 SPECS/binutils/CVE-2017-12448.patch create mode 100644 SPECS/binutils/CVE-2017-12449_12455_12457_12458_12459.patch create mode 100644 SPECS/binutils/CVE-2017-12450.patch create mode 100644 SPECS/binutils/CVE-2017-12451.patch create mode 100644 SPECS/binutils/CVE-2017-12452_12453_12454_12456.patch diff --git a/.gitignore b/.gitignore index 17ab7b82bf..de3bb40d88 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ stage discus-cache/ output-*/ tools/bin/ +common/data/pkg_info.json diff --git a/SPECS/binutils/CVE-2017-12448.patch b/SPECS/binutils/CVE-2017-12448.patch new file mode 100644 index 0000000000..d237dad90d --- /dev/null +++ b/SPECS/binutils/CVE-2017-12448.patch @@ -0,0 +1,20 @@ +X-Git-Url: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=blobdiff_plain;f=bfd%2Farchive.c;h=885bf489c024a7a24444bb82740987dd20aff184;hp=f209babe149f3f5b302da64f593e039c9c79ea8c;hb=909e4e716c4d77e33357bbe9bc902bfaf2e1af24;hpb=62a5222fdab2acdc129b7c7d3713e7f349e26029 + +diff --git a/bfd/archive.c b/bfd/archive.c +index f209bab..885bf48 100644 +--- a/bfd/archive.c ++++ b/bfd/archive.c +@@ -834,7 +834,12 @@ bfd_generic_archive_p (bfd *abfd) + if (strncmp (armag, ARMAG, SARMAG) != 0 + && strncmp (armag, ARMAGB, SARMAG) != 0 + && ! bfd_is_thin_archive (abfd)) +- return NULL; ++ { ++ bfd_set_error (bfd_error_wrong_format); ++ if (abfd->format == bfd_archive) ++ abfd->format = bfd_unknown; ++ return NULL; ++ } + + tdata_hold = bfd_ardata (abfd); + diff --git a/SPECS/binutils/CVE-2017-12449_12455_12457_12458_12459.patch b/SPECS/binutils/CVE-2017-12449_12455_12457_12458_12459.patch new file mode 100644 index 0000000000..f9db5dd6e0 --- /dev/null +++ b/SPECS/binutils/CVE-2017-12449_12455_12457_12458_12459.patch @@ -0,0 +1,233 @@ +From 8bdf0be19d2777565a8b1c88347f65d6a4b8c5fc Mon Sep 17 00:00:00 2001 +From: Nick Clifton +Date: Thu, 27 Jul 2017 12:04:50 +0100 +Subject: [PATCH 1/1] Fix address violation issues encountered when parsing + corrupt binaries. + + PR 21840 + * mach-o.c (bfd_mach_o_read_symtab_strtab): Fail if the symtab + size is -1. + * nlmcode.h (nlm_swap_auxiliary_headers_in): Replace assertion + with error return. + * section.c (bfd_make_section_with_flags): Fail if the name or bfd + are NULL. + * vms-alpha.c (bfd_make_section_with_flags): Correct computation + of end pointer. + (evax_bfd_print_emh): Check for invalid string lengths. +--- + bfd/mach-o.c | 3 ++ + bfd/nlmcode.h | 4 ++- + bfd/section.c | 2 +- + bfd/vms-alpha.c | 91 ++++++++++++++++++++++++++++++++++++--------------------- + bfd/vms-misc.c | 8 ++--- + 6 files changed, 82 insertions(+), 39 deletions(-) + +diff --git a/bfd/mach-o.c b/bfd/mach-o.c +index 1807391..9fe6326 100644 +--- a/bfd/mach-o.c ++++ b/bfd/mach-o.c +@@ -3749,6 +3749,9 @@ bfd_mach_o_read_symtab_strtab (bfd *abfd) + } + else + { ++ /* See PR 21840 for a reproducer. */ ++ if ((sym->strsize + 1) == 0) ++ return FALSE; + sym->strtab = bfd_alloc (abfd, sym->strsize + 1); + if (sym->strtab == NULL) + return FALSE; +diff --git a/bfd/nlmcode.h b/bfd/nlmcode.h +index 6d6aed0..350c83e 100644 +--- a/bfd/nlmcode.h ++++ b/bfd/nlmcode.h +@@ -351,7 +351,9 @@ nlm_swap_auxiliary_headers_in (bfd *abfd) + bfd_byte *contents; + bfd_byte *p, *pend; + +- BFD_ASSERT (hdrLength == 0 && hdr == NULL); ++ /* See PR 21840 for a reproducer. */ ++ if (hdrLength != 0 || hdr != NULL) ++ return FALSE; + + pos = bfd_tell (abfd); + if (bfd_seek (abfd, dataOffset, SEEK_SET) != 0) +diff --git a/bfd/section.c b/bfd/section.c +index 28eee7f..811d42a 100644 +--- a/bfd/section.c ++++ b/bfd/section.c +@@ -1240,7 +1240,7 @@ bfd_make_section_with_flags (bfd *abfd, const char *name, + struct section_hash_entry *sh; + asection *newsect; + +- if (abfd->output_has_begun) ++ if (abfd == NULL || name == NULL || abfd->output_has_begun) + { + bfd_set_error (bfd_error_invalid_operation); + return NULL; +diff --git a/bfd/vms-alpha.c b/bfd/vms-alpha.c +index 610b034..5595b61 100644 +--- a/bfd/vms-alpha.c ++++ b/bfd/vms-alpha.c +@@ -903,7 +903,7 @@ _bfd_vms_slurp_ehdr (bfd *abfd) + + vms_rec = PRIV (recrd.rec); + /* PR 17512: file: 62736583. */ +- end = vms_rec + PRIV (recrd.buf_size); ++ end = PRIV (recrd.buf) + PRIV (recrd.buf_size); + + vms_debug2 ((2, "HDR/EMH\n")); + +@@ -5737,8 +5737,9 @@ evax_bfd_print_emh (FILE *file, unsigned char *rec, unsigned int rec_len) + { + struct vms_emh_common *emh = (struct vms_emh_common *)rec; + unsigned int subtype; ++ int extra; + +- subtype = (unsigned)bfd_getl16 (emh->subtyp); ++ subtype = (unsigned) bfd_getl16 (emh->subtyp); + + /* xgettext:c-format */ + fprintf (file, _(" EMH %u (len=%u): "), subtype, rec_len); +@@ -5749,58 +5750,82 @@ evax_bfd_print_emh (FILE *file, unsigned char *rec, unsigned int rec_len) + fprintf (file, _(" Error: The length is less than the length of an EMH record\n")); + return; + } +- ++ extra = rec_len - sizeof (struct vms_emh_common); ++ + switch (subtype) + { + case EMH__C_MHD: + { +- struct vms_emh_mhd *mhd = (struct vms_emh_mhd *)rec; +- const char *name; ++ struct vms_emh_mhd *mhd = (struct vms_emh_mhd *) rec; ++ const char * name; ++ const char * nextname; ++ const char * maxname; + ++ /* PR 21840: Check for invalid lengths. */ ++ if (rec_len < sizeof (* mhd)) ++ { ++ fprintf (file, _(" Error: The record length is less than the size of an EMH_MHD record\n")); ++ return; ++ } + fprintf (file, _("Module header\n")); + fprintf (file, _(" structure level: %u\n"), mhd->strlvl); + fprintf (file, _(" max record size: %u\n"), +- (unsigned)bfd_getl32 (mhd->recsiz)); ++ (unsigned) bfd_getl32 (mhd->recsiz)); + name = (char *)(mhd + 1); ++ maxname = (char *) rec + rec_len; ++ if (name > maxname - 2) ++ { ++ fprintf (file, _(" Error: The module name is missing\n")); ++ return; ++ } ++ nextname = name + name[0] + 1; ++ if (nextname >= maxname) ++ { ++ fprintf (file, _(" Error: The module name is too long\n")); ++ return; ++ } + fprintf (file, _(" module name : %.*s\n"), name[0], name + 1); +- name += name[0] + 1; ++ name = nextname; ++ if (name > maxname - 2) ++ { ++ fprintf (file, _(" Error: The module version is missing\n")); ++ return; ++ } ++ nextname = name + name[0] + 1; ++ if (nextname >= maxname) ++ { ++ fprintf (file, _(" Error: The module version is too long\n")); ++ return; ++ } + fprintf (file, _(" module version : %.*s\n"), name[0], name + 1); +- name += name[0] + 1; +- fprintf (file, _(" compile date : %.17s\n"), name); ++ name = nextname; ++ if ((maxname - name) < 17 && maxname[-1] != 0) ++ fprintf (file, _(" Error: The compile date is truncated\n")); ++ else ++ fprintf (file, _(" compile date : %.17s\n"), name); + } + break; ++ + case EMH__C_LNM: +- { +- fprintf (file, _("Language Processor Name\n")); +- fprintf (file, _(" language name: %.*s\n"), +- (int)(rec_len - sizeof (struct vms_emh_common)), +- (char *)rec + sizeof (struct vms_emh_common)); +- } ++ fprintf (file, _("Language Processor Name\n")); ++ fprintf (file, _(" language name: %.*s\n"), extra, (char *)(emh + 1)); + break; ++ + case EMH__C_SRC: +- { +- fprintf (file, _("Source Files Header\n")); +- fprintf (file, _(" file: %.*s\n"), +- (int)(rec_len - sizeof (struct vms_emh_common)), +- (char *)rec + sizeof (struct vms_emh_common)); +- } ++ fprintf (file, _("Source Files Header\n")); ++ fprintf (file, _(" file: %.*s\n"), extra, (char *)(emh + 1)); + break; ++ + case EMH__C_TTL: +- { +- fprintf (file, _("Title Text Header\n")); +- fprintf (file, _(" title: %.*s\n"), +- (int)(rec_len - sizeof (struct vms_emh_common)), +- (char *)rec + sizeof (struct vms_emh_common)); +- } ++ fprintf (file, _("Title Text Header\n")); ++ fprintf (file, _(" title: %.*s\n"), extra, (char *)(emh + 1)); + break; ++ + case EMH__C_CPR: +- { +- fprintf (file, _("Copyright Header\n")); +- fprintf (file, _(" copyright: %.*s\n"), +- (int)(rec_len - sizeof (struct vms_emh_common)), +- (char *)rec + sizeof (struct vms_emh_common)); +- } ++ fprintf (file, _("Copyright Header\n")); ++ fprintf (file, _(" copyright: %.*s\n"), extra, (char *)(emh + 1)); + break; ++ + default: + fprintf (file, _("unhandled emh subtype %u\n"), subtype); + break; +diff --git a/bfd/vms-misc.c b/bfd/vms-misc.c +index 7497f02..91e2ec7 100644 +--- a/bfd/vms-misc.c ++++ b/bfd/vms-misc.c +@@ -135,8 +135,8 @@ _bfd_hexdump (int level, unsigned char *ptr, int size, int offset) + #endif + + +-/* Copy sized string (string with fixed size) to new allocated area +- size is string size (size of record) */ ++/* Copy sized string (string with fixed size) to new allocated area. ++ Size is string size (size of record). */ + + char * + _bfd_vms_save_sized_string (unsigned char *str, unsigned int size) +@@ -151,8 +151,8 @@ _bfd_vms_save_sized_string (unsigned char *str, unsigned int size) + return newstr; + } + +-/* Copy counted string (string with size at first byte) to new allocated area +- ptr points to size byte on entry */ ++/* Copy counted string (string with size at first byte) to new allocated area. ++ PTR points to size byte on entry. */ + + char * + _bfd_vms_save_counted_string (unsigned char *ptr, unsigned int maxlen) +-- +2.9.3 + diff --git a/SPECS/binutils/CVE-2017-12450.patch b/SPECS/binutils/CVE-2017-12450.patch new file mode 100644 index 0000000000..be644b595b --- /dev/null +++ b/SPECS/binutils/CVE-2017-12450.patch @@ -0,0 +1,29 @@ +From 8a2df5e2df374289e00ecd8f099eb46d76ef982e Mon Sep 17 00:00:00 2001 +From: Nick Clifton +Date: Mon, 24 Jul 2017 14:04:04 +0100 +Subject: [PATCH] Fix another memory access error triggered by attempting to + parse a corrupt binary. + + PR 21813 + (alpha_vms_object_p): Check for a truncated record. +--- + bfd/vms-alpha.c | 3 +++ + 2 files changed, 5 insertions(+) + +diff --git a/bfd/vms-alpha.c b/bfd/vms-alpha.c +index 5e9170d..610b034 100644 +--- a/bfd/vms-alpha.c ++++ b/bfd/vms-alpha.c +@@ -2679,6 +2679,9 @@ alpha_vms_object_p (bfd *abfd) + 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); +-- +2.9.3 + diff --git a/SPECS/binutils/CVE-2017-12451.patch b/SPECS/binutils/CVE-2017-12451.patch new file mode 100644 index 0000000000..7a75cc5527 --- /dev/null +++ b/SPECS/binutils/CVE-2017-12451.patch @@ -0,0 +1,289 @@ +From 29866fa186ee3ebda5242221607dba360b2e541e Mon Sep 17 00:00:00 2001 +From: Nick Clifton +Date: Wed, 19 Jul 2017 11:07:43 +0100 +Subject: [PATCH] Fix address violation when attempting to read a corrupt field + in a COFF archive header structure. + + PR 21786 + * coff-rs6000.c (_bfd_strntol): New function. + (_bfd_strntoll): New function. + (GET_VALUE_IN_FIELD): New macro. + (EQ_VALUE_IN_FIELD): new macro. + (_bfd_xcoff_slurp_armap): Use new macros. + (_bfd_xcoff_archive_p): Likewise. + (_bfd_xcoff_read_ar_hdr): Likewise. + (_bfd_xcoff_openr_next_archived_file): Likewise. + (_bfd_xcoff_stat_arch_elt): Likewise. +--- + bfd/coff-rs6000.c | 126 ++++++++++++++++++++++++++++++++---------------------- + 2 files changed, 89 insertions(+), 50 deletions(-) + +diff --git a/bfd/coff-rs6000.c b/bfd/coff-rs6000.c +index 025c424..c72d0db 100644 +--- a/bfd/coff-rs6000.c ++++ b/bfd/coff-rs6000.c +@@ -203,7 +203,8 @@ bfd_boolean (*xcoff_complain_overflow[XCOFF_MAX_COMPLAIN_OVERFLOW]) + }; + + /* Information about one member of an archive. */ +-struct member_layout { ++struct member_layout ++{ + /* The archive member that this structure describes. */ + bfd *member; + +@@ -237,7 +238,8 @@ struct member_layout { + }; + + /* A structure used for iterating over the members of an archive. */ +-struct archive_iterator { ++struct archive_iterator ++{ + /* The archive itself. */ + bfd *archive; + +@@ -654,8 +656,6 @@ _bfd_xcoff_swap_aux_out (bfd *abfd, void * inp, int type, int in_class, + end: + return bfd_coff_auxesz (abfd); + } +- +- + + /* The XCOFF reloc table. Actually, XCOFF relocations specify the + bitsize and whether they are signed or not, along with a +@@ -663,7 +663,6 @@ end: + different algorithms for putting in the reloc. Many of these + relocs need special_function entries, which I have not written. */ + +- + reloc_howto_type xcoff_howto_table[] = + { + /* 0x00: Standard 32 bit relocation. */ +@@ -1185,6 +1184,51 @@ bfd_xcoff_ar_archive_set_magic (bfd *abfd ATTRIBUTE_UNUSED, + /* bfd_xcoff_archive_set_magic (abfd, magic); */ + } + ++/* PR 21786: The PE/COFF standard does not require NUL termination for any of ++ the ASCII fields in the archive headers. So in order to be able to extract ++ numerical values we provide our own versions of strtol and strtoll which ++ take a maximum length as an additional parameter. Also - just to save space, ++ we omit the endptr return parameter, since we know that it is never used. */ ++ ++static long ++_bfd_strntol (const char * nptr, int base, unsigned int maxlen) ++{ ++ char buf[24]; /* Should be enough. */ ++ ++ BFD_ASSERT (maxlen < (sizeof (buf) - 1)); ++ ++ memcpy (buf, nptr, maxlen); ++ buf[maxlen] = 0; ++ return strtol (buf, NULL, base); ++} ++ ++static long long ++_bfd_strntoll (const char * nptr, int base, unsigned int maxlen) ++{ ++ char buf[32]; /* Should be enough. */ ++ ++ BFD_ASSERT (maxlen < (sizeof (buf) - 1)); ++ ++ memcpy (buf, nptr, maxlen); ++ buf[maxlen] = 0; ++ return strtoll (buf, NULL, base); ++} ++ ++/* Macro to read an ASCII value stored in an archive header field. */ ++#define GET_VALUE_IN_FIELD(VAR, FIELD) \ ++ do \ ++ { \ ++ (VAR) = sizeof (VAR) > sizeof (long) \ ++ ? _bfd_strntoll (FIELD, 10, sizeof FIELD) \ ++ : _bfd_strntol (FIELD, 10, sizeof FIELD); \ ++ } \ ++ while (0) ++ ++#define EQ_VALUE_IN_FIELD(VAR, FIELD) \ ++ (sizeof (VAR) > sizeof (long) \ ++ ? (VAR) ==_bfd_strntoll (FIELD, 10, sizeof FIELD) \ ++ : (VAR) == _bfd_strntol (FIELD, 10, sizeof FIELD)) ++ + /* Read in the armap of an XCOFF archive. */ + + bfd_boolean +@@ -1209,7 +1253,7 @@ _bfd_xcoff_slurp_armap (bfd *abfd) + /* This is for the old format. */ + struct xcoff_ar_hdr hdr; + +- off = strtol (xcoff_ardata (abfd)->symoff, (char **) NULL, 10); ++ GET_VALUE_IN_FIELD (off, xcoff_ardata (abfd)->symoff); + if (off == 0) + { + bfd_has_map (abfd) = FALSE; +@@ -1225,12 +1269,12 @@ _bfd_xcoff_slurp_armap (bfd *abfd) + return FALSE; + + /* Skip the name (normally empty). */ +- namlen = strtol (hdr.namlen, (char **) NULL, 10); ++ GET_VALUE_IN_FIELD (namlen, hdr.namlen); + off = ((namlen + 1) & ~ (size_t) 1) + SXCOFFARFMAG; + if (bfd_seek (abfd, off, SEEK_CUR) != 0) + return FALSE; + +- sz = strtol (hdr.size, (char **) NULL, 10); ++ GET_VALUE_IN_FIELD (sz, hdr.size); + + /* Read in the entire symbol table. */ + contents = (bfd_byte *) bfd_alloc (abfd, sz); +@@ -1264,7 +1308,7 @@ _bfd_xcoff_slurp_armap (bfd *abfd) + /* This is for the new format. */ + struct xcoff_ar_hdr_big hdr; + +- off = strtol (xcoff_ardata_big (abfd)->symoff, (char **) NULL, 10); ++ GET_VALUE_IN_FIELD (off, xcoff_ardata_big (abfd)->symoff); + if (off == 0) + { + bfd_has_map (abfd) = FALSE; +@@ -1280,15 +1324,12 @@ _bfd_xcoff_slurp_armap (bfd *abfd) + return FALSE; + + /* Skip the name (normally empty). */ +- namlen = strtol (hdr.namlen, (char **) NULL, 10); ++ GET_VALUE_IN_FIELD (namlen, hdr.namlen); + off = ((namlen + 1) & ~ (size_t) 1) + SXCOFFARFMAG; + if (bfd_seek (abfd, off, SEEK_CUR) != 0) + return FALSE; + +- /* XXX This actually has to be a call to strtoll (at least on 32-bit +- machines) since the field width is 20 and there numbers with more +- than 32 bits can be represented. */ +- sz = strtol (hdr.size, (char **) NULL, 10); ++ GET_VALUE_IN_FIELD (sz, hdr.size); + + /* Read in the entire symbol table. */ + contents = (bfd_byte *) bfd_alloc (abfd, sz); +@@ -1393,8 +1434,8 @@ _bfd_xcoff_archive_p (bfd *abfd) + goto error_ret; + } + +- bfd_ardata (abfd)->first_file_filepos = strtol (hdr.firstmemoff, +- (char **) NULL, 10); ++ GET_VALUE_IN_FIELD (bfd_ardata (abfd)->first_file_filepos, ++ hdr.firstmemoff); + + amt = SIZEOF_AR_FILE_HDR; + bfd_ardata (abfd)->tdata = bfd_zalloc (abfd, amt); +@@ -1469,7 +1510,7 @@ _bfd_xcoff_read_ar_hdr (bfd *abfd) + return NULL; + } + +- namlen = strtol (hdr.namlen, (char **) NULL, 10); ++ GET_VALUE_IN_FIELD (namlen, hdr.namlen); + amt = SIZEOF_AR_HDR + namlen + 1; + hdrp = (struct xcoff_ar_hdr *) bfd_alloc (abfd, amt); + if (hdrp == NULL) +@@ -1486,7 +1527,7 @@ _bfd_xcoff_read_ar_hdr (bfd *abfd) + ((char *) hdrp)[SIZEOF_AR_HDR + namlen] = '\0'; + + ret->arch_header = (char *) hdrp; +- ret->parsed_size = strtol (hdr.size, (char **) NULL, 10); ++ GET_VALUE_IN_FIELD (ret->parsed_size, hdr.size); + ret->filename = (char *) hdrp + SIZEOF_AR_HDR; + } + else +@@ -1501,7 +1542,7 @@ _bfd_xcoff_read_ar_hdr (bfd *abfd) + return NULL; + } + +- namlen = strtol (hdr.namlen, (char **) NULL, 10); ++ GET_VALUE_IN_FIELD (namlen, hdr.namlen); + amt = SIZEOF_AR_HDR_BIG + namlen + 1; + hdrp = (struct xcoff_ar_hdr_big *) bfd_alloc (abfd, amt); + if (hdrp == NULL) +@@ -1518,10 +1559,7 @@ _bfd_xcoff_read_ar_hdr (bfd *abfd) + ((char *) hdrp)[SIZEOF_AR_HDR_BIG + namlen] = '\0'; + + ret->arch_header = (char *) hdrp; +- /* XXX This actually has to be a call to strtoll (at least on 32-bit +- machines) since the field width is 20 and there numbers with more +- than 32 bits can be represented. */ +- ret->parsed_size = strtol (hdr.size, (char **) NULL, 10); ++ GET_VALUE_IN_FIELD (ret->parsed_size, hdr.size); + ret->filename = (char *) hdrp + SIZEOF_AR_HDR_BIG; + } + +@@ -1550,14 +1588,11 @@ _bfd_xcoff_openr_next_archived_file (bfd *archive, bfd *last_file) + if (last_file == NULL) + filestart = bfd_ardata (archive)->first_file_filepos; + else +- filestart = strtol (arch_xhdr (last_file)->nextoff, (char **) NULL, +- 10); ++ GET_VALUE_IN_FIELD (filestart, arch_xhdr (last_file)->nextoff); + + if (filestart == 0 +- || filestart == strtol (xcoff_ardata (archive)->memoff, +- (char **) NULL, 10) +- || filestart == strtol (xcoff_ardata (archive)->symoff, +- (char **) NULL, 10)) ++ || EQ_VALUE_IN_FIELD (filestart, xcoff_ardata (archive)->memoff) ++ || EQ_VALUE_IN_FIELD (filestart, xcoff_ardata (archive)->symoff)) + { + bfd_set_error (bfd_error_no_more_archived_files); + return NULL; +@@ -1568,20 +1603,11 @@ _bfd_xcoff_openr_next_archived_file (bfd *archive, bfd *last_file) + if (last_file == NULL) + filestart = bfd_ardata (archive)->first_file_filepos; + else +- /* XXX These actually have to be a calls to strtoll (at least +- on 32-bit machines) since the fields's width is 20 and +- there numbers with more than 32 bits can be represented. */ +- filestart = strtol (arch_xhdr_big (last_file)->nextoff, (char **) NULL, +- 10); +- +- /* XXX These actually have to be calls to strtoll (at least on 32-bit +- machines) since the fields's width is 20 and there numbers with more +- than 32 bits can be represented. */ ++ GET_VALUE_IN_FIELD (filestart, arch_xhdr_big (last_file)->nextoff); ++ + if (filestart == 0 +- || filestart == strtol (xcoff_ardata_big (archive)->memoff, +- (char **) NULL, 10) +- || filestart == strtol (xcoff_ardata_big (archive)->symoff, +- (char **) NULL, 10)) ++ || EQ_VALUE_IN_FIELD (filestart, xcoff_ardata_big (archive)->memoff) ++ || EQ_VALUE_IN_FIELD (filestart, xcoff_ardata_big (archive)->symoff)) + { + bfd_set_error (bfd_error_no_more_archived_files); + return NULL; +@@ -1606,20 +1632,20 @@ _bfd_xcoff_stat_arch_elt (bfd *abfd, struct stat *s) + { + struct xcoff_ar_hdr *hdrp = arch_xhdr (abfd); + +- s->st_mtime = strtol (hdrp->date, (char **) NULL, 10); +- s->st_uid = strtol (hdrp->uid, (char **) NULL, 10); +- s->st_gid = strtol (hdrp->gid, (char **) NULL, 10); +- s->st_mode = strtol (hdrp->mode, (char **) NULL, 8); ++ GET_VALUE_IN_FIELD (s->st_mtime, hdrp->date); ++ GET_VALUE_IN_FIELD (s->st_uid, hdrp->uid); ++ GET_VALUE_IN_FIELD (s->st_gid, hdrp->gid); ++ GET_VALUE_IN_FIELD (s->st_mode, hdrp->mode); + s->st_size = arch_eltdata (abfd)->parsed_size; + } + else + { + struct xcoff_ar_hdr_big *hdrp = arch_xhdr_big (abfd); + +- s->st_mtime = strtol (hdrp->date, (char **) NULL, 10); +- s->st_uid = strtol (hdrp->uid, (char **) NULL, 10); +- s->st_gid = strtol (hdrp->gid, (char **) NULL, 10); +- s->st_mode = strtol (hdrp->mode, (char **) NULL, 8); ++ GET_VALUE_IN_FIELD (s->st_mtime, hdrp->date); ++ GET_VALUE_IN_FIELD (s->st_uid, hdrp->uid); ++ GET_VALUE_IN_FIELD (s->st_gid, hdrp->gid); ++ GET_VALUE_IN_FIELD (s->st_mode, hdrp->mode); + s->st_size = arch_eltdata (abfd)->parsed_size; + } + +-- +2.9.3 + diff --git a/SPECS/binutils/CVE-2017-12452_12453_12454_12456.patch b/SPECS/binutils/CVE-2017-12452_12453_12454_12456.patch new file mode 100644 index 0000000000..a63d9ea745 --- /dev/null +++ b/SPECS/binutils/CVE-2017-12452_12453_12454_12456.patch @@ -0,0 +1,319 @@ +From ca4cf9b9c622a5695e01f7f5815a7382a31fcf51 Mon Sep 17 00:00:00 2001 +From: Nick Clifton +Date: Mon, 24 Jul 2017 13:49:22 +0100 +Subject: [PATCH 1/1] 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. +--- + bfd/mach-o-aarch64.c | 8 ++++--- + bfd/mach-o-arm.c | 13 ++++++++---- + bfd/mach-o-i386.c | 17 +++++++++------ + bfd/mach-o-x86-64.c | 8 ++++--- + bfd/mach-o.c | 2 +- + bfd/mach-o.h | 2 +- + bfd/vms-alpha.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++----- + binutils/rddbg.c | 3 ++- + 10 files changed, 118 insertions(+), 24 deletions(-) + +diff --git a/bfd/mach-o-aarch64.c b/bfd/mach-o-aarch64.c +index 12fc47e..5cf3364 100644 +--- a/bfd/mach-o-aarch64.c ++++ b/bfd/mach-o-aarch64.c +@@ -147,9 +147,11 @@ static reloc_howto_type arm64_howto_table[]= + }; + + 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; + +diff --git a/bfd/mach-o-arm.c b/bfd/mach-o-arm.c +index 5139f79..9eb614c 100644 +--- a/bfd/mach-o-arm.c ++++ b/bfd/mach-o-arm.c +@@ -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 reloc_howto_type arm_howto_table[]= + }; + + 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 @@ bfd_mach_o_arm_canonicalize_one_reloc (bfd *abfd, + 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]; +diff --git a/bfd/mach-o-i386.c b/bfd/mach-o-i386.c +index ce0389e..803af98 100644 +--- a/bfd/mach-o-i386.c ++++ b/bfd/mach-o-i386.c +@@ -112,9 +112,11 @@ static reloc_howto_type i386_howto_table[]= + }; + + 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 @@ bfd_mach_o_i386_canonicalize_one_reloc (bfd *abfd, + 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 @@ const mach_o_segment_name_xlat mach_o_i386_segsec_names_xlat[] = + { 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 +diff --git a/bfd/mach-o-x86-64.c b/bfd/mach-o-x86-64.c +index 1c83b10..2c50476 100644 +--- a/bfd/mach-o-x86-64.c ++++ b/bfd/mach-o-x86-64.c +@@ -120,9 +120,11 @@ static reloc_howto_type x86_64_howto_table[]= + }; + + 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; + +diff --git a/bfd/mach-o.c b/bfd/mach-o.c +index be2fb17..1807391 100644 +--- a/bfd/mach-o.c ++++ b/bfd/mach-o.c +@@ -1496,7 +1496,7 @@ bfd_mach_o_canonicalize_relocs (bfd *abfd, unsigned long filepos, + 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); +diff --git a/bfd/mach-o.h b/bfd/mach-o.h +index 83660a4..0719b53 100644 +--- a/bfd/mach-o.h ++++ b/bfd/mach-o.h +@@ -746,7 +746,7 @@ typedef struct bfd_mach_o_backend_data + 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 *); +diff --git a/bfd/vms-alpha.c b/bfd/vms-alpha.c +index 991a1be..5e9170d 100644 +--- a/bfd/vms-alpha.c ++++ b/bfd/vms-alpha.c +@@ -473,6 +473,14 @@ _bfd_vms_slurp_eihd (bfd *abfd, unsigned int *eisd_offset, + + 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); + +@@ -1312,19 +1320,38 @@ _bfd_vms_slurp_egsd (bfd *abfd) + 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]; + } + } + } +@@ -1351,9 +1378,20 @@ _bfd_vms_slurp_egsd (bfd *abfd) + + 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; +@@ -1446,6 +1484,9 @@ image_set_ptr (bfd *abfd, bfd_vma vma, int sect, struct bfd_link_info *info) + + if (PRIV (sections) == NULL) + return; ++ if (sect < 0 || sect >= (int) PRIV (section_count)) ++ return; ++ + sec = PRIV (sections)[sect]; + + if (info) +@@ -2450,6 +2491,14 @@ _bfd_vms_slurp_eeom (bfd *abfd) + + 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) +@@ -5173,7 +5222,7 @@ alpha_vms_slurp_relocs (bfd *abfd) + } + 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; +diff --git a/binutils/rddbg.c b/binutils/rddbg.c +index 1d8c447..b978060 100644 +--- a/binutils/rddbg.c ++++ b/binutils/rddbg.c +@@ -303,7 +303,8 @@ read_symbol_stabs_debugging_info (bfd *abfd, asymbol **syms, long symcount, + return FALSE; + f = NULL; + +- while (s[strlen (s) - 1] == '\\' ++ while (strlen (s) > 0 ++ && s[strlen (s) - 1] == '\\' + && ps + 1 < symend) + { + char *sc, *n; +-- +2.9.3 + diff --git a/SPECS/binutils/binutils.spec b/SPECS/binutils/binutils.spec index bced222a79..8151e60a8d 100644 --- a/SPECS/binutils/binutils.spec +++ b/SPECS/binutils/binutils.spec @@ -1,7 +1,7 @@ Summary: Contains a linker, an assembler, and other tools Name: binutils Version: 2.29 -Release: 2%{?dist} +Release: 3%{?dist} License: GPLv2+ URL: http://www.gnu.org/software/binutils Group: System Environment/Base @@ -11,6 +11,12 @@ Source0: http://ftp.gnu.org/gnu/binutils/%{name}-%{version}.tar.xz %define sha1 binutils=47817089b3867baf307365004c51677174a27000 Patch0: check-elf-section-header-only-for-elf-output.patch Patch1: elf-checks-for-orphan-placement.patch +Patch2: CVE-2017-12448.patch +Patch3: CVE-2017-12449_12455_12457_12458_12459.patch +Patch4: CVE-2017-12450.patch +Patch5: CVE-2017-12451.patch +Patch6: CVE-2017-12452_12453_12454_12456.patch + %description The Binutils package contains a linker, an assembler, and other tools for handling object files. @@ -24,6 +30,11 @@ for handling compiled objects. %setup -q %patch0 -p1 %patch1 -p1 +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 +%patch6 -p1 %build install -vdm 755 ../binutils-build cd ../binutils-build @@ -192,6 +203,10 @@ make %{?_smp_mflags} check %{_libdir}/libopcodes.so %changelog +* Fri Aug 11 2017 Anish Swaminathan 2.29-3 +- Apply patches for CVE-2017-12448,CVE-2017-12449,CVE-2017-12450,CVE-2017-12451, +- CVE-2017-12452,CVE-2017-12453,CVE-2017-12454,CVE-2017-12455,CVE-2017-12456, +- CVE-2017-12457,CVE-2017-12458,CVE-2017-12459 * Tue Aug 8 2017 Rongrong Qiu 2.29-2 - fix for make check for bug 1900247 * Wed Aug 2 2017 Alexey Makhalov 2.29-1