From df4986e3dcbdd968465ece48b25fedb757aad6cac8184f0bd0ca33a74ab0bac6 Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Fri, 26 Aug 2022 13:26:14 +0000 Subject: [PATCH 01/10] - Add binutils-pr29482.diff for PR29482, aka CVE-2022-38533 [bsc#1202816] OBS-URL: https://build.opensuse.org/package/show/devel:gcc/binutils?expand=0&rev=417 --- binutils-pr29482.diff | 33 +++++++++++++++++++++++++++++++++ binutils.changes | 6 ++++++ binutils.spec | 2 ++ 3 files changed, 41 insertions(+) create mode 100644 binutils-pr29482.diff diff --git a/binutils-pr29482.diff b/binutils-pr29482.diff new file mode 100644 index 0000000..49cafb6 --- /dev/null +++ b/binutils-pr29482.diff @@ -0,0 +1,33 @@ +PR29482 aka CVE-2022-38533 + +From ef186fe54aa6d281a3ff8a9528417e5cc614c797 Mon Sep 17 00:00:00 2001 +From: Alan Modra +Date: Sat, 13 Aug 2022 15:32:47 +0930 +Subject: [PATCH 1/1] PR29482 - strip: heap-buffer-overflow + + PR 29482 + * coffcode.h (coff_set_section_contents): Sanity check _LIB. +--- + bfd/coffcode.h | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +Index: binutils-2.39/bfd/coffcode.h +=================================================================== +--- binutils-2.39.orig/bfd/coffcode.h 2022-07-08 11:46:47.000000000 +0200 ++++ binutils-2.39/bfd/coffcode.h 2022-08-26 15:23:58.749610670 +0200 +@@ -4284,10 +4284,13 @@ coff_set_section_contents (bfd * abfd, + + rec = (bfd_byte *) location; + recend = rec + count; +- while (rec < recend) ++ while (recend - rec >= 4) + { ++ size_t len = bfd_get_32 (abfd, rec); ++ if (len == 0 || len > (size_t) (recend - rec) / 4) ++ break; ++ rec += len * 4; + ++section->lma; +- rec += bfd_get_32 (abfd, rec) * 4; + } + + BFD_ASSERT (rec == recend); diff --git a/binutils.changes b/binutils.changes index 4d7e66f..9c9a1e4 100644 --- a/binutils.changes +++ b/binutils.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Fri Aug 26 13:24:35 UTC 2022 - Michael Matz + +- Add binutils-pr29482.diff for PR29482, aka CVE-2022-38533 + [bsc#1202816] + ------------------------------------------------------------------- Wed Aug 10 09:04:57 UTC 2022 - Martin Liška diff --git a/binutils.spec b/binutils.spec index d894868..da0b4dc 100644 --- a/binutils.spec +++ b/binutils.spec @@ -138,6 +138,7 @@ Patch40: binutils-fix-abierrormsg.diff Patch41: binutils-fix-relax.diff Patch42: binutils-compat-old-behaviour.diff Patch43: binutils-revert-hlasm-insns.diff +Patch44: binutils-pr29482.diff Patch100: add-ulp-section.diff Patch90: cross-avr-nesc-as.patch Patch92: cross-avr-omit_section_dynsym.patch @@ -260,6 +261,7 @@ cp ld/ldgram.y ld/ldgram.y.orig %patch42 -p1 %patch43 -p1 %endif +%patch44 -p1 %patch100 -p1 %if "%{TARGET}" == "avr" cp gas/config/tc-avr.h gas/config/tc-avr-nesc.h From 8d8118647ce7e276202de70d0e1baeed9a0ba306aced76c741c166b21a268ead Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Thu, 1 Sep 2022 11:54:53 +0000 Subject: [PATCH 02/10] - Add binutils-pr29370.diff and their prerequisites binutils-pr29370-pre1.diff and binutils-pr29370-pre2.diff for PR29370, aka CVE-2022-38128 [bsc#1203016] OBS-URL: https://build.opensuse.org/package/show/devel:gcc/binutils?expand=0&rev=418 --- binutils-pr29370-pre1.diff | 532 +++++++++++++++++++++++++++++++++++++ binutils-pr29370-pre2.diff | 349 ++++++++++++++++++++++++ binutils-pr29370.diff | 96 +++++++ binutils.changes | 7 + binutils.spec | 6 + 5 files changed, 990 insertions(+) create mode 100644 binutils-pr29370-pre1.diff create mode 100644 binutils-pr29370-pre2.diff create mode 100644 binutils-pr29370.diff diff --git a/binutils-pr29370-pre1.diff b/binutils-pr29370-pre1.diff new file mode 100644 index 0000000..2dfc713 --- /dev/null +++ b/binutils-pr29370-pre1.diff @@ -0,0 +1,532 @@ +From 175b91507b83ad42607d2f6dadaf55b7b511bdbe Mon Sep 17 00:00:00 2001 +From: Alan Modra +Date: Wed, 20 Jul 2022 18:28:50 +0930 +Subject: [PATCH] miscellaneous dwarf.c tidies + + * dwarf.c: Leading and trailing whitespace fixes. + (free_abbrev_list): New function. + (free_all_abbrevs): Use the above. Free cu_abbrev_map here too. + (process_abbrev_set): Print actual section name on error. + (get_type_abbrev_from_form): Add overflow check. + (free_debug_memory): Don't free cu_abbrev_map here.. + (process_debug_info): ..or here. Warn on another case of not + finding a neeeded abbrev. +--- + binutils/dwarf.c | 216 +++++++++++++++++++++++------------------------ + 1 file changed, 106 insertions(+), 110 deletions(-) + +Index: binutils-2.39/binutils/dwarf.c +=================================================================== +--- binutils-2.39.orig/binutils/dwarf.c 2022-09-01 13:51:14.818699924 +0200 ++++ binutils-2.39/binutils/dwarf.c 2022-09-01 13:51:32.090984628 +0200 +@@ -806,7 +806,7 @@ fetch_indexed_value (dwarf_vma idx, + pointer_size = 4; + bias = 12; + } +- ++ + dwarf_vma offset = idx * pointer_size; + + /* Offsets are biased by the size of the section header +@@ -901,38 +901,41 @@ record_abbrev_list_for_cu (dwarf_vma sta + next_free_abbrev_map_entry ++; + } + +-static void +-free_all_abbrevs (void) ++static abbrev_list * ++free_abbrev_list (abbrev_list *list) + { +- abbrev_list * list; ++ abbrev_entry *abbrv = list->first_abbrev; + +- for (list = abbrev_lists; list != NULL;) ++ while (abbrv) + { +- abbrev_list * next = list->next; +- abbrev_entry * abbrv; ++ abbrev_attr *attr = abbrv->first_attr; + +- for (abbrv = list->first_abbrev; abbrv != NULL;) ++ while (attr) + { +- abbrev_entry * next_abbrev = abbrv->next; +- abbrev_attr * attr; +- +- for (attr = abbrv->first_attr; attr;) +- { +- abbrev_attr *next_attr = attr->next; +- +- free (attr); +- attr = next_attr; +- } +- +- free (abbrv); +- abbrv = next_abbrev; ++ abbrev_attr *next_attr = attr->next; ++ free (attr); ++ attr = next_attr; + } + +- free (list); +- list = next; ++ abbrev_entry *next_abbrev = abbrv->next; ++ free (abbrv); ++ abbrv = next_abbrev; + } + +- abbrev_lists = NULL; ++ abbrev_list *next = list->next; ++ free (list); ++ return next; ++} ++ ++static void ++free_all_abbrevs (void) ++{ ++ while (abbrev_lists) ++ abbrev_lists = free_abbrev_list (abbrev_lists); ++ ++ free (cu_abbrev_map); ++ cu_abbrev_map = NULL; ++ next_free_abbrev_map_entry = 0; + } + + static abbrev_list * +@@ -978,7 +981,7 @@ find_abbrev_map_by_offset (dwarf_vma off + && cu_abbrev_map[i].end > offset) + return cu_abbrev_map + i; + +- return NULL; ++ return NULL; + } + + static void +@@ -1119,7 +1122,7 @@ process_abbrev_set (struct dwarf_section + } + + /* Report the missing single zero which ends the section. */ +- error (_(".debug_abbrev section not zero terminated\n")); ++ error (_("%s section not zero terminated\n"), section->name); + + return NULL; + } +@@ -1842,7 +1845,7 @@ fetch_alt_indirect_string (dwarf_vma off + dwarf_vmatoa ("x", offset)); + return _(""); + } +- ++ + static const char * + get_AT_name (unsigned long attribute) + { +@@ -2124,7 +2127,8 @@ get_type_abbrev_from_form (unsigned long + case DW_FORM_ref4: + case DW_FORM_ref8: + case DW_FORM_ref_udata: +- if (uvalue + cu_offset > (size_t) (cu_end - section->start)) ++ if (uvalue + cu_offset < uvalue ++ || uvalue + cu_offset > (size_t) (cu_end - section->start)) + { + warn (_("Unable to resolve ref form: uvalue %lx + cu_offset %lx > CU size %lx\n"), + uvalue, (long) cu_offset, (long) (cu_end - section->start)); +@@ -2161,7 +2165,7 @@ get_type_abbrev_from_form (unsigned long + else + *map_return = NULL; + } +- ++ + READ_ULEB (abbrev_number, data, section->start + section->size); + + for (entry = map->list->first_abbrev; entry != NULL; entry = entry->next) +@@ -2750,10 +2754,10 @@ read_and_display_attr_value (unsigned lo + if (form == DW_FORM_loclistx) + { + if (dwo) +- { +- index = fetch_indexed_value (uvalue, loclists_dwo, 0); +- index += (offset_size == 8) ? 20 : 12; +- } ++ { ++ index = fetch_indexed_value (uvalue, loclists_dwo, 0); ++ index += (offset_size == 8) ? 20 : 12; ++ } + else if (debug_info_p == NULL) + { + index = fetch_indexed_value (uvalue, loclists, 0); +@@ -2771,21 +2775,21 @@ read_and_display_attr_value (unsigned lo + else if (form == DW_FORM_rnglistx) + { + if (dwo) +- { +- index = fetch_indexed_value (uvalue, rnglists_dwo, 0); +- index += (offset_size == 8) ? 20 : 12; +- } ++ { ++ index = fetch_indexed_value (uvalue, rnglists_dwo, 0); ++ index += (offset_size == 8) ? 20 : 12; ++ } + else +- { +- if (debug_info_p == NULL) +- base = 0; +- else +- base = debug_info_p->rnglists_base; +- /* We do not have a cached value this time, so we perform the +- computation manually. */ +- index = fetch_indexed_value (uvalue, rnglists, base); +- index += base; +- } ++ { ++ if (debug_info_p == NULL) ++ base = 0; ++ else ++ base = debug_info_p->rnglists_base; ++ /* We do not have a cached value this time, so we perform the ++ computation manually. */ ++ index = fetch_indexed_value (uvalue, rnglists, base); ++ index += base; ++ } + } + else + { +@@ -2811,7 +2815,7 @@ read_and_display_attr_value (unsigned lo + if (!do_loc) + printf ("%c<0x%s>", delimiter, dwarf_vmatoa ("x", uvalue + cu_offset)); + break; +- ++ + default: + warn (_("Unrecognized form: 0x%lx\n"), form); + /* What to do? Consume a byte maybe? */ +@@ -2836,9 +2840,9 @@ read_and_display_attr_value (unsigned lo + case DW_AT_rnglists_base: + if (debug_info_p->rnglists_base) + warn (_("CU @ 0x%s has multiple rnglists_base values (0x%s and 0x%s)"), +- dwarf_vmatoa ("x", debug_info_p->cu_offset), +- dwarf_vmatoa ("x", debug_info_p->rnglists_base), +- dwarf_vmatoa ("x", uvalue)); ++ dwarf_vmatoa ("x", debug_info_p->cu_offset), ++ dwarf_vmatoa ("x", debug_info_p->rnglists_base), ++ dwarf_vmatoa ("x", uvalue)); + debug_info_p->rnglists_base = uvalue; + break; + case DW_AT_str_offsets_base: +@@ -2988,7 +2992,7 @@ read_and_display_attr_value (unsigned lo + case DW_FORM_strx3: + case DW_FORM_strx4: + add_dwo_name (fetch_indexed_string (uvalue, this_set, offset_size, false, +- debug_info_p->str_offsets_base), ++ debug_info_p->str_offsets_base), + cu_offset); + break; + case DW_FORM_string: +@@ -3022,7 +3026,7 @@ read_and_display_attr_value (unsigned lo + case DW_FORM_strx3: + case DW_FORM_strx4: + add_dwo_dir (fetch_indexed_string (uvalue, this_set, offset_size, false, +- debug_info_p->str_offsets_base), ++ debug_info_p->str_offsets_base), + cu_offset); + break; + case DW_FORM_string: +@@ -3653,11 +3657,8 @@ process_debug_info (struct dwarf_section + introduce (section, false); + + free_all_abbrevs (); +- free (cu_abbrev_map); +- cu_abbrev_map = NULL; +- next_free_abbrev_map_entry = 0; + +- /* In order to be able to resolve DW_FORM_ref_attr forms we need ++ /* In order to be able to resolve DW_FORM_ref_addr forms we need + to load *all* of the abbrevs for all CUs in this .debug_info + section. This does effectively mean that we (partially) read + every CU header twice. */ +@@ -4028,12 +4029,11 @@ process_debug_info (struct dwarf_section + + /* Scan through the abbreviation list until we reach the + correct entry. */ +- if (list == NULL) +- continue; +- +- for (entry = list->first_abbrev; entry != NULL; entry = entry->next) +- if (entry->number == abbrev_number) +- break; ++ entry = NULL; ++ if (list != NULL) ++ for (entry = list->first_abbrev; entry != NULL; entry = entry->next) ++ if (entry->number == abbrev_number) ++ break; + + if (entry == NULL) + { +@@ -4057,7 +4057,7 @@ process_debug_info (struct dwarf_section + break; + case DW_TAG_compile_unit: + case DW_TAG_skeleton_unit: +- need_base_address = 1; ++ need_base_address = 1; + need_dwo_info = do_loc; + break; + case DW_TAG_entry_point: +@@ -4440,7 +4440,7 @@ display_debug_sup (struct dwarf_section + + SAFE_BYTE_GET_AND_INC (is_supplementary, start, 1, end); + if (is_supplementary != 0 && is_supplementary != 1) +- warn (_("corrupt .debug_sup section: is_supplementary not 0 or 1\n")); ++ warn (_("corrupt .debug_sup section: is_supplementary not 0 or 1\n")); + + sup_filename = start; + if (is_supplementary && sup_filename[0] != 0) +@@ -5619,7 +5619,7 @@ display_debug_lines_decoded (struct dwar + printf ("%s %11d %#18" DWARF_VMA_FMT "x", + newFileName, state_machine_regs.line, + state_machine_regs.address); +- } ++ } + else + { + if (xop == -DW_LNE_end_sequence) +@@ -6073,7 +6073,7 @@ display_debug_macro (struct dwarf_sectio + load_debug_section_with_follow (str, file); + load_debug_section_with_follow (line, file); + load_debug_section_with_follow (str_index, file); +- ++ + introduce (section, false); + + while (curr < end) +@@ -6525,7 +6525,7 @@ display_loc_list (struct dwarf_section * + + /* Check base address specifiers. */ + if (is_max_address (begin, pointer_size) +- && !is_max_address (end, pointer_size)) ++ && !is_max_address (end, pointer_size)) + { + base_address = end; + print_dwarf_vma (begin, pointer_size); +@@ -6703,7 +6703,7 @@ display_loclists_list (struct dwarf_sect + case DW_LLE_default_location: + begin = end = 0; + break; +- ++ + case DW_LLE_offset_pair: + READ_ULEB (begin, start, section_end); + begin += base_address; +@@ -6999,7 +6999,7 @@ display_offset_entry_loclists (struct dw + unsigned char * start = section->start; + unsigned char * const end = start + section->size; + +- introduce (section, false); ++ introduce (section, false); + + do + { +@@ -7048,14 +7048,14 @@ display_offset_entry_loclists (struct dw + section->name, segment_selector_size); + return 0; + } +- ++ + if (offset_entry_count == 0) + { + warn (_("The %s section contains a table without offset\n"), + section->name); + return 0; + } +- ++ + printf (_("\n Offset Entries starting at 0x%lx:\n"), + (long)(start - section->start)); + +@@ -8217,7 +8217,7 @@ display_debug_rnglists (struct dwarf_sec + start = display_debug_rnglists_list + (start, end, address_size, offset, 0, offset_size); + if (start >= end) +- break; ++ break; + } + + start = end; +@@ -8335,12 +8335,12 @@ display_debug_ranges (struct dwarf_secti + next = section_begin + offset + debug_info_p->rnglists_base; + + /* If multiple DWARF entities reference the same range then we will +- have multiple entries in the `range_entries' list for the same +- offset. Thanks to the sort above these will all be consecutive in +- the `range_entries' list, so we can easily ignore duplicates +- here. */ ++ have multiple entries in the `range_entries' list for the same ++ offset. Thanks to the sort above these will all be consecutive in ++ the `range_entries' list, so we can easily ignore duplicates ++ here. */ + if (i > 0 && last_offset == offset) +- continue; ++ continue; + last_offset = offset; + + if (dwarf_check != 0 && i > 0) +@@ -10274,7 +10274,7 @@ display_debug_names (struct dwarf_sectio + printf (_("Out of %lu items there are %zu bucket clashes" + " (longest of %zu entries).\n"), + (unsigned long) name_count, hash_clash_count, longest_clash); +- ++ + if (name_count != buckets_filled + hash_clash_count) + warn (_("The name_count (%lu) is not the same as the used bucket_count (%lu) + the hash clash count (%lu)"), + (unsigned long) name_count, +@@ -10378,7 +10378,7 @@ display_debug_names (struct dwarf_sectio + break; + if (tagno >= 0) + printf ("%s<%lu>", +- (tagno == 0 && second_abbrev_tag == 0 ? " " : "\n\t"), ++ (tagno == 0 && second_abbrev_tag == 0 ? " " : "\n\t"), + (unsigned long) abbrev_tag); + + for (entry = abbrev_lookup; +@@ -10907,7 +10907,7 @@ process_cu_tu_index (struct dwarf_sectio + Check for integer overflow (can occur when size_t is 32-bit) + with overlarge ncols or nused values. */ + if (nused == -1u +- || _mul_overflow ((size_t) ncols, 4, &temp) ++ || _mul_overflow ((size_t) ncols, 4, &temp) + || _mul_overflow ((size_t) nused + 1, temp, &total) + || total > (size_t) (limit - ppool)) + { +@@ -10915,7 +10915,7 @@ process_cu_tu_index (struct dwarf_sectio + section->name); + return 0; + } +- ++ + if (do_display) + { + printf (_(" Offset table\n")); +@@ -11419,8 +11419,8 @@ add_separate_debug_file (const char * fi + + static bool + debuginfod_fetch_separate_debug_info (struct dwarf_section * section, +- char ** filename, +- void * file) ++ char ** filename, ++ void * file) + { + size_t build_id_len; + unsigned char * build_id; +@@ -11438,14 +11438,14 @@ debuginfod_fetch_separate_debug_info (st + + filelen = strnlen ((const char *)section->start, section->size); + if (filelen == section->size) +- /* Corrupt debugaltlink. */ +- return false; ++ /* Corrupt debugaltlink. */ ++ return false; + + build_id = section->start + filelen + 1; + build_id_len = section->size - (filelen + 1); + + if (build_id_len == 0) +- return false; ++ return false; + } + else + return false; +@@ -11457,25 +11457,25 @@ debuginfod_fetch_separate_debug_info (st + + client = debuginfod_begin (); + if (client == NULL) +- return false; ++ return false; + + /* Query debuginfod servers for the target file. If found its path +- will be stored in filename. */ ++ will be stored in filename. */ + fd = debuginfod_find_debuginfo (client, build_id, build_id_len, filename); + debuginfod_end (client); + + /* Only free build_id if we allocated space for a hex string +- in get_build_id (). */ ++ in get_build_id (). */ + if (build_id_len == 0) +- free (build_id); ++ free (build_id); + + if (fd >= 0) +- { +- /* File successfully retrieved. Close fd since we want to +- use open_debug_file () on filename instead. */ +- close (fd); +- return true; +- } ++ { ++ /* File successfully retrieved. Close fd since we want to ++ use open_debug_file () on filename instead. */ ++ close (fd); ++ return true; ++ } + } + + return false; +@@ -11488,7 +11488,7 @@ load_separate_debug_info (const char * + parse_func_type parse_func, + check_func_type check_func, + void * func_data, +- void * file ATTRIBUTE_UNUSED) ++ void * file ATTRIBUTE_UNUSED) + { + const char * separate_filename; + char * debug_filename; +@@ -11604,11 +11604,11 @@ load_separate_debug_info (const char * + & tmp_filename, + file)) + { +- /* File successfully downloaded from server, replace +- debug_filename with the file's path. */ +- free (debug_filename); +- debug_filename = tmp_filename; +- goto found; ++ /* File successfully downloaded from server, replace ++ debug_filename with the file's path. */ ++ free (debug_filename); ++ debug_filename = tmp_filename; ++ goto found; + } + } + #endif +@@ -11775,12 +11775,12 @@ load_build_id_debug_file (const char * m + /* In theory we should extract the contents of the section into + a note structure and then check the fields. For now though + just use hard coded offsets instead: +- ++ + Field Bytes Contents + NSize 0...3 4 + DSize 4...7 8+ + Type 8..11 3 (NT_GNU_BUILD_ID) +- Name 12.15 GNU\0 ++ Name 12.15 GNU\0 + Data 16.... */ + + /* FIXME: Check the name size, name and type fields. */ +@@ -11792,7 +11792,7 @@ load_build_id_debug_file (const char * m + warn (_(".note.gnu.build-id data size is too small\n")); + return; + } +- ++ + if (build_id_size > (section->size - 16)) + { + warn (_(".note.gnu.build-id data size is too bug\n")); +@@ -12088,10 +12088,6 @@ free_debug_memory (void) + + free_all_abbrevs (); + +- free (cu_abbrev_map); +- cu_abbrev_map = NULL; +- next_free_abbrev_map_entry = 0; +- + free (shndx_pool); + shndx_pool = NULL; + shndx_pool_size = 0; diff --git a/binutils-pr29370-pre2.diff b/binutils-pr29370-pre2.diff new file mode 100644 index 0000000..be87ba8 --- /dev/null +++ b/binutils-pr29370-pre2.diff @@ -0,0 +1,349 @@ +From f07c08e115e27cddf5a0030dc6332bbee1bd9c6a Mon Sep 17 00:00:00 2001 +From: Alan Modra +Date: Thu, 21 Jul 2022 08:38:14 +0930 +Subject: [PATCH] binutils/dwarf.c: abbrev caching + +I'm inclined to think that abbrev caching is counter-productive. The +time taken to search the list of abbrevs converted to internal form is +non-zero, and it's easy to decode the raw abbrevs. It's especially +silly to cache empty lists of decoded abbrevs (happens with zero +padding in .debug_abbrev), or abbrevs as they are displayed when there +is no further use of those abbrevs. This patch stops caching in those +cases. + + * dwarf.c (record_abbrev_list_for_cu): Add free_list param. + Put abbrevs on abbrev_lists here. + (new_abbrev_list): Delete function. + (process_abbrev_set): Return newly allocated list. Move + abbrev base, offset and size checking to.. + (find_and_process_abbrev_set): ..here, new function. Handle + lookup of cached abbrevs here, and calculate start and end + for process_abbrev_set. Return free_list if newly alloc'd. + (process_debug_info): Consolidate cached list lookup, new list + alloc and processing into find_and_process_abbrev_set call. + Free list when not cached. + (display_debug_abbrev): Similarly. +--- + binutils/dwarf.c | 208 +++++++++++++++++++++++++---------------------- + 1 file changed, 110 insertions(+), 98 deletions(-) + +diff --git a/binutils/dwarf.c b/binutils/dwarf.c +index 267ed3bb382..2fc352f74c5 100644 +--- a/binutils/dwarf.c ++++ b/binutils/dwarf.c +@@ -882,8 +882,15 @@ static unsigned long next_free_abbrev_map_entry = 0; + #define ABBREV_MAP_ENTRIES_INCREMENT 8 + + static void +-record_abbrev_list_for_cu (dwarf_vma start, dwarf_vma end, abbrev_list * list) ++record_abbrev_list_for_cu (dwarf_vma start, dwarf_vma end, ++ abbrev_list *list, abbrev_list *free_list) + { ++ if (free_list != NULL) ++ { ++ list->next = abbrev_lists; ++ abbrev_lists = list; ++ } ++ + if (cu_abbrev_map == NULL) + { + num_abbrev_map_entries = INITIAL_NUM_ABBREV_MAP_ENTRIES; +@@ -938,20 +945,6 @@ free_all_abbrevs (void) + next_free_abbrev_map_entry = 0; + } + +-static abbrev_list * +-new_abbrev_list (dwarf_vma abbrev_base, dwarf_vma abbrev_offset) +-{ +- abbrev_list * list = (abbrev_list *) xcalloc (sizeof * list, 1); +- +- list->abbrev_base = abbrev_base; +- list->abbrev_offset = abbrev_offset; +- +- list->next = abbrev_lists; +- abbrev_lists = list; +- +- return list; +-} +- + static abbrev_list * + find_abbrev_list_by_abbrev_offset (dwarf_vma abbrev_base, + dwarf_vma abbrev_offset) +@@ -969,7 +962,7 @@ find_abbrev_list_by_abbrev_offset (dwarf_vma abbrev_base, + /* Find the abbreviation map for the CU that includes OFFSET. + OFFSET is an absolute offset from the start of the .debug_info section. */ + /* FIXME: This function is going to slow down readelf & objdump. +- Consider using a better algorithm to mitigate this effect. */ ++ Not caching abbrevs is likely the answer. */ + + static abbrev_map * + find_abbrev_map_by_offset (dwarf_vma offset) +@@ -1036,40 +1029,18 @@ add_abbrev_attr (unsigned long attribute, + list->last_abbrev->last_attr = attr; + } + +-/* Processes the (partial) contents of a .debug_abbrev section. +- Returns NULL if the end of the section was encountered. +- Returns the address after the last byte read if the end of +- an abbreviation set was found. */ ++/* Return processed (partial) contents of a .debug_abbrev section. ++ Returns NULL on errors. */ + +-static unsigned char * ++static abbrev_list * + process_abbrev_set (struct dwarf_section *section, +- dwarf_vma abbrev_base, +- dwarf_vma abbrev_size, +- dwarf_vma abbrev_offset, +- abbrev_list *list) ++ unsigned char *start, ++ unsigned char *end) + { +- if (abbrev_base >= section->size +- || abbrev_size > section->size - abbrev_base) +- { +- /* PR 17531: file:4bcd9ce9. */ +- warn (_("Debug info is corrupted, abbrev size (%lx) is larger than " +- "abbrev section size (%lx)\n"), +- (unsigned long) (abbrev_base + abbrev_size), +- (unsigned long) section->size); +- return NULL; +- } +- if (abbrev_offset >= abbrev_size) +- { +- warn (_("Debug info is corrupted, abbrev offset (%lx) is larger than " +- "abbrev section size (%lx)\n"), +- (unsigned long) abbrev_offset, +- (unsigned long) abbrev_size); +- return NULL; +- } ++ abbrev_list *list = xmalloc (sizeof (*list)); ++ list->first_abbrev = NULL; ++ list->last_abbrev = NULL; + +- unsigned char *start = section->start + abbrev_base; +- unsigned char *end = start + abbrev_size; +- start += abbrev_offset; + while (start < end) + { + unsigned long entry; +@@ -1082,14 +1053,18 @@ process_abbrev_set (struct dwarf_section *section, + /* A single zero is supposed to end the set according + to the standard. If there's more, then signal that to + the caller. */ +- if (start == end) +- return NULL; +- if (entry == 0) +- return start; ++ if (start == end || entry == 0) ++ { ++ list->start_of_next_abbrevs = start != end ? start : NULL; ++ return list; ++ } + + READ_ULEB (tag, start, end); + if (start == end) +- return NULL; ++ { ++ free (list); ++ return NULL; ++ } + + children = *start++; + +@@ -1124,9 +1099,67 @@ process_abbrev_set (struct dwarf_section *section, + /* Report the missing single zero which ends the section. */ + error (_("%s section not zero terminated\n"), section->name); + ++ free (list); + return NULL; + } + ++/* Return a sequence of abbrevs in SECTION starting at ABBREV_BASE ++ plus ABBREV_OFFSET and finishing at ABBREV_BASE + ABBREV_SIZE. ++ If FREE_LIST is non-NULL search the already decoded abbrevs on ++ abbrev_lists first and if found set *FREE_LIST to NULL. If ++ searching doesn't find a matching abbrev, set *FREE_LIST to the ++ newly allocated list. If FREE_LIST is NULL, no search is done and ++ the returned abbrev_list is always newly allocated. */ ++ ++static abbrev_list * ++find_and_process_abbrev_set (struct dwarf_section *section, ++ dwarf_vma abbrev_base, ++ dwarf_vma abbrev_size, ++ dwarf_vma abbrev_offset, ++ abbrev_list **free_list) ++{ ++ if (free_list) ++ *free_list = NULL; ++ ++ if (abbrev_base >= section->size ++ || abbrev_size > section->size - abbrev_base) ++ { ++ /* PR 17531: file:4bcd9ce9. */ ++ warn (_("Debug info is corrupted, abbrev size (%lx) is larger than " ++ "abbrev section size (%lx)\n"), ++ (unsigned long) (abbrev_base + abbrev_size), ++ (unsigned long) section->size); ++ return NULL; ++ } ++ if (abbrev_offset >= abbrev_size) ++ { ++ warn (_("Debug info is corrupted, abbrev offset (%lx) is larger than " ++ "abbrev section size (%lx)\n"), ++ (unsigned long) abbrev_offset, ++ (unsigned long) abbrev_size); ++ return NULL; ++ } ++ ++ unsigned char *start = section->start + abbrev_base + abbrev_offset; ++ unsigned char *end = section->start + abbrev_base + abbrev_size; ++ abbrev_list *list = NULL; ++ if (free_list) ++ list = find_abbrev_list_by_abbrev_offset (abbrev_base, abbrev_offset); ++ if (list == NULL) ++ { ++ list = process_abbrev_set (section, start, end); ++ if (list) ++ { ++ list->abbrev_base = abbrev_base; ++ list->abbrev_offset = abbrev_offset; ++ list->next = NULL; ++ } ++ if (free_list) ++ *free_list = list; ++ } ++ return list; ++} ++ + static const char * + get_TAG_name (unsigned long tag) + { +@@ -3671,7 +3704,6 @@ process_debug_info (struct dwarf_section * section, + dwarf_vma cu_offset; + unsigned int offset_size; + struct cu_tu_set * this_set; +- abbrev_list * list; + unsigned char *end_cu; + + hdrptr = start; +@@ -3727,22 +3759,18 @@ process_debug_info (struct dwarf_section * section, + abbrev_size = this_set->section_sizes [DW_SECT_ABBREV]; + } + +- list = find_abbrev_list_by_abbrev_offset (abbrev_base, +- compunit.cu_abbrev_offset); +- if (list == NULL) +- { +- unsigned char * next; +- +- list = new_abbrev_list (abbrev_base, +- compunit.cu_abbrev_offset); +- next = process_abbrev_set (&debug_displays[abbrev_sec].section, +- abbrev_base, abbrev_size, +- compunit.cu_abbrev_offset, list); +- list->start_of_next_abbrevs = next; +- } +- ++ abbrev_list *list; ++ abbrev_list *free_list; ++ list = find_and_process_abbrev_set (&debug_displays[abbrev_sec].section, ++ abbrev_base, abbrev_size, ++ compunit.cu_abbrev_offset, ++ &free_list); + start = end_cu; +- record_abbrev_list_for_cu (cu_offset, start - section_begin, list); ++ if (list != NULL && list->first_abbrev != NULL) ++ record_abbrev_list_for_cu (cu_offset, start - section_begin, ++ list, free_list); ++ else if (free_list != NULL) ++ free_abbrev_list (free_list); + } + + for (start = section_begin, unit = 0; start < end; unit++) +@@ -3758,7 +3786,6 @@ process_debug_info (struct dwarf_section * section, + struct cu_tu_set *this_set; + dwarf_vma abbrev_base; + size_t abbrev_size; +- abbrev_list * list = NULL; + unsigned char *end_cu; + + hdrptr = start; +@@ -3937,20 +3964,10 @@ process_debug_info (struct dwarf_section * section, + } + + /* Process the abbrevs used by this compilation unit. */ +- list = find_abbrev_list_by_abbrev_offset (abbrev_base, +- compunit.cu_abbrev_offset); +- if (list == NULL) +- { +- unsigned char *next; +- +- list = new_abbrev_list (abbrev_base, +- compunit.cu_abbrev_offset); +- next = process_abbrev_set (&debug_displays[abbrev_sec].section, +- abbrev_base, abbrev_size, +- compunit.cu_abbrev_offset, list); +- list->start_of_next_abbrevs = next; +- } +- ++ abbrev_list *list; ++ list = find_and_process_abbrev_set (&debug_displays[abbrev_sec].section, ++ abbrev_base, abbrev_size, ++ compunit.cu_abbrev_offset, NULL); + level = 0; + last_level = level; + saved_level = -1; +@@ -4128,6 +4145,8 @@ process_debug_info (struct dwarf_section * section, + if (entry->children) + ++level; + } ++ if (list != NULL) ++ free_abbrev_list (list); + } + + /* Set num_debug_info_entries here so that it can be used to check if +@@ -6353,24 +6372,15 @@ display_debug_abbrev (struct dwarf_section *section, + + do + { +- abbrev_list * list; +- dwarf_vma offset; +- +- offset = start - section->start; +- list = find_abbrev_list_by_abbrev_offset (0, offset); ++ dwarf_vma offset = start - section->start; ++ abbrev_list *list = find_and_process_abbrev_set (section, 0, ++ section->size, offset, ++ NULL); + if (list == NULL) +- { +- list = new_abbrev_list (0, offset); +- start = process_abbrev_set (section, 0, section->size, offset, list); +- list->start_of_next_abbrevs = start; +- } +- else +- start = list->start_of_next_abbrevs; +- +- if (list->first_abbrev == NULL) +- continue; ++ break; + +- printf (_(" Number TAG (0x%lx)\n"), (long) offset); ++ if (list->first_abbrev) ++ printf (_(" Number TAG (0x%lx)\n"), (long) offset); + + for (entry = list->first_abbrev; entry; entry = entry->next) + { +@@ -6391,6 +6401,8 @@ display_debug_abbrev (struct dwarf_section *section, + putchar ('\n'); + } + } ++ start = list->start_of_next_abbrevs; ++ free_abbrev_list (list); + } + while (start); + +-- +2.31.1 + diff --git a/binutils-pr29370.diff b/binutils-pr29370.diff new file mode 100644 index 0000000..61edbea --- /dev/null +++ b/binutils-pr29370.diff @@ -0,0 +1,96 @@ +Aka bsc#1203016 + +From 695c6dfe7e85006b98c8b746f3fd5f913c94ebff Mon Sep 17 00:00:00 2001 +From: Alan Modra +Date: Thu, 21 Jul 2022 09:56:15 +0930 +Subject: [PATCH] PR29370, infinite loop in display_debug_abbrev + +The PR29370 testcase is a fuzzed object file with multiple +.trace_abbrev sections. Multiple .trace_abbrev or .debug_abbrev +sections are not a violation of the DWARF standard. The DWARF5 +standard even gives an example of multiple .debug_abbrev sections +contained in groups. Caching and lookup of processed abbrevs thus +needs to be done by section and offset rather than base and offset. +(Why base anyway?) Or, since section contents are kept, by a pointer +into the contents. + + PR 29370 + * dwarf.c (struct abbrev_list): Replace abbrev_base and + abbrev_offset with raw field. + (find_abbrev_list_by_abbrev_offset): Delete. + (find_abbrev_list_by_raw_abbrev): New function. + (process_abbrev_set): Set list->raw and list->next. + (find_and_process_abbrev_set): Replace abbrev list lookup with + new function. Don't set list abbrev_base, abbrev_offset or next. +--- + binutils/dwarf.c | 19 ++++++------------- + 1 file changed, 6 insertions(+), 13 deletions(-) + +diff --git a/binutils/dwarf.c b/binutils/dwarf.c +index 2fc352f74c5..99fb3566994 100644 +--- a/binutils/dwarf.c ++++ b/binutils/dwarf.c +@@ -856,8 +856,7 @@ typedef struct abbrev_list + { + abbrev_entry * first_abbrev; + abbrev_entry * last_abbrev; +- dwarf_vma abbrev_base; +- dwarf_vma abbrev_offset; ++ unsigned char * raw; + struct abbrev_list * next; + unsigned char * start_of_next_abbrevs; + } +@@ -946,14 +945,12 @@ free_all_abbrevs (void) + } + + static abbrev_list * +-find_abbrev_list_by_abbrev_offset (dwarf_vma abbrev_base, +- dwarf_vma abbrev_offset) ++find_abbrev_list_by_raw_abbrev (unsigned char *raw) + { + abbrev_list * list; + + for (list = abbrev_lists; list != NULL; list = list->next) +- if (list->abbrev_base == abbrev_base +- && list->abbrev_offset == abbrev_offset) ++ if (list->raw == raw) + return list; + + return NULL; +@@ -1040,6 +1037,7 @@ process_abbrev_set (struct dwarf_section *section, + abbrev_list *list = xmalloc (sizeof (*list)); + list->first_abbrev = NULL; + list->last_abbrev = NULL; ++ list->raw = start; + + while (start < end) + { +@@ -1055,6 +1053,7 @@ process_abbrev_set (struct dwarf_section *section, + the caller. */ + if (start == end || entry == 0) + { ++ list->next = NULL; + list->start_of_next_abbrevs = start != end ? start : NULL; + return list; + } +@@ -1144,16 +1143,10 @@ find_and_process_abbrev_set (struct dwarf_section *section, + unsigned char *end = section->start + abbrev_base + abbrev_size; + abbrev_list *list = NULL; + if (free_list) +- list = find_abbrev_list_by_abbrev_offset (abbrev_base, abbrev_offset); ++ list = find_abbrev_list_by_raw_abbrev (start); + if (list == NULL) + { + list = process_abbrev_set (section, start, end); +- if (list) +- { +- list->abbrev_base = abbrev_base; +- list->abbrev_offset = abbrev_offset; +- list->next = NULL; +- } + if (free_list) + *free_list = list; + } +-- +2.31.1 + diff --git a/binutils.changes b/binutils.changes index 9c9a1e4..0085354 100644 --- a/binutils.changes +++ b/binutils.changes @@ -1,3 +1,10 @@ +------------------------------------------------------------------- +Thu Sep 1 11:52:52 UTC 2022 - Michael Matz + +- Add binutils-pr29370.diff and their prerequisites + binutils-pr29370-pre1.diff and binutils-pr29370-pre2.diff + for PR29370, aka CVE-2022-38128 [bsc#1203016] + ------------------------------------------------------------------- Fri Aug 26 13:24:35 UTC 2022 - Michael Matz diff --git a/binutils.spec b/binutils.spec index da0b4dc..30e4101 100644 --- a/binutils.spec +++ b/binutils.spec @@ -139,6 +139,9 @@ Patch41: binutils-fix-relax.diff Patch42: binutils-compat-old-behaviour.diff Patch43: binutils-revert-hlasm-insns.diff Patch44: binutils-pr29482.diff +Patch45: binutils-pr29370-pre1.diff +Patch46: binutils-pr29370-pre2.diff +Patch47: binutils-pr29370.diff Patch100: add-ulp-section.diff Patch90: cross-avr-nesc-as.patch Patch92: cross-avr-omit_section_dynsym.patch @@ -262,6 +265,9 @@ cp ld/ldgram.y ld/ldgram.y.orig %patch43 -p1 %endif %patch44 -p1 +%patch45 -p1 +%patch46 -p1 +%patch47 -p1 %patch100 -p1 %if "%{TARGET}" == "avr" cp gas/config/tc-avr.h gas/config/tc-avr-nesc.h From 9460b44a5c6b84b590c55ccb69dd14a7593a0142300c728fe79cc0fa82d257d3 Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Thu, 1 Sep 2022 11:57:45 +0000 Subject: [PATCH 03/10] The last change was premature, 2.39 isn't actually affected by the problem, it was introduced in one of the prerequisite patches, remove all traces of the change. OBS-URL: https://build.opensuse.org/package/show/devel:gcc/binutils?expand=0&rev=419 --- binutils-pr29370-pre1.diff | 532 ------------------------------------- binutils-pr29370-pre2.diff | 349 ------------------------ binutils-pr29370.diff | 96 ------- binutils.changes | 7 - binutils.spec | 6 - 5 files changed, 990 deletions(-) delete mode 100644 binutils-pr29370-pre1.diff delete mode 100644 binutils-pr29370-pre2.diff delete mode 100644 binutils-pr29370.diff diff --git a/binutils-pr29370-pre1.diff b/binutils-pr29370-pre1.diff deleted file mode 100644 index 2dfc713..0000000 --- a/binutils-pr29370-pre1.diff +++ /dev/null @@ -1,532 +0,0 @@ -From 175b91507b83ad42607d2f6dadaf55b7b511bdbe Mon Sep 17 00:00:00 2001 -From: Alan Modra -Date: Wed, 20 Jul 2022 18:28:50 +0930 -Subject: [PATCH] miscellaneous dwarf.c tidies - - * dwarf.c: Leading and trailing whitespace fixes. - (free_abbrev_list): New function. - (free_all_abbrevs): Use the above. Free cu_abbrev_map here too. - (process_abbrev_set): Print actual section name on error. - (get_type_abbrev_from_form): Add overflow check. - (free_debug_memory): Don't free cu_abbrev_map here.. - (process_debug_info): ..or here. Warn on another case of not - finding a neeeded abbrev. ---- - binutils/dwarf.c | 216 +++++++++++++++++++++++------------------------ - 1 file changed, 106 insertions(+), 110 deletions(-) - -Index: binutils-2.39/binutils/dwarf.c -=================================================================== ---- binutils-2.39.orig/binutils/dwarf.c 2022-09-01 13:51:14.818699924 +0200 -+++ binutils-2.39/binutils/dwarf.c 2022-09-01 13:51:32.090984628 +0200 -@@ -806,7 +806,7 @@ fetch_indexed_value (dwarf_vma idx, - pointer_size = 4; - bias = 12; - } -- -+ - dwarf_vma offset = idx * pointer_size; - - /* Offsets are biased by the size of the section header -@@ -901,38 +901,41 @@ record_abbrev_list_for_cu (dwarf_vma sta - next_free_abbrev_map_entry ++; - } - --static void --free_all_abbrevs (void) -+static abbrev_list * -+free_abbrev_list (abbrev_list *list) - { -- abbrev_list * list; -+ abbrev_entry *abbrv = list->first_abbrev; - -- for (list = abbrev_lists; list != NULL;) -+ while (abbrv) - { -- abbrev_list * next = list->next; -- abbrev_entry * abbrv; -+ abbrev_attr *attr = abbrv->first_attr; - -- for (abbrv = list->first_abbrev; abbrv != NULL;) -+ while (attr) - { -- abbrev_entry * next_abbrev = abbrv->next; -- abbrev_attr * attr; -- -- for (attr = abbrv->first_attr; attr;) -- { -- abbrev_attr *next_attr = attr->next; -- -- free (attr); -- attr = next_attr; -- } -- -- free (abbrv); -- abbrv = next_abbrev; -+ abbrev_attr *next_attr = attr->next; -+ free (attr); -+ attr = next_attr; - } - -- free (list); -- list = next; -+ abbrev_entry *next_abbrev = abbrv->next; -+ free (abbrv); -+ abbrv = next_abbrev; - } - -- abbrev_lists = NULL; -+ abbrev_list *next = list->next; -+ free (list); -+ return next; -+} -+ -+static void -+free_all_abbrevs (void) -+{ -+ while (abbrev_lists) -+ abbrev_lists = free_abbrev_list (abbrev_lists); -+ -+ free (cu_abbrev_map); -+ cu_abbrev_map = NULL; -+ next_free_abbrev_map_entry = 0; - } - - static abbrev_list * -@@ -978,7 +981,7 @@ find_abbrev_map_by_offset (dwarf_vma off - && cu_abbrev_map[i].end > offset) - return cu_abbrev_map + i; - -- return NULL; -+ return NULL; - } - - static void -@@ -1119,7 +1122,7 @@ process_abbrev_set (struct dwarf_section - } - - /* Report the missing single zero which ends the section. */ -- error (_(".debug_abbrev section not zero terminated\n")); -+ error (_("%s section not zero terminated\n"), section->name); - - return NULL; - } -@@ -1842,7 +1845,7 @@ fetch_alt_indirect_string (dwarf_vma off - dwarf_vmatoa ("x", offset)); - return _(""); - } -- -+ - static const char * - get_AT_name (unsigned long attribute) - { -@@ -2124,7 +2127,8 @@ get_type_abbrev_from_form (unsigned long - case DW_FORM_ref4: - case DW_FORM_ref8: - case DW_FORM_ref_udata: -- if (uvalue + cu_offset > (size_t) (cu_end - section->start)) -+ if (uvalue + cu_offset < uvalue -+ || uvalue + cu_offset > (size_t) (cu_end - section->start)) - { - warn (_("Unable to resolve ref form: uvalue %lx + cu_offset %lx > CU size %lx\n"), - uvalue, (long) cu_offset, (long) (cu_end - section->start)); -@@ -2161,7 +2165,7 @@ get_type_abbrev_from_form (unsigned long - else - *map_return = NULL; - } -- -+ - READ_ULEB (abbrev_number, data, section->start + section->size); - - for (entry = map->list->first_abbrev; entry != NULL; entry = entry->next) -@@ -2750,10 +2754,10 @@ read_and_display_attr_value (unsigned lo - if (form == DW_FORM_loclistx) - { - if (dwo) -- { -- index = fetch_indexed_value (uvalue, loclists_dwo, 0); -- index += (offset_size == 8) ? 20 : 12; -- } -+ { -+ index = fetch_indexed_value (uvalue, loclists_dwo, 0); -+ index += (offset_size == 8) ? 20 : 12; -+ } - else if (debug_info_p == NULL) - { - index = fetch_indexed_value (uvalue, loclists, 0); -@@ -2771,21 +2775,21 @@ read_and_display_attr_value (unsigned lo - else if (form == DW_FORM_rnglistx) - { - if (dwo) -- { -- index = fetch_indexed_value (uvalue, rnglists_dwo, 0); -- index += (offset_size == 8) ? 20 : 12; -- } -+ { -+ index = fetch_indexed_value (uvalue, rnglists_dwo, 0); -+ index += (offset_size == 8) ? 20 : 12; -+ } - else -- { -- if (debug_info_p == NULL) -- base = 0; -- else -- base = debug_info_p->rnglists_base; -- /* We do not have a cached value this time, so we perform the -- computation manually. */ -- index = fetch_indexed_value (uvalue, rnglists, base); -- index += base; -- } -+ { -+ if (debug_info_p == NULL) -+ base = 0; -+ else -+ base = debug_info_p->rnglists_base; -+ /* We do not have a cached value this time, so we perform the -+ computation manually. */ -+ index = fetch_indexed_value (uvalue, rnglists, base); -+ index += base; -+ } - } - else - { -@@ -2811,7 +2815,7 @@ read_and_display_attr_value (unsigned lo - if (!do_loc) - printf ("%c<0x%s>", delimiter, dwarf_vmatoa ("x", uvalue + cu_offset)); - break; -- -+ - default: - warn (_("Unrecognized form: 0x%lx\n"), form); - /* What to do? Consume a byte maybe? */ -@@ -2836,9 +2840,9 @@ read_and_display_attr_value (unsigned lo - case DW_AT_rnglists_base: - if (debug_info_p->rnglists_base) - warn (_("CU @ 0x%s has multiple rnglists_base values (0x%s and 0x%s)"), -- dwarf_vmatoa ("x", debug_info_p->cu_offset), -- dwarf_vmatoa ("x", debug_info_p->rnglists_base), -- dwarf_vmatoa ("x", uvalue)); -+ dwarf_vmatoa ("x", debug_info_p->cu_offset), -+ dwarf_vmatoa ("x", debug_info_p->rnglists_base), -+ dwarf_vmatoa ("x", uvalue)); - debug_info_p->rnglists_base = uvalue; - break; - case DW_AT_str_offsets_base: -@@ -2988,7 +2992,7 @@ read_and_display_attr_value (unsigned lo - case DW_FORM_strx3: - case DW_FORM_strx4: - add_dwo_name (fetch_indexed_string (uvalue, this_set, offset_size, false, -- debug_info_p->str_offsets_base), -+ debug_info_p->str_offsets_base), - cu_offset); - break; - case DW_FORM_string: -@@ -3022,7 +3026,7 @@ read_and_display_attr_value (unsigned lo - case DW_FORM_strx3: - case DW_FORM_strx4: - add_dwo_dir (fetch_indexed_string (uvalue, this_set, offset_size, false, -- debug_info_p->str_offsets_base), -+ debug_info_p->str_offsets_base), - cu_offset); - break; - case DW_FORM_string: -@@ -3653,11 +3657,8 @@ process_debug_info (struct dwarf_section - introduce (section, false); - - free_all_abbrevs (); -- free (cu_abbrev_map); -- cu_abbrev_map = NULL; -- next_free_abbrev_map_entry = 0; - -- /* In order to be able to resolve DW_FORM_ref_attr forms we need -+ /* In order to be able to resolve DW_FORM_ref_addr forms we need - to load *all* of the abbrevs for all CUs in this .debug_info - section. This does effectively mean that we (partially) read - every CU header twice. */ -@@ -4028,12 +4029,11 @@ process_debug_info (struct dwarf_section - - /* Scan through the abbreviation list until we reach the - correct entry. */ -- if (list == NULL) -- continue; -- -- for (entry = list->first_abbrev; entry != NULL; entry = entry->next) -- if (entry->number == abbrev_number) -- break; -+ entry = NULL; -+ if (list != NULL) -+ for (entry = list->first_abbrev; entry != NULL; entry = entry->next) -+ if (entry->number == abbrev_number) -+ break; - - if (entry == NULL) - { -@@ -4057,7 +4057,7 @@ process_debug_info (struct dwarf_section - break; - case DW_TAG_compile_unit: - case DW_TAG_skeleton_unit: -- need_base_address = 1; -+ need_base_address = 1; - need_dwo_info = do_loc; - break; - case DW_TAG_entry_point: -@@ -4440,7 +4440,7 @@ display_debug_sup (struct dwarf_section - - SAFE_BYTE_GET_AND_INC (is_supplementary, start, 1, end); - if (is_supplementary != 0 && is_supplementary != 1) -- warn (_("corrupt .debug_sup section: is_supplementary not 0 or 1\n")); -+ warn (_("corrupt .debug_sup section: is_supplementary not 0 or 1\n")); - - sup_filename = start; - if (is_supplementary && sup_filename[0] != 0) -@@ -5619,7 +5619,7 @@ display_debug_lines_decoded (struct dwar - printf ("%s %11d %#18" DWARF_VMA_FMT "x", - newFileName, state_machine_regs.line, - state_machine_regs.address); -- } -+ } - else - { - if (xop == -DW_LNE_end_sequence) -@@ -6073,7 +6073,7 @@ display_debug_macro (struct dwarf_sectio - load_debug_section_with_follow (str, file); - load_debug_section_with_follow (line, file); - load_debug_section_with_follow (str_index, file); -- -+ - introduce (section, false); - - while (curr < end) -@@ -6525,7 +6525,7 @@ display_loc_list (struct dwarf_section * - - /* Check base address specifiers. */ - if (is_max_address (begin, pointer_size) -- && !is_max_address (end, pointer_size)) -+ && !is_max_address (end, pointer_size)) - { - base_address = end; - print_dwarf_vma (begin, pointer_size); -@@ -6703,7 +6703,7 @@ display_loclists_list (struct dwarf_sect - case DW_LLE_default_location: - begin = end = 0; - break; -- -+ - case DW_LLE_offset_pair: - READ_ULEB (begin, start, section_end); - begin += base_address; -@@ -6999,7 +6999,7 @@ display_offset_entry_loclists (struct dw - unsigned char * start = section->start; - unsigned char * const end = start + section->size; - -- introduce (section, false); -+ introduce (section, false); - - do - { -@@ -7048,14 +7048,14 @@ display_offset_entry_loclists (struct dw - section->name, segment_selector_size); - return 0; - } -- -+ - if (offset_entry_count == 0) - { - warn (_("The %s section contains a table without offset\n"), - section->name); - return 0; - } -- -+ - printf (_("\n Offset Entries starting at 0x%lx:\n"), - (long)(start - section->start)); - -@@ -8217,7 +8217,7 @@ display_debug_rnglists (struct dwarf_sec - start = display_debug_rnglists_list - (start, end, address_size, offset, 0, offset_size); - if (start >= end) -- break; -+ break; - } - - start = end; -@@ -8335,12 +8335,12 @@ display_debug_ranges (struct dwarf_secti - next = section_begin + offset + debug_info_p->rnglists_base; - - /* If multiple DWARF entities reference the same range then we will -- have multiple entries in the `range_entries' list for the same -- offset. Thanks to the sort above these will all be consecutive in -- the `range_entries' list, so we can easily ignore duplicates -- here. */ -+ have multiple entries in the `range_entries' list for the same -+ offset. Thanks to the sort above these will all be consecutive in -+ the `range_entries' list, so we can easily ignore duplicates -+ here. */ - if (i > 0 && last_offset == offset) -- continue; -+ continue; - last_offset = offset; - - if (dwarf_check != 0 && i > 0) -@@ -10274,7 +10274,7 @@ display_debug_names (struct dwarf_sectio - printf (_("Out of %lu items there are %zu bucket clashes" - " (longest of %zu entries).\n"), - (unsigned long) name_count, hash_clash_count, longest_clash); -- -+ - if (name_count != buckets_filled + hash_clash_count) - warn (_("The name_count (%lu) is not the same as the used bucket_count (%lu) + the hash clash count (%lu)"), - (unsigned long) name_count, -@@ -10378,7 +10378,7 @@ display_debug_names (struct dwarf_sectio - break; - if (tagno >= 0) - printf ("%s<%lu>", -- (tagno == 0 && second_abbrev_tag == 0 ? " " : "\n\t"), -+ (tagno == 0 && second_abbrev_tag == 0 ? " " : "\n\t"), - (unsigned long) abbrev_tag); - - for (entry = abbrev_lookup; -@@ -10907,7 +10907,7 @@ process_cu_tu_index (struct dwarf_sectio - Check for integer overflow (can occur when size_t is 32-bit) - with overlarge ncols or nused values. */ - if (nused == -1u -- || _mul_overflow ((size_t) ncols, 4, &temp) -+ || _mul_overflow ((size_t) ncols, 4, &temp) - || _mul_overflow ((size_t) nused + 1, temp, &total) - || total > (size_t) (limit - ppool)) - { -@@ -10915,7 +10915,7 @@ process_cu_tu_index (struct dwarf_sectio - section->name); - return 0; - } -- -+ - if (do_display) - { - printf (_(" Offset table\n")); -@@ -11419,8 +11419,8 @@ add_separate_debug_file (const char * fi - - static bool - debuginfod_fetch_separate_debug_info (struct dwarf_section * section, -- char ** filename, -- void * file) -+ char ** filename, -+ void * file) - { - size_t build_id_len; - unsigned char * build_id; -@@ -11438,14 +11438,14 @@ debuginfod_fetch_separate_debug_info (st - - filelen = strnlen ((const char *)section->start, section->size); - if (filelen == section->size) -- /* Corrupt debugaltlink. */ -- return false; -+ /* Corrupt debugaltlink. */ -+ return false; - - build_id = section->start + filelen + 1; - build_id_len = section->size - (filelen + 1); - - if (build_id_len == 0) -- return false; -+ return false; - } - else - return false; -@@ -11457,25 +11457,25 @@ debuginfod_fetch_separate_debug_info (st - - client = debuginfod_begin (); - if (client == NULL) -- return false; -+ return false; - - /* Query debuginfod servers for the target file. If found its path -- will be stored in filename. */ -+ will be stored in filename. */ - fd = debuginfod_find_debuginfo (client, build_id, build_id_len, filename); - debuginfod_end (client); - - /* Only free build_id if we allocated space for a hex string -- in get_build_id (). */ -+ in get_build_id (). */ - if (build_id_len == 0) -- free (build_id); -+ free (build_id); - - if (fd >= 0) -- { -- /* File successfully retrieved. Close fd since we want to -- use open_debug_file () on filename instead. */ -- close (fd); -- return true; -- } -+ { -+ /* File successfully retrieved. Close fd since we want to -+ use open_debug_file () on filename instead. */ -+ close (fd); -+ return true; -+ } - } - - return false; -@@ -11488,7 +11488,7 @@ load_separate_debug_info (const char * - parse_func_type parse_func, - check_func_type check_func, - void * func_data, -- void * file ATTRIBUTE_UNUSED) -+ void * file ATTRIBUTE_UNUSED) - { - const char * separate_filename; - char * debug_filename; -@@ -11604,11 +11604,11 @@ load_separate_debug_info (const char * - & tmp_filename, - file)) - { -- /* File successfully downloaded from server, replace -- debug_filename with the file's path. */ -- free (debug_filename); -- debug_filename = tmp_filename; -- goto found; -+ /* File successfully downloaded from server, replace -+ debug_filename with the file's path. */ -+ free (debug_filename); -+ debug_filename = tmp_filename; -+ goto found; - } - } - #endif -@@ -11775,12 +11775,12 @@ load_build_id_debug_file (const char * m - /* In theory we should extract the contents of the section into - a note structure and then check the fields. For now though - just use hard coded offsets instead: -- -+ - Field Bytes Contents - NSize 0...3 4 - DSize 4...7 8+ - Type 8..11 3 (NT_GNU_BUILD_ID) -- Name 12.15 GNU\0 -+ Name 12.15 GNU\0 - Data 16.... */ - - /* FIXME: Check the name size, name and type fields. */ -@@ -11792,7 +11792,7 @@ load_build_id_debug_file (const char * m - warn (_(".note.gnu.build-id data size is too small\n")); - return; - } -- -+ - if (build_id_size > (section->size - 16)) - { - warn (_(".note.gnu.build-id data size is too bug\n")); -@@ -12088,10 +12088,6 @@ free_debug_memory (void) - - free_all_abbrevs (); - -- free (cu_abbrev_map); -- cu_abbrev_map = NULL; -- next_free_abbrev_map_entry = 0; -- - free (shndx_pool); - shndx_pool = NULL; - shndx_pool_size = 0; diff --git a/binutils-pr29370-pre2.diff b/binutils-pr29370-pre2.diff deleted file mode 100644 index be87ba8..0000000 --- a/binutils-pr29370-pre2.diff +++ /dev/null @@ -1,349 +0,0 @@ -From f07c08e115e27cddf5a0030dc6332bbee1bd9c6a Mon Sep 17 00:00:00 2001 -From: Alan Modra -Date: Thu, 21 Jul 2022 08:38:14 +0930 -Subject: [PATCH] binutils/dwarf.c: abbrev caching - -I'm inclined to think that abbrev caching is counter-productive. The -time taken to search the list of abbrevs converted to internal form is -non-zero, and it's easy to decode the raw abbrevs. It's especially -silly to cache empty lists of decoded abbrevs (happens with zero -padding in .debug_abbrev), or abbrevs as they are displayed when there -is no further use of those abbrevs. This patch stops caching in those -cases. - - * dwarf.c (record_abbrev_list_for_cu): Add free_list param. - Put abbrevs on abbrev_lists here. - (new_abbrev_list): Delete function. - (process_abbrev_set): Return newly allocated list. Move - abbrev base, offset and size checking to.. - (find_and_process_abbrev_set): ..here, new function. Handle - lookup of cached abbrevs here, and calculate start and end - for process_abbrev_set. Return free_list if newly alloc'd. - (process_debug_info): Consolidate cached list lookup, new list - alloc and processing into find_and_process_abbrev_set call. - Free list when not cached. - (display_debug_abbrev): Similarly. ---- - binutils/dwarf.c | 208 +++++++++++++++++++++++++---------------------- - 1 file changed, 110 insertions(+), 98 deletions(-) - -diff --git a/binutils/dwarf.c b/binutils/dwarf.c -index 267ed3bb382..2fc352f74c5 100644 ---- a/binutils/dwarf.c -+++ b/binutils/dwarf.c -@@ -882,8 +882,15 @@ static unsigned long next_free_abbrev_map_entry = 0; - #define ABBREV_MAP_ENTRIES_INCREMENT 8 - - static void --record_abbrev_list_for_cu (dwarf_vma start, dwarf_vma end, abbrev_list * list) -+record_abbrev_list_for_cu (dwarf_vma start, dwarf_vma end, -+ abbrev_list *list, abbrev_list *free_list) - { -+ if (free_list != NULL) -+ { -+ list->next = abbrev_lists; -+ abbrev_lists = list; -+ } -+ - if (cu_abbrev_map == NULL) - { - num_abbrev_map_entries = INITIAL_NUM_ABBREV_MAP_ENTRIES; -@@ -938,20 +945,6 @@ free_all_abbrevs (void) - next_free_abbrev_map_entry = 0; - } - --static abbrev_list * --new_abbrev_list (dwarf_vma abbrev_base, dwarf_vma abbrev_offset) --{ -- abbrev_list * list = (abbrev_list *) xcalloc (sizeof * list, 1); -- -- list->abbrev_base = abbrev_base; -- list->abbrev_offset = abbrev_offset; -- -- list->next = abbrev_lists; -- abbrev_lists = list; -- -- return list; --} -- - static abbrev_list * - find_abbrev_list_by_abbrev_offset (dwarf_vma abbrev_base, - dwarf_vma abbrev_offset) -@@ -969,7 +962,7 @@ find_abbrev_list_by_abbrev_offset (dwarf_vma abbrev_base, - /* Find the abbreviation map for the CU that includes OFFSET. - OFFSET is an absolute offset from the start of the .debug_info section. */ - /* FIXME: This function is going to slow down readelf & objdump. -- Consider using a better algorithm to mitigate this effect. */ -+ Not caching abbrevs is likely the answer. */ - - static abbrev_map * - find_abbrev_map_by_offset (dwarf_vma offset) -@@ -1036,40 +1029,18 @@ add_abbrev_attr (unsigned long attribute, - list->last_abbrev->last_attr = attr; - } - --/* Processes the (partial) contents of a .debug_abbrev section. -- Returns NULL if the end of the section was encountered. -- Returns the address after the last byte read if the end of -- an abbreviation set was found. */ -+/* Return processed (partial) contents of a .debug_abbrev section. -+ Returns NULL on errors. */ - --static unsigned char * -+static abbrev_list * - process_abbrev_set (struct dwarf_section *section, -- dwarf_vma abbrev_base, -- dwarf_vma abbrev_size, -- dwarf_vma abbrev_offset, -- abbrev_list *list) -+ unsigned char *start, -+ unsigned char *end) - { -- if (abbrev_base >= section->size -- || abbrev_size > section->size - abbrev_base) -- { -- /* PR 17531: file:4bcd9ce9. */ -- warn (_("Debug info is corrupted, abbrev size (%lx) is larger than " -- "abbrev section size (%lx)\n"), -- (unsigned long) (abbrev_base + abbrev_size), -- (unsigned long) section->size); -- return NULL; -- } -- if (abbrev_offset >= abbrev_size) -- { -- warn (_("Debug info is corrupted, abbrev offset (%lx) is larger than " -- "abbrev section size (%lx)\n"), -- (unsigned long) abbrev_offset, -- (unsigned long) abbrev_size); -- return NULL; -- } -+ abbrev_list *list = xmalloc (sizeof (*list)); -+ list->first_abbrev = NULL; -+ list->last_abbrev = NULL; - -- unsigned char *start = section->start + abbrev_base; -- unsigned char *end = start + abbrev_size; -- start += abbrev_offset; - while (start < end) - { - unsigned long entry; -@@ -1082,14 +1053,18 @@ process_abbrev_set (struct dwarf_section *section, - /* A single zero is supposed to end the set according - to the standard. If there's more, then signal that to - the caller. */ -- if (start == end) -- return NULL; -- if (entry == 0) -- return start; -+ if (start == end || entry == 0) -+ { -+ list->start_of_next_abbrevs = start != end ? start : NULL; -+ return list; -+ } - - READ_ULEB (tag, start, end); - if (start == end) -- return NULL; -+ { -+ free (list); -+ return NULL; -+ } - - children = *start++; - -@@ -1124,9 +1099,67 @@ process_abbrev_set (struct dwarf_section *section, - /* Report the missing single zero which ends the section. */ - error (_("%s section not zero terminated\n"), section->name); - -+ free (list); - return NULL; - } - -+/* Return a sequence of abbrevs in SECTION starting at ABBREV_BASE -+ plus ABBREV_OFFSET and finishing at ABBREV_BASE + ABBREV_SIZE. -+ If FREE_LIST is non-NULL search the already decoded abbrevs on -+ abbrev_lists first and if found set *FREE_LIST to NULL. If -+ searching doesn't find a matching abbrev, set *FREE_LIST to the -+ newly allocated list. If FREE_LIST is NULL, no search is done and -+ the returned abbrev_list is always newly allocated. */ -+ -+static abbrev_list * -+find_and_process_abbrev_set (struct dwarf_section *section, -+ dwarf_vma abbrev_base, -+ dwarf_vma abbrev_size, -+ dwarf_vma abbrev_offset, -+ abbrev_list **free_list) -+{ -+ if (free_list) -+ *free_list = NULL; -+ -+ if (abbrev_base >= section->size -+ || abbrev_size > section->size - abbrev_base) -+ { -+ /* PR 17531: file:4bcd9ce9. */ -+ warn (_("Debug info is corrupted, abbrev size (%lx) is larger than " -+ "abbrev section size (%lx)\n"), -+ (unsigned long) (abbrev_base + abbrev_size), -+ (unsigned long) section->size); -+ return NULL; -+ } -+ if (abbrev_offset >= abbrev_size) -+ { -+ warn (_("Debug info is corrupted, abbrev offset (%lx) is larger than " -+ "abbrev section size (%lx)\n"), -+ (unsigned long) abbrev_offset, -+ (unsigned long) abbrev_size); -+ return NULL; -+ } -+ -+ unsigned char *start = section->start + abbrev_base + abbrev_offset; -+ unsigned char *end = section->start + abbrev_base + abbrev_size; -+ abbrev_list *list = NULL; -+ if (free_list) -+ list = find_abbrev_list_by_abbrev_offset (abbrev_base, abbrev_offset); -+ if (list == NULL) -+ { -+ list = process_abbrev_set (section, start, end); -+ if (list) -+ { -+ list->abbrev_base = abbrev_base; -+ list->abbrev_offset = abbrev_offset; -+ list->next = NULL; -+ } -+ if (free_list) -+ *free_list = list; -+ } -+ return list; -+} -+ - static const char * - get_TAG_name (unsigned long tag) - { -@@ -3671,7 +3704,6 @@ process_debug_info (struct dwarf_section * section, - dwarf_vma cu_offset; - unsigned int offset_size; - struct cu_tu_set * this_set; -- abbrev_list * list; - unsigned char *end_cu; - - hdrptr = start; -@@ -3727,22 +3759,18 @@ process_debug_info (struct dwarf_section * section, - abbrev_size = this_set->section_sizes [DW_SECT_ABBREV]; - } - -- list = find_abbrev_list_by_abbrev_offset (abbrev_base, -- compunit.cu_abbrev_offset); -- if (list == NULL) -- { -- unsigned char * next; -- -- list = new_abbrev_list (abbrev_base, -- compunit.cu_abbrev_offset); -- next = process_abbrev_set (&debug_displays[abbrev_sec].section, -- abbrev_base, abbrev_size, -- compunit.cu_abbrev_offset, list); -- list->start_of_next_abbrevs = next; -- } -- -+ abbrev_list *list; -+ abbrev_list *free_list; -+ list = find_and_process_abbrev_set (&debug_displays[abbrev_sec].section, -+ abbrev_base, abbrev_size, -+ compunit.cu_abbrev_offset, -+ &free_list); - start = end_cu; -- record_abbrev_list_for_cu (cu_offset, start - section_begin, list); -+ if (list != NULL && list->first_abbrev != NULL) -+ record_abbrev_list_for_cu (cu_offset, start - section_begin, -+ list, free_list); -+ else if (free_list != NULL) -+ free_abbrev_list (free_list); - } - - for (start = section_begin, unit = 0; start < end; unit++) -@@ -3758,7 +3786,6 @@ process_debug_info (struct dwarf_section * section, - struct cu_tu_set *this_set; - dwarf_vma abbrev_base; - size_t abbrev_size; -- abbrev_list * list = NULL; - unsigned char *end_cu; - - hdrptr = start; -@@ -3937,20 +3964,10 @@ process_debug_info (struct dwarf_section * section, - } - - /* Process the abbrevs used by this compilation unit. */ -- list = find_abbrev_list_by_abbrev_offset (abbrev_base, -- compunit.cu_abbrev_offset); -- if (list == NULL) -- { -- unsigned char *next; -- -- list = new_abbrev_list (abbrev_base, -- compunit.cu_abbrev_offset); -- next = process_abbrev_set (&debug_displays[abbrev_sec].section, -- abbrev_base, abbrev_size, -- compunit.cu_abbrev_offset, list); -- list->start_of_next_abbrevs = next; -- } -- -+ abbrev_list *list; -+ list = find_and_process_abbrev_set (&debug_displays[abbrev_sec].section, -+ abbrev_base, abbrev_size, -+ compunit.cu_abbrev_offset, NULL); - level = 0; - last_level = level; - saved_level = -1; -@@ -4128,6 +4145,8 @@ process_debug_info (struct dwarf_section * section, - if (entry->children) - ++level; - } -+ if (list != NULL) -+ free_abbrev_list (list); - } - - /* Set num_debug_info_entries here so that it can be used to check if -@@ -6353,24 +6372,15 @@ display_debug_abbrev (struct dwarf_section *section, - - do - { -- abbrev_list * list; -- dwarf_vma offset; -- -- offset = start - section->start; -- list = find_abbrev_list_by_abbrev_offset (0, offset); -+ dwarf_vma offset = start - section->start; -+ abbrev_list *list = find_and_process_abbrev_set (section, 0, -+ section->size, offset, -+ NULL); - if (list == NULL) -- { -- list = new_abbrev_list (0, offset); -- start = process_abbrev_set (section, 0, section->size, offset, list); -- list->start_of_next_abbrevs = start; -- } -- else -- start = list->start_of_next_abbrevs; -- -- if (list->first_abbrev == NULL) -- continue; -+ break; - -- printf (_(" Number TAG (0x%lx)\n"), (long) offset); -+ if (list->first_abbrev) -+ printf (_(" Number TAG (0x%lx)\n"), (long) offset); - - for (entry = list->first_abbrev; entry; entry = entry->next) - { -@@ -6391,6 +6401,8 @@ display_debug_abbrev (struct dwarf_section *section, - putchar ('\n'); - } - } -+ start = list->start_of_next_abbrevs; -+ free_abbrev_list (list); - } - while (start); - --- -2.31.1 - diff --git a/binutils-pr29370.diff b/binutils-pr29370.diff deleted file mode 100644 index 61edbea..0000000 --- a/binutils-pr29370.diff +++ /dev/null @@ -1,96 +0,0 @@ -Aka bsc#1203016 - -From 695c6dfe7e85006b98c8b746f3fd5f913c94ebff Mon Sep 17 00:00:00 2001 -From: Alan Modra -Date: Thu, 21 Jul 2022 09:56:15 +0930 -Subject: [PATCH] PR29370, infinite loop in display_debug_abbrev - -The PR29370 testcase is a fuzzed object file with multiple -.trace_abbrev sections. Multiple .trace_abbrev or .debug_abbrev -sections are not a violation of the DWARF standard. The DWARF5 -standard even gives an example of multiple .debug_abbrev sections -contained in groups. Caching and lookup of processed abbrevs thus -needs to be done by section and offset rather than base and offset. -(Why base anyway?) Or, since section contents are kept, by a pointer -into the contents. - - PR 29370 - * dwarf.c (struct abbrev_list): Replace abbrev_base and - abbrev_offset with raw field. - (find_abbrev_list_by_abbrev_offset): Delete. - (find_abbrev_list_by_raw_abbrev): New function. - (process_abbrev_set): Set list->raw and list->next. - (find_and_process_abbrev_set): Replace abbrev list lookup with - new function. Don't set list abbrev_base, abbrev_offset or next. ---- - binutils/dwarf.c | 19 ++++++------------- - 1 file changed, 6 insertions(+), 13 deletions(-) - -diff --git a/binutils/dwarf.c b/binutils/dwarf.c -index 2fc352f74c5..99fb3566994 100644 ---- a/binutils/dwarf.c -+++ b/binutils/dwarf.c -@@ -856,8 +856,7 @@ typedef struct abbrev_list - { - abbrev_entry * first_abbrev; - abbrev_entry * last_abbrev; -- dwarf_vma abbrev_base; -- dwarf_vma abbrev_offset; -+ unsigned char * raw; - struct abbrev_list * next; - unsigned char * start_of_next_abbrevs; - } -@@ -946,14 +945,12 @@ free_all_abbrevs (void) - } - - static abbrev_list * --find_abbrev_list_by_abbrev_offset (dwarf_vma abbrev_base, -- dwarf_vma abbrev_offset) -+find_abbrev_list_by_raw_abbrev (unsigned char *raw) - { - abbrev_list * list; - - for (list = abbrev_lists; list != NULL; list = list->next) -- if (list->abbrev_base == abbrev_base -- && list->abbrev_offset == abbrev_offset) -+ if (list->raw == raw) - return list; - - return NULL; -@@ -1040,6 +1037,7 @@ process_abbrev_set (struct dwarf_section *section, - abbrev_list *list = xmalloc (sizeof (*list)); - list->first_abbrev = NULL; - list->last_abbrev = NULL; -+ list->raw = start; - - while (start < end) - { -@@ -1055,6 +1053,7 @@ process_abbrev_set (struct dwarf_section *section, - the caller. */ - if (start == end || entry == 0) - { -+ list->next = NULL; - list->start_of_next_abbrevs = start != end ? start : NULL; - return list; - } -@@ -1144,16 +1143,10 @@ find_and_process_abbrev_set (struct dwarf_section *section, - unsigned char *end = section->start + abbrev_base + abbrev_size; - abbrev_list *list = NULL; - if (free_list) -- list = find_abbrev_list_by_abbrev_offset (abbrev_base, abbrev_offset); -+ list = find_abbrev_list_by_raw_abbrev (start); - if (list == NULL) - { - list = process_abbrev_set (section, start, end); -- if (list) -- { -- list->abbrev_base = abbrev_base; -- list->abbrev_offset = abbrev_offset; -- list->next = NULL; -- } - if (free_list) - *free_list = list; - } --- -2.31.1 - diff --git a/binutils.changes b/binutils.changes index 0085354..9c9a1e4 100644 --- a/binutils.changes +++ b/binutils.changes @@ -1,10 +1,3 @@ -------------------------------------------------------------------- -Thu Sep 1 11:52:52 UTC 2022 - Michael Matz - -- Add binutils-pr29370.diff and their prerequisites - binutils-pr29370-pre1.diff and binutils-pr29370-pre2.diff - for PR29370, aka CVE-2022-38128 [bsc#1203016] - ------------------------------------------------------------------- Fri Aug 26 13:24:35 UTC 2022 - Michael Matz diff --git a/binutils.spec b/binutils.spec index 30e4101..da0b4dc 100644 --- a/binutils.spec +++ b/binutils.spec @@ -139,9 +139,6 @@ Patch41: binutils-fix-relax.diff Patch42: binutils-compat-old-behaviour.diff Patch43: binutils-revert-hlasm-insns.diff Patch44: binutils-pr29482.diff -Patch45: binutils-pr29370-pre1.diff -Patch46: binutils-pr29370-pre2.diff -Patch47: binutils-pr29370.diff Patch100: add-ulp-section.diff Patch90: cross-avr-nesc-as.patch Patch92: cross-avr-omit_section_dynsym.patch @@ -265,9 +262,6 @@ cp ld/ldgram.y ld/ldgram.y.orig %patch43 -p1 %endif %patch44 -p1 -%patch45 -p1 -%patch46 -p1 -%patch47 -p1 %patch100 -p1 %if "%{TARGET}" == "avr" cp gas/config/tc-avr.h gas/config/tc-avr-nesc.h From cfaae36524e339515575ccc4e664d04b8c9ebf9cac224f1ab62b682a8d5f8c9a Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Mon, 17 Oct 2022 15:04:37 +0000 Subject: [PATCH 04/10] - Add binutils-revert-rela.diff to revert back to old behaviour of not ignoring the in-section content of to be relocated fields on x86-64, even though that's a RELA architecture. Compatibility with buggy object files generated by old tools. [bsc#1198422] (forward port from SLE) OBS-URL: https://build.opensuse.org/package/show/devel:gcc/binutils?expand=0&rev=420 --- binutils-revert-rela.diff | 272 ++++++++++++++++++++++++++++++++++++++ binutils.changes | 10 ++ binutils.spec | 11 +- 3 files changed, 289 insertions(+), 4 deletions(-) create mode 100644 binutils-revert-rela.diff diff --git a/binutils-revert-rela.diff b/binutils-revert-rela.diff new file mode 100644 index 0000000..eb8d1fe --- /dev/null +++ b/binutils-revert-rela.diff @@ -0,0 +1,272 @@ +This is for bsc#1198422 + +This essentially reverts commit 17c6c3b99156fe82c1e637e1a5fd9f163ac788c8 +to return back to old behaviour regarding RELA relocs: old binutils +used the relocated field as additional addend, relying on it being +zero for normal RELA behaviour. This isn't correct according to the +psABI, but some old tools (e.g. older ICC) emit object files where +the in-field "addend" is to be used (and record the zero in the A field +of the RELA reloc). This change was included starting with binutils 2.37, +but for older codestreams we want to be compatible with the old (buggy) +behaviour. We revert the change for all relocs and not just those for +which it arguably made some sense or where we had a report about (PLT32). + + +Index: binutils-2.39/bfd/elf64-x86-64.c +=================================================================== +--- binutils-2.39.orig/bfd/elf64-x86-64.c 2022-10-17 16:20:55.074224642 +0200 ++++ binutils-2.39/bfd/elf64-x86-64.c 2022-10-17 16:31:36.128864508 +0200 +@@ -47,127 +47,127 @@ static reloc_howto_type x86_64_elf_howto + bfd_elf_generic_reloc, "R_X86_64_NONE", false, 0, 0x00000000, + false), + HOWTO(R_X86_64_64, 0, 8, 64, false, 0, complain_overflow_dont, +- bfd_elf_generic_reloc, "R_X86_64_64", false, 0, MINUS_ONE, ++ bfd_elf_generic_reloc, "R_X86_64_64", false, MINUS_ONE, MINUS_ONE, + false), + HOWTO(R_X86_64_PC32, 0, 4, 32, true, 0, complain_overflow_signed, +- bfd_elf_generic_reloc, "R_X86_64_PC32", false, 0, 0xffffffff, ++ bfd_elf_generic_reloc, "R_X86_64_PC32", false, 0xffffffff, 0xffffffff, + true), + HOWTO(R_X86_64_GOT32, 0, 4, 32, false, 0, complain_overflow_signed, +- bfd_elf_generic_reloc, "R_X86_64_GOT32", false, 0, 0xffffffff, ++ bfd_elf_generic_reloc, "R_X86_64_GOT32", false, 0xffffffff, 0xffffffff, + false), + HOWTO(R_X86_64_PLT32, 0, 4, 32, true, 0, complain_overflow_signed, +- bfd_elf_generic_reloc, "R_X86_64_PLT32", false, 0, 0xffffffff, ++ bfd_elf_generic_reloc, "R_X86_64_PLT32", false, 0xffffffff, 0xffffffff, + true), + HOWTO(R_X86_64_COPY, 0, 4, 32, false, 0, complain_overflow_bitfield, +- bfd_elf_generic_reloc, "R_X86_64_COPY", false, 0, 0xffffffff, ++ bfd_elf_generic_reloc, "R_X86_64_COPY", false, 0xffffffff, 0xffffffff, + false), + HOWTO(R_X86_64_GLOB_DAT, 0, 8, 64, false, 0, complain_overflow_dont, +- bfd_elf_generic_reloc, "R_X86_64_GLOB_DAT", false, 0, MINUS_ONE, ++ bfd_elf_generic_reloc, "R_X86_64_GLOB_DAT", false, MINUS_ONE, MINUS_ONE, + false), + HOWTO(R_X86_64_JUMP_SLOT, 0, 8, 64, false, 0, complain_overflow_dont, +- bfd_elf_generic_reloc, "R_X86_64_JUMP_SLOT", false, 0, MINUS_ONE, ++ bfd_elf_generic_reloc, "R_X86_64_JUMP_SLOT", false, MINUS_ONE, MINUS_ONE, + false), + HOWTO(R_X86_64_RELATIVE, 0, 8, 64, false, 0, complain_overflow_dont, +- bfd_elf_generic_reloc, "R_X86_64_RELATIVE", false, 0, MINUS_ONE, ++ bfd_elf_generic_reloc, "R_X86_64_RELATIVE", false, MINUS_ONE, MINUS_ONE, + false), + HOWTO(R_X86_64_GOTPCREL, 0, 4, 32, true, 0, complain_overflow_signed, +- bfd_elf_generic_reloc, "R_X86_64_GOTPCREL", false, 0, 0xffffffff, ++ bfd_elf_generic_reloc, "R_X86_64_GOTPCREL", false, 0xffffffff, 0xffffffff, + true), + HOWTO(R_X86_64_32, 0, 4, 32, false, 0, complain_overflow_unsigned, +- bfd_elf_generic_reloc, "R_X86_64_32", false, 0, 0xffffffff, ++ bfd_elf_generic_reloc, "R_X86_64_32", false, 0xffffffff, 0xffffffff, + false), + HOWTO(R_X86_64_32S, 0, 4, 32, false, 0, complain_overflow_signed, +- bfd_elf_generic_reloc, "R_X86_64_32S", false, 0, 0xffffffff, ++ bfd_elf_generic_reloc, "R_X86_64_32S", false, 0xffffffff, 0xffffffff, + false), + HOWTO(R_X86_64_16, 0, 2, 16, false, 0, complain_overflow_bitfield, +- bfd_elf_generic_reloc, "R_X86_64_16", false, 0, 0xffff, false), ++ bfd_elf_generic_reloc, "R_X86_64_16", false, 0xffff, 0xffff, false), + HOWTO(R_X86_64_PC16, 0, 2, 16, true, 0, complain_overflow_bitfield, +- bfd_elf_generic_reloc, "R_X86_64_PC16", false, 0, 0xffff, true), ++ bfd_elf_generic_reloc, "R_X86_64_PC16", false, 0xffff, 0xffff, true), + HOWTO(R_X86_64_8, 0, 1, 8, false, 0, complain_overflow_bitfield, +- bfd_elf_generic_reloc, "R_X86_64_8", false, 0, 0xff, false), ++ bfd_elf_generic_reloc, "R_X86_64_8", false, 0xff, 0xff, false), + HOWTO(R_X86_64_PC8, 0, 1, 8, true, 0, complain_overflow_signed, +- bfd_elf_generic_reloc, "R_X86_64_PC8", false, 0, 0xff, true), ++ bfd_elf_generic_reloc, "R_X86_64_PC8", false, 0xff, 0xff, true), + HOWTO(R_X86_64_DTPMOD64, 0, 8, 64, false, 0, complain_overflow_dont, +- bfd_elf_generic_reloc, "R_X86_64_DTPMOD64", false, 0, MINUS_ONE, ++ bfd_elf_generic_reloc, "R_X86_64_DTPMOD64", false, MINUS_ONE, MINUS_ONE, + false), + HOWTO(R_X86_64_DTPOFF64, 0, 8, 64, false, 0, complain_overflow_dont, +- bfd_elf_generic_reloc, "R_X86_64_DTPOFF64", false, 0, MINUS_ONE, ++ bfd_elf_generic_reloc, "R_X86_64_DTPOFF64", false, MINUS_ONE, MINUS_ONE, + false), + HOWTO(R_X86_64_TPOFF64, 0, 8, 64, false, 0, complain_overflow_dont, +- bfd_elf_generic_reloc, "R_X86_64_TPOFF64", false, 0, MINUS_ONE, ++ bfd_elf_generic_reloc, "R_X86_64_TPOFF64", false, MINUS_ONE, MINUS_ONE, + false), + HOWTO(R_X86_64_TLSGD, 0, 4, 32, true, 0, complain_overflow_signed, +- bfd_elf_generic_reloc, "R_X86_64_TLSGD", false, 0, 0xffffffff, ++ bfd_elf_generic_reloc, "R_X86_64_TLSGD", false, 0xffffffff, 0xffffffff, + true), + HOWTO(R_X86_64_TLSLD, 0, 4, 32, true, 0, complain_overflow_signed, +- bfd_elf_generic_reloc, "R_X86_64_TLSLD", false, 0, 0xffffffff, ++ bfd_elf_generic_reloc, "R_X86_64_TLSLD", false, 0xffffffff, 0xffffffff, + true), + HOWTO(R_X86_64_DTPOFF32, 0, 4, 32, false, 0, complain_overflow_signed, +- bfd_elf_generic_reloc, "R_X86_64_DTPOFF32", false, 0, 0xffffffff, ++ bfd_elf_generic_reloc, "R_X86_64_DTPOFF32", false, 0xffffffff, 0xffffffff, + false), + HOWTO(R_X86_64_GOTTPOFF, 0, 4, 32, true, 0, complain_overflow_signed, +- bfd_elf_generic_reloc, "R_X86_64_GOTTPOFF", false, 0, 0xffffffff, ++ bfd_elf_generic_reloc, "R_X86_64_GOTTPOFF", false, 0xffffffff, 0xffffffff, + true), + HOWTO(R_X86_64_TPOFF32, 0, 4, 32, false, 0, complain_overflow_signed, +- bfd_elf_generic_reloc, "R_X86_64_TPOFF32", false, 0, 0xffffffff, ++ bfd_elf_generic_reloc, "R_X86_64_TPOFF32", false, 0xffffffff, 0xffffffff, + false), + HOWTO(R_X86_64_PC64, 0, 8, 64, true, 0, complain_overflow_dont, +- bfd_elf_generic_reloc, "R_X86_64_PC64", false, 0, MINUS_ONE, ++ bfd_elf_generic_reloc, "R_X86_64_PC64", false, MINUS_ONE, MINUS_ONE, + true), + HOWTO(R_X86_64_GOTOFF64, 0, 8, 64, false, 0, complain_overflow_dont, +- bfd_elf_generic_reloc, "R_X86_64_GOTOFF64", false, 0, MINUS_ONE, ++ bfd_elf_generic_reloc, "R_X86_64_GOTOFF64", false, MINUS_ONE, MINUS_ONE, + false), + HOWTO(R_X86_64_GOTPC32, 0, 4, 32, true, 0, complain_overflow_signed, +- bfd_elf_generic_reloc, "R_X86_64_GOTPC32", false, 0, 0xffffffff, ++ bfd_elf_generic_reloc, "R_X86_64_GOTPC32", false, 0xffffffff, 0xffffffff, + true), + HOWTO(R_X86_64_GOT64, 0, 8, 64, false, 0, complain_overflow_signed, +- bfd_elf_generic_reloc, "R_X86_64_GOT64", false, 0, MINUS_ONE, ++ bfd_elf_generic_reloc, "R_X86_64_GOT64", false, MINUS_ONE, MINUS_ONE, + false), + HOWTO(R_X86_64_GOTPCREL64, 0, 8, 64, true, 0, complain_overflow_signed, +- bfd_elf_generic_reloc, "R_X86_64_GOTPCREL64", false, 0, MINUS_ONE, ++ bfd_elf_generic_reloc, "R_X86_64_GOTPCREL64", false, MINUS_ONE, MINUS_ONE, + true), + HOWTO(R_X86_64_GOTPC64, 0, 8, 64, true, 0, complain_overflow_signed, +- bfd_elf_generic_reloc, "R_X86_64_GOTPC64", false, 0, MINUS_ONE, ++ bfd_elf_generic_reloc, "R_X86_64_GOTPC64", false, MINUS_ONE, MINUS_ONE, + true), + HOWTO(R_X86_64_GOTPLT64, 0, 8, 64, false, 0, complain_overflow_signed, +- bfd_elf_generic_reloc, "R_X86_64_GOTPLT64", false, 0, MINUS_ONE, ++ bfd_elf_generic_reloc, "R_X86_64_GOTPLT64", false, MINUS_ONE, MINUS_ONE, + false), + HOWTO(R_X86_64_PLTOFF64, 0, 8, 64, false, 0, complain_overflow_signed, +- bfd_elf_generic_reloc, "R_X86_64_PLTOFF64", false, 0, MINUS_ONE, ++ bfd_elf_generic_reloc, "R_X86_64_PLTOFF64", false, MINUS_ONE, MINUS_ONE, + false), + HOWTO(R_X86_64_SIZE32, 0, 4, 32, false, 0, complain_overflow_unsigned, +- bfd_elf_generic_reloc, "R_X86_64_SIZE32", false, 0, 0xffffffff, ++ bfd_elf_generic_reloc, "R_X86_64_SIZE32", false, 0xffffffff, 0xffffffff, + false), + HOWTO(R_X86_64_SIZE64, 0, 8, 64, false, 0, complain_overflow_dont, +- bfd_elf_generic_reloc, "R_X86_64_SIZE64", false, 0, MINUS_ONE, ++ bfd_elf_generic_reloc, "R_X86_64_SIZE64", false, MINUS_ONE, MINUS_ONE, + false), + HOWTO(R_X86_64_GOTPC32_TLSDESC, 0, 4, 32, true, 0, + complain_overflow_bitfield, bfd_elf_generic_reloc, +- "R_X86_64_GOTPC32_TLSDESC", false, 0, 0xffffffff, true), ++ "R_X86_64_GOTPC32_TLSDESC", false, 0xffffffff, 0xffffffff, true), + HOWTO(R_X86_64_TLSDESC_CALL, 0, 0, 0, false, 0, + complain_overflow_dont, bfd_elf_generic_reloc, + "R_X86_64_TLSDESC_CALL", + false, 0, 0, false), + HOWTO(R_X86_64_TLSDESC, 0, 8, 64, false, 0, + complain_overflow_dont, bfd_elf_generic_reloc, +- "R_X86_64_TLSDESC", false, 0, MINUS_ONE, false), ++ "R_X86_64_TLSDESC", false, MINUS_ONE, MINUS_ONE, false), + HOWTO(R_X86_64_IRELATIVE, 0, 8, 64, false, 0, complain_overflow_dont, +- bfd_elf_generic_reloc, "R_X86_64_IRELATIVE", false, 0, MINUS_ONE, ++ bfd_elf_generic_reloc, "R_X86_64_IRELATIVE", false, MINUS_ONE, MINUS_ONE, + false), + HOWTO(R_X86_64_RELATIVE64, 0, 8, 64, false, 0, complain_overflow_dont, +- bfd_elf_generic_reloc, "R_X86_64_RELATIVE64", false, 0, MINUS_ONE, ++ bfd_elf_generic_reloc, "R_X86_64_RELATIVE64", false, MINUS_ONE, MINUS_ONE, + false), + HOWTO(R_X86_64_PC32_BND, 0, 4, 32, true, 0, complain_overflow_signed, +- bfd_elf_generic_reloc, "R_X86_64_PC32_BND", false, 0, 0xffffffff, ++ bfd_elf_generic_reloc, "R_X86_64_PC32_BND", false, 0xffffffff, 0xffffffff, + true), + HOWTO(R_X86_64_PLT32_BND, 0, 4, 32, true, 0, complain_overflow_signed, +- bfd_elf_generic_reloc, "R_X86_64_PLT32_BND", false, 0, 0xffffffff, ++ bfd_elf_generic_reloc, "R_X86_64_PLT32_BND", false, 0xffffffff, 0xffffffff, + true), + HOWTO(R_X86_64_GOTPCRELX, 0, 4, 32, true, 0, complain_overflow_signed, +- bfd_elf_generic_reloc, "R_X86_64_GOTPCRELX", false, 0, 0xffffffff, ++ bfd_elf_generic_reloc, "R_X86_64_GOTPCRELX", false, 0xffffffff, 0xffffffff, + true), + HOWTO(R_X86_64_REX_GOTPCRELX, 0, 4, 32, true, 0, complain_overflow_signed, +- bfd_elf_generic_reloc, "R_X86_64_REX_GOTPCRELX", false, 0, 0xffffffff, ++ bfd_elf_generic_reloc, "R_X86_64_REX_GOTPCRELX", false, 0xffffffff, 0xffffffff, + true), + + /* We have a gap in the reloc numbers here. +@@ -188,7 +188,7 @@ static reloc_howto_type x86_64_elf_howto + + /* Use complain_overflow_bitfield on R_X86_64_32 for x32. */ + HOWTO(R_X86_64_32, 0, 4, 32, false, 0, complain_overflow_bitfield, +- bfd_elf_generic_reloc, "R_X86_64_32", false, 0, 0xffffffff, ++ bfd_elf_generic_reloc, "R_X86_64_32", false, 0xffffffff, 0xffffffff, + false) + }; + +Index: binutils-2.39/gas/testsuite/gas/i386/i386.exp +=================================================================== +--- binutils-2.39.orig/gas/testsuite/gas/i386/i386.exp 2022-07-08 11:46:47.000000000 +0200 ++++ binutils-2.39/gas/testsuite/gas/i386/i386.exp 2022-10-17 16:27:41.276966573 +0200 +@@ -1287,7 +1287,6 @@ if [gas_64_check] then { + run_list_test "reloc64" "--defsym _bad_=1" + run_list_test "x86-64-inval-tls" + run_dump_test "mixed-mode-reloc64" +- run_dump_test "rela" + run_dump_test "x86-64-ifunc" + run_dump_test "x86-64-opcode-inval" + run_dump_test "x86-64-opcode-inval-intel" +Index: binutils-2.39/gas/testsuite/gas/i386/rela.d +=================================================================== +--- binutils-2.39.orig/gas/testsuite/gas/i386/rela.d 2022-07-08 11:46:47.000000000 +0200 ++++ /dev/null 1970-01-01 00:00:00.000000000 +0000 +@@ -1,13 +0,0 @@ +-#name: x86-64 rela relocs w/ non-zero relocated fields +-#objdump: -rsj .data +- +-.*: +file format .* +- +-RELOCATION RECORDS FOR \[\.data\]: +- +-OFFSET +TYPE +VALUE +-0*0 R_X86_64_64 *q +-0*8 R_X86_64_32 *l +- +-Contents of section .data: +- 0+0 11 ?11 ?11 ?11 22 ?22 ?22 ?22 33 ?33 ?33 ?33 44 ?44 ?44 ?44 .* +Index: binutils-2.39/gas/testsuite/gas/i386/rela.s +=================================================================== +--- binutils-2.39.orig/gas/testsuite/gas/i386/rela.s 2022-07-08 11:46:47.000000000 +0200 ++++ /dev/null 1970-01-01 00:00:00.000000000 +0000 +@@ -1,14 +0,0 @@ +-# Note: This file is also used by an ld test case. +- +- .text +- .global _start +-_start: +- ret +- +- .data +- .p2align 4 +-l: .long 0x11111111, 0x22222222 +-q: .quad 0x4444444433333333 +- +- .reloc l, BFD_RELOC_64, q +- .reloc q, BFD_RELOC_32, l +Index: binutils-2.39/ld/testsuite/ld-x86-64/rela.d +=================================================================== +--- binutils-2.39.orig/ld/testsuite/ld-x86-64/rela.d 2022-07-08 11:46:48.000000000 +0200 ++++ /dev/null 1970-01-01 00:00:00.000000000 +0000 +@@ -1,10 +0,0 @@ +-#name: x86-64 rela relocs w/ non-zero relocated fields +-#as: --64 +-#source: ${srcdir}/../../../gas/testsuite/gas/i386/rela.s +-#ld: -melf_x86_64 +-#objdump: -sj .data +- +-.*: +file format .* +- +-Contents of section .data: +- *[0-9a-f]*0 .8 ?.. ?.. ?.. 00 ?00 ?00 ?00 .0 ?.. ?.. ?.. 44 ?44 ?44 ?44 .* +Index: binutils-2.39/ld/testsuite/ld-x86-64/x86-64.exp +=================================================================== +--- binutils-2.39.orig/ld/testsuite/ld-x86-64/x86-64.exp 2022-07-26 09:13:10.000000000 +0200 ++++ binutils-2.39/ld/testsuite/ld-x86-64/x86-64.exp 2022-10-17 16:27:41.276966573 +0200 +@@ -286,7 +286,6 @@ run_dump_test "apic" + run_dump_test "pcrel8" + run_dump_test "pcrel16" + run_dump_test "pcrel16-2" +-run_dump_test "rela" + run_dump_test "tlsgd2" + run_dump_test "tlsgd3" + run_dump_test "tlsgd12" diff --git a/binutils.changes b/binutils.changes index 9c9a1e4..4ad7166 100644 --- a/binutils.changes +++ b/binutils.changes @@ -89,6 +89,16 @@ Mon May 2 10:15:26 UTC 2022 - Martin Liška - Start using _multibuild for cross binutils. +------------------------------------------------------------------- +Mon Apr 25 16:25:47 UTC 2022 - Michael Matz + +- Add binutils-revert-rela.diff to revert back to old behaviour + of not ignoring the in-section content of to be relocated + fields on x86-64, even though that's a RELA architecture. + Compatibility with buggy object files generated by old tools. + [bsc#1198422] + (forward port from SLE) + ------------------------------------------------------------------- Mon Apr 11 13:49:19 UTC 2022 - Michael Matz diff --git a/binutils.spec b/binutils.spec index da0b4dc..80f27b5 100644 --- a/binutils.spec +++ b/binutils.spec @@ -16,7 +16,8 @@ # -%define flavor @BUILD_FLAVOR@%{nil} +#define flavor @BUILD_FLAVOR@%{nil} +%define flavor %{nil} %if "%{flavor}" != "" %define cross 1 @@ -104,7 +105,7 @@ Release: 0 # # URL: https://www.gnu.org/software/binutils/ -PreReq: %{install_info_prereq} +#PreReq: %{install_info_prereq} # bug437293 %ifarch ppc64 Obsoletes: binutils-64bit @@ -138,7 +139,8 @@ Patch40: binutils-fix-abierrormsg.diff Patch41: binutils-fix-relax.diff Patch42: binutils-compat-old-behaviour.diff Patch43: binutils-revert-hlasm-insns.diff -Patch44: binutils-pr29482.diff +Patch44: binutils-revert-rela.diff +Patch45: binutils-pr29482.diff Patch100: add-ulp-section.diff Patch90: cross-avr-nesc-as.patch Patch92: cross-avr-omit_section_dynsym.patch @@ -260,8 +262,9 @@ cp ld/ldgram.y ld/ldgram.y.orig %if %{suse_version} < 1550 %patch42 -p1 %patch43 -p1 -%endif %patch44 -p1 +%endif +%patch45 -p1 %patch100 -p1 %if "%{TARGET}" == "avr" cp gas/config/tc-avr.h gas/config/tc-avr-nesc.h From b182f7d94cad241892c9d1c8013aad9e49da3cc024368d552298c45a26b48e96 Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Mon, 17 Oct 2022 15:06:56 +0000 Subject: [PATCH 05/10] Whoops OBS-URL: https://build.opensuse.org/package/show/devel:gcc/binutils?expand=0&rev=421 --- binutils.spec | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/binutils.spec b/binutils.spec index 80f27b5..865828b 100644 --- a/binutils.spec +++ b/binutils.spec @@ -16,8 +16,7 @@ # -#define flavor @BUILD_FLAVOR@%{nil} -%define flavor %{nil} +%define flavor @BUILD_FLAVOR@%{nil} %if "%{flavor}" != "" %define cross 1 @@ -105,7 +104,7 @@ Release: 0 # # URL: https://www.gnu.org/software/binutils/ -#PreReq: %{install_info_prereq} +PreReq: %{install_info_prereq} # bug437293 %ifarch ppc64 Obsoletes: binutils-64bit From b1a0c6a5a8948a09969ebcd036476446b0ba2df19c2c332dd5e92bf705e4b3ff Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Mon, 17 Oct 2022 15:18:05 +0000 Subject: [PATCH 06/10] - SLE toolchain update of binutils. Update to 2.39 from 2.37, which means obsoleting and hence removing these patches: binutils-add-efi-aarch64-1.diff, binutils-add-efi-aarch64-2.diff, binutils-add-efi-aarch64-3.diff, binutils-fix-keepdebug.diff, binutils-add-z16-name.diff. (Fake entry from SLE for tracking purposes:) - For building shim 15.6~rc1 (and later versions) aarch64 image, objcopy needs to support efi-app-aarch64 target. (bsc#1198458) Adds binutils-add-efi-aarch64-1.diff, binutils-add-efi-aarch64-2.diff, binutils-add-efi-aarch64-3.diff . (Fake entry from SLE for tracking purposes:) - Add binutils-fix-keepdebug.diff for fix bsc#1191908, a problem in crash not accepting some of our .ko.debug files. (Fake entry from SLE for tracking purposes:) - Add binutils-add-z16-name.diff so that the now official name z16 for arch14 is recognized. [bsc#1198237] OBS-URL: https://build.opensuse.org/package/show/devel:gcc/binutils?expand=0&rev=422 --- binutils.changes | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/binutils.changes b/binutils.changes index 4ad7166..1ec69d2 100644 --- a/binutils.changes +++ b/binutils.changes @@ -1,3 +1,12 @@ +------------------------------------------------------------------- +Mon Oct 17 15:16:23 UTC 2022 - Michael Matz + +- SLE toolchain update of binutils. Update to 2.39 from 2.37, + which means obsoleting and hence removing these patches: + binutils-add-efi-aarch64-1.diff, binutils-add-efi-aarch64-2.diff, + binutils-add-efi-aarch64-3.diff, binutils-fix-keepdebug.diff, + binutils-add-z16-name.diff. + ------------------------------------------------------------------- Fri Aug 26 13:24:35 UTC 2022 - Michael Matz @@ -50,6 +59,15 @@ Sat Aug 6 08:41:08 UTC 2022 - Martin Liška - Includes fixes for these CVEs: bnc#1142579 aka CVE-2019-1010204 aka PR23765 +------------------------------------------------------------------- +Mon Jun 13 12:09:35 UTC 2022 - Michael Matz + +(Fake entry from SLE for tracking purposes:) +- For building shim 15.6~rc1 (and later versions) aarch64 image, objcopy + needs to support efi-app-aarch64 target. (bsc#1198458) + Adds binutils-add-efi-aarch64-1.diff, + binutils-add-efi-aarch64-2.diff, binutils-add-efi-aarch64-3.diff . + ------------------------------------------------------------------- Wed May 25 10:23:35 UTC 2022 - Martin Liška @@ -68,6 +86,13 @@ Mon May 9 10:18:29 UTC 2022 - Andreas Schwab - On SLE15 and later, use make -Oline to synchronize configure output by lines +------------------------------------------------------------------- +Fri May 6 14:17:19 UTC 2022 - Michael Matz + +(Fake entry from SLE for tracking purposes:) +- Add binutils-fix-keepdebug.diff for fix bsc#1191908, a problem + in crash not accepting some of our .ko.debug files. + ------------------------------------------------------------------- Wed May 4 12:08:27 UTC 2022 - Martin Liška @@ -105,6 +130,13 @@ Mon Apr 11 13:49:19 UTC 2022 - Michael Matz - Update binutils-2.38-branch.diff.gz (to c210342d7f5) to include recognition of 'z16' name for 'arch14' on s390. [bsc#1198237] +------------------------------------------------------------------- +Mon Apr 11 13:43:11 UTC 2022 - Michael Matz + +(Fake entry from SLE for tracking purposes:) +- Add binutils-add-z16-name.diff so that the now official name + z16 for arch14 is recognized. [bsc#1198237] + ------------------------------------------------------------------- Mon Mar 21 16:40:26 UTC 2022 - Marcus Meissner From 278e829c006c2b3a9f29e99b9f2d9e9977859498542b89b4a63b85b2dd7a323e Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Tue, 25 Oct 2022 14:40:05 +0000 Subject: [PATCH 07/10] Accepting request 1031143 from home:Andreas_Schwab:Factory - s390-pic-dso.diff: use %pB instead of %B OBS-URL: https://build.opensuse.org/request/show/1031143 OBS-URL: https://build.opensuse.org/package/show/devel:gcc/binutils?expand=0&rev=423 --- binutils.changes | 5 +++++ s390-pic-dso.diff | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/binutils.changes b/binutils.changes index 1ec69d2..b9cc0c4 100644 --- a/binutils.changes +++ b/binutils.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Tue Oct 25 12:54:34 UTC 2022 - Andreas Schwab + +- s390-pic-dso.diff: use %pB instead of %B + ------------------------------------------------------------------- Mon Oct 17 15:16:23 UTC 2022 - Michael Matz diff --git a/s390-pic-dso.diff b/s390-pic-dso.diff index c5e9826..ec85195 100644 --- a/s390-pic-dso.diff +++ b/s390-pic-dso.diff @@ -19,7 +19,7 @@ Index: bfd/elf32-s390.c + || ELF_ST_VISIBILITY (h->other) != STV_PROTECTED)) + { + (*_bfd_error_handler) -+ (_("%B: relocation %s against `%s' can not be used when " ++ (_("%pB: relocation %s against `%s' can not be used when " + "making a shared object; recompile with -fPIC"), + input_bfd, elf_howto_table[r_type].name, + h->root.root.string); From 2489107f5683784f411d357437c155868258c69399424a0eaf097a635f9f86e3 Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Tue, 25 Oct 2022 15:43:19 +0000 Subject: [PATCH 08/10] Another SLE patch and updating CVE mentions in .changes - Add binutils-maxpagesize.diff for a problem on old code streams, where we would generate too large binaries. - This fixes these CVEs relative to 2.37: [bsc#1188374, bsc#1185597] aka (GCC) PR99935 aka CVE-2021-3648 [bsc#1193929] aka PR28694 aka CVE-2021-45078 [bsc#1194783] aka (GCC) PR98886 aka CVE-2021-46195 [bsc#1197592] aka (GCC) PR105039 aka CVE-2022-27943 [bsc#1202966] aka PR29289 aka CVE-2022-38126 [bsc#1202967] aka PR29290 aka CVE-2022-38127 [bsc#1202969] aka CVE-2021-3826 OBS-URL: https://build.opensuse.org/package/show/devel:gcc/binutils?expand=0&rev=424 --- binutils-maxpagesize.diff | 54 +++++++++++++++++++++++++++++++++++++++ binutils.changes | 14 ++++++++++ binutils.spec | 2 ++ 3 files changed, 70 insertions(+) create mode 100644 binutils-maxpagesize.diff diff --git a/binutils-maxpagesize.diff b/binutils-maxpagesize.diff new file mode 100644 index 0000000..9529719 --- /dev/null +++ b/binutils-maxpagesize.diff @@ -0,0 +1,54 @@ +commit a2267dbfc9e1dd955f78561c40f00afa9ddbe619 +Author: Michael Matz +Date: Thu Oct 20 16:06:57 2022 +0200 + + x86-64: Use only one default max-page-size + + On x86-64 the default ELF_MAXPAGESIZE depends on a configure + option (--disable-separate-code). Since 9833b775 + ("PR28824, relro security issues") we use max-page-size for relro + alignment (with a short interval, from 31b4d3a ("PR28824, relro + security issues, x86 keep COMMONPAGESIZE relro") to its revert + a1faa5ea, where x86-64 only used COMMONPAGESIZE as relro alignment + target). + + But that means that a linker configured with --disable-separate-code + behaves different from one configured with --enable-separate-code + (the default), _even if using "-z {no,}separate-code" option to use + the non-configured behaviour_ . In particular it means that when + configuring with --disable-separate-code the linker will produce + binaries aligned to 2MB pages on disk, and hence generate 2MB + executables for a hello world (and even 6MB when linked with + "-z separate-code"). + + Generally we can't have constants that ultimately land in static + variables be depending on configure options if those only influence + behaviour that is overridable by command line options. + + So, do away with that, make the default MAXPAGESIZE be 4k (as is default + for most x86-64 configs anyway, as most people won't configure with + --disable-separate-code). If people need more they can use the + "-z max-page-size" (with would have been required right now for a + default configure binutils). + + bfd/ + * elf64-x86-64.c (ELF_MAXPAGESIZE): Don't depend on + DEFAULT_LD_Z_SEPARATE_CODE. + +diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c +index f3b54400013..2ae8dffba0f 100644 +--- a/bfd/elf64-x86-64.c ++++ b/bfd/elf64-x86-64.c +@@ -5259,11 +5259,7 @@ elf_x86_64_special_sections[]= + #define ELF_ARCH bfd_arch_i386 + #define ELF_TARGET_ID X86_64_ELF_DATA + #define ELF_MACHINE_CODE EM_X86_64 +-#if DEFAULT_LD_Z_SEPARATE_CODE +-# define ELF_MAXPAGESIZE 0x1000 +-#else +-# define ELF_MAXPAGESIZE 0x200000 +-#endif ++#define ELF_MAXPAGESIZE 0x1000 + #define ELF_COMMONPAGESIZE 0x1000 + + #define elf_backend_can_gc_sections 1 diff --git a/binutils.changes b/binutils.changes index b9cc0c4..2a4713f 100644 --- a/binutils.changes +++ b/binutils.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Tue Oct 25 14:52:30 UTC 2022 - Michael Matz + +- Add binutils-maxpagesize.diff for a problem on old code + streams, where we would generate too large binaries. + ------------------------------------------------------------------- Tue Oct 25 12:54:34 UTC 2022 - Andreas Schwab @@ -11,6 +17,14 @@ Mon Oct 17 15:16:23 UTC 2022 - Michael Matz binutils-add-efi-aarch64-1.diff, binutils-add-efi-aarch64-2.diff, binutils-add-efi-aarch64-3.diff, binutils-fix-keepdebug.diff, binutils-add-z16-name.diff. +- This fixes these CVEs relative to 2.37: + [bsc#1188374, bsc#1185597] aka (GCC) PR99935 aka CVE-2021-3648 + [bsc#1193929] aka PR28694 aka CVE-2021-45078 + [bsc#1194783] aka (GCC) PR98886 aka CVE-2021-46195 + [bsc#1197592] aka (GCC) PR105039 aka CVE-2022-27943 + [bsc#1202966] aka PR29289 aka CVE-2022-38126 + [bsc#1202967] aka PR29290 aka CVE-2022-38127 + [bsc#1202969] aka CVE-2021-3826 ------------------------------------------------------------------- Fri Aug 26 13:24:35 UTC 2022 - Michael Matz diff --git a/binutils.spec b/binutils.spec index 865828b..bc2ce10 100644 --- a/binutils.spec +++ b/binutils.spec @@ -140,6 +140,7 @@ Patch42: binutils-compat-old-behaviour.diff Patch43: binutils-revert-hlasm-insns.diff Patch44: binutils-revert-rela.diff Patch45: binutils-pr29482.diff +Patch46: binutils-maxpagesize.diff Patch100: add-ulp-section.diff Patch90: cross-avr-nesc-as.patch Patch92: cross-avr-omit_section_dynsym.patch @@ -264,6 +265,7 @@ cp ld/ldgram.y ld/ldgram.y.orig %patch44 -p1 %endif %patch45 -p1 +%patch46 -p1 %patch100 -p1 %if "%{TARGET}" == "avr" cp gas/config/tc-avr.h gas/config/tc-avr-nesc.h From f3d315cc8dbd5f2de4b184a30f55907ba747e73c4ebd58e20326c028a929e463 Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Wed, 2 Nov 2022 16:28:43 +0000 Subject: [PATCH 09/10] Mention all the various duplicated tracker entries. Implements [jsc#SLE-25046, jsc#PED-2029, jsc#PED-2035, jsc#PED-2033, jsc#PED-2030, jsc#PED-2038, jsc#PED-2032, jsc#PED-2034, jsc#PED-2031, jsc#SLE-25047] OBS-URL: https://build.opensuse.org/package/show/devel:gcc/binutils?expand=0&rev=425 --- binutils.changes | 3 +++ 1 file changed, 3 insertions(+) diff --git a/binutils.changes b/binutils.changes index 2a4713f..ef1d7a7 100644 --- a/binutils.changes +++ b/binutils.changes @@ -17,6 +17,9 @@ Mon Oct 17 15:16:23 UTC 2022 - Michael Matz binutils-add-efi-aarch64-1.diff, binutils-add-efi-aarch64-2.diff, binutils-add-efi-aarch64-3.diff, binutils-fix-keepdebug.diff, binutils-add-z16-name.diff. + Implements [jsc#SLE-25046, jsc#PED-2029, jsc#PED-2035, jsc#PED-2033, + jsc#PED-2030, jsc#PED-2038, jsc#PED-2032, jsc#PED-2034, jsc#PED-2031, + jsc#SLE-25047] - This fixes these CVEs relative to 2.37: [bsc#1188374, bsc#1185597] aka (GCC) PR99935 aka CVE-2021-3648 [bsc#1193929] aka PR28694 aka CVE-2021-45078 From 2580f878fbdd39a803c4cf8a91779ea5db5c4f8b1a4e5e77b223296d9210bb93 Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Fri, 20 Jan 2023 17:08:10 +0000 Subject: [PATCH 10/10] Accepting request 1060005 from home:dirkmueller:Factory - fix build on x86_64_vX platforms - add arm32-avoid-copyreloc.patch for PR16177 (bsc#1200962) OBS-URL: https://build.opensuse.org/request/show/1060005 OBS-URL: https://build.opensuse.org/package/show/devel:gcc/binutils?expand=0&rev=426 --- arm32-avoid-copyreloc.patch | 61 +++++++++++++++++++++++++++++++++++++ binutils.changes | 10 ++++++ binutils.spec | 10 +++--- 3 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 arm32-avoid-copyreloc.patch diff --git a/arm32-avoid-copyreloc.patch b/arm32-avoid-copyreloc.patch new file mode 100644 index 0000000..f5e18f4 --- /dev/null +++ b/arm32-avoid-copyreloc.patch @@ -0,0 +1,61 @@ +When a writable input section (i.e. data) refers to a symbol defined in an +ET_DYN object, BFD ld for ARM targets generates a COPY dynamic reloc. For +other targets like x86, this situation generates a plain data dynamic +reloc. Gold for ARM also generates the plain data dynamic reloc. + +https://bugzilla.suse.com/show_bug.cgi?id=1200962 +https://sourceware.org/bugzilla/show_bug.cgi?id=16177 + +--- + bfd/elf32-arm.c | 25 +++++++++++++++++++------ + 1 file changed, 19 insertions(+), 6 deletions(-) +Index: binutils-2.39/bfd/elf32-arm.c +=================================================================== +--- binutils-2.39.orig/bfd/elf32-arm.c ++++ binutils-2.39/bfd/elf32-arm.c +@@ -16196,6 +16196,21 @@ elf32_arm_adjust_dynamic_symbol (struct + if (bfd_link_pic (info) || globals->root.is_relocatable_executable) + return true; + ++ /* If -z nocopyreloc was given, we won't generate them either. */ ++ if (info->nocopyreloc) ++ { ++ h->non_got_ref = 0; ++ return true; ++ } ++ ++ /* If we don't find any dynamic relocs in read-only sections, then ++ we'll be keeping the dynamic relocs and avoiding the copy reloc. */ ++ if (!_bfd_elf_readonly_dynrelocs (h)) ++ { ++ h->non_got_ref = 0; ++ return true; ++ } ++ + /* We must allocate the symbol in our .dynbss section, which will + become part of the .bss section of the executable. There will be + an entry for this symbol in the .dynsym section. The dynamic +@@ -16205,9 +16220,9 @@ elf32_arm_adjust_dynamic_symbol (struct + determine the address it must put in the global offset table, so + both the dynamic object and the regular object will refer to the + same memory location for the variable. */ +- /* If allowed, we must generate a R_ARM_COPY reloc to tell the dynamic +- linker to copy the initial value out of the dynamic object and into +- the runtime process image. We need to remember the offset into the ++ /* We must generate a R_ARM_COPY reloc to tell the dynamic linker to ++ copy the initial value out of the dynamic object and into the ++ runtime process image. We need to remember the offset into the + .rel(a).bss section we are going to use. */ + if ((h->root.u.def.section->flags & SEC_READONLY) != 0) + { +@@ -16219,9 +16234,7 @@ elf32_arm_adjust_dynamic_symbol (struct + s = globals->root.sdynbss; + srel = globals->root.srelbss; + } +- if (info->nocopyreloc == 0 +- && (h->root.u.def.section->flags & SEC_ALLOC) != 0 +- && h->size != 0) ++ if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0) + { + elf32_arm_allocate_dynrelocs (info, srel, 1); + h->needs_copy = 1; diff --git a/binutils.changes b/binutils.changes index ef1d7a7..48a2e21 100644 --- a/binutils.changes +++ b/binutils.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Sat Dec 10 10:00:56 UTC 2022 - Dirk Müller + +- fix build on x86_64_vX platforms + ------------------------------------------------------------------- Tue Oct 25 14:52:30 UTC 2022 - Michael Matz @@ -29,6 +34,11 @@ Mon Oct 17 15:16:23 UTC 2022 - Michael Matz [bsc#1202967] aka PR29290 aka CVE-2022-38127 [bsc#1202969] aka CVE-2021-3826 +------------------------------------------------------------------- +Fri Oct 14 15:22:38 UTC 2022 - Dirk Müller + +- add arm32-avoid-copyreloc.patch for PR16177 (bsc#1200962) + ------------------------------------------------------------------- Fri Aug 26 13:24:35 UTC 2022 - Michael Matz diff --git a/binutils.spec b/binutils.spec index bc2ce10..7506275 100644 --- a/binutils.spec +++ b/binutils.spec @@ -94,7 +94,7 @@ Release: 0 %define make_check_handling false %endif # handle all binary object formats supported by SUSE (and a few more) -%ifarch %ix86 %arm aarch64 ia64 ppc ppc64 ppc64le riscv64 s390 s390x x86_64 +%ifarch %ix86 %arm aarch64 ia64 ppc ppc64 ppc64le riscv64 s390 s390x x86_64 %x86_64 %define build_multitarget 1 %else %define build_multitarget 0 @@ -125,6 +125,7 @@ Patch6: unit-at-a-time.patch Patch8: ld-relro.diff Patch9: testsuite.diff Patch10: enable-targets-gold.diff +Patch11: arm32-avoid-copyreloc.patch Patch12: s390-pic-dso.diff Patch14: binutils-build-as-needed.diff Patch15: binutils-znow.patch @@ -168,7 +169,7 @@ Requires: alts PreReq: update-alternatives %endif %if 0%{!?cross:1} && 0%{?suse_version} >= 1310 -%define gold_archs %ix86 aarch64 %arm x86_64 ppc ppc64 ppc64le s390x %sparc +%define gold_archs %ix86 aarch64 %arm x86_64 %x86_64 ppc ppc64 ppc64le s390x %sparc %endif %description gold @@ -218,7 +219,7 @@ The next generation profiling tool for Linux %ifarch %arm %define HOST %{_target_cpu}-suse-linux-gnueabi %else -%define HOST %(echo %{_target_cpu} | sed -e "s/parisc/hppa/" -e "s/i.86/i586/" -e "s/ppc/powerpc/" -e "s/sparc64v.*/sparc64/" -e "s/sparcv.*/sparc/")-suse-linux +%define HOST %(echo %{_target_cpu} | sed -s -e "s/x86_64_v./x86_64/" -e "s/parisc/hppa/" -e "s/i.86/i586/" -e "s/ppc/powerpc/" -e "s/sparc64v.*/sparc64/" -e "s/sparcv.*/sparc/")-suse-linux %endif %define DIST %(echo '%distribution' | sed 's/ (.*)//') @@ -246,6 +247,7 @@ cp ld/ldgram.y ld/ldgram.y.orig %patch8 %patch9 %patch10 +%patch11 -p1 %patch12 %patch14 %patch15 @@ -696,7 +698,7 @@ fi; %{_libdir}/libctf-nobfd.so.* %if %{suse_version} > 1500 -%ifarch %ix86 x86_64 aarch64 +%ifarch %ix86 x86_64 %x86_64 aarch64 %files -n gprofng %defattr(-,root,root) %dir %{_libdir}/gprofng/