From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pj1-x1036.google.com (mail-pj1-x1036.google.com [IPv6:2607:f8b0:4864:20::1036]) by sourceware.org (Postfix) with ESMTPS id 4C20C3858D1E for ; Mon, 6 Feb 2023 09:37:02 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 4C20C3858D1E Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-pj1-x1036.google.com with SMTP id d2so7380747pjd.5 for ; Mon, 06 Feb 2023 01:37:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-disposition:mime-version:message-id:subject:to:from:date :from:to:cc:subject:date:message-id:reply-to; bh=/ddXlKTP54E3mamzLNf8xPNq56kQ8NihwKsZI6mY32A=; b=Q8Z4skP8qCpNTBze2vWupm3lEc/OupAlMVqtBwdiOY/XY94V0q364S0wcR3NFHH1xG iew/SH3E06Tlzo41lExq1t7m6Y9Pd5L/fefDfiHo/TcBjZ1gvhdGHHEutNwFRNLrzMK8 j9u2lMcitI8i6/aitcQNRz4UKLYkGbVBE1ybb9dchtSfbChSzvYg3gQUnBhfANafuInD zoKXDNgMXFYs+EbXEXDcNs8PBemza/y+55S0WutMO6WCtfZeO0F6KQ73ydq2YcZFKbx/ 2GXCvgme7ADkNf+0LqCHJP5Q6255Bojv4kzNaXvIYKxIuDLJOTOxvSsJREboo0zI37nN 2DUw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-disposition:mime-version:message-id:subject:to:from:date :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=/ddXlKTP54E3mamzLNf8xPNq56kQ8NihwKsZI6mY32A=; b=kBw7Wf+z1r4IEk5bnvffQ0EnxzzxRb/wdVG82CJp5F1hCWdTWRslbGxOW2HbWMEOOW k69cIL4+bBySusyIEz/r+FSZW9UliEEcItJ41c2wYCsDaFy/Ow86Us1hxRnJJQ1REmJp XNYGfu5MXZVmCCKwoF/xEkVzy9LKBkkQZj1UhfI85Ke50sH73002mfLXGFCZH9TG9L0n DCFzK+NSvpR2E+2SXR1zg/PAcfB27fEIJCUc41856nretqgD0Ge+4lZtHXyNFWsRYe8j +2xzA3NeSiLtJAxIFZO1MP8kSafm0aC6Wptz9rP8sB7nhyDrSI2oYAR1WUkCPyGeIiGo u4tA== X-Gm-Message-State: AO0yUKX0NURKxJ+0R40kxYVMtF3602n5MbfsM/iuZHA7YQsQm9wLG+9p GUPFbjC/rF3qYg4ZubGM5tocvTVZ2qk= X-Google-Smtp-Source: AK7set8bAW8zDC2QwCj/p8c8BYqehszlAQoyxgb6KOI1M+CgoqhdZPSVrz/0qPFtYBXql5z130xqrw== X-Received: by 2002:a17:902:ea12:b0:194:828d:62b0 with SMTP id s18-20020a170902ea1200b00194828d62b0mr25339205plg.48.1675676221035; Mon, 06 Feb 2023 01:37:01 -0800 (PST) Received: from squeak.grove.modra.org ([2406:3400:51d:8cc0:8595:7eb:ede9:c45]) by smtp.gmail.com with ESMTPSA id e12-20020a170902784c00b00192b23b8451sm6382062pln.108.2023.02.06.01.37.00 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 06 Feb 2023 01:37:00 -0800 (PST) Received: by squeak.grove.modra.org (Postfix, from userid 1000) id 3B8561142CDD; Mon, 6 Feb 2023 20:06:58 +1030 (ACDT) Date: Mon, 6 Feb 2023 20:06:58 +1030 From: Alan Modra To: binutils@sourceware.org Subject: Resetting section vma after _bfd_dwarf2_find_nearest_line Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline X-Spam-Status: No, score=-3035.0 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,GIT_PATCH_0,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: There are failure paths in _bfd_dwarf2_slurp_debug_info that can result in altered section vmas. Also, when setting ET_REL section vmas it's not too difficult to handle cases where the original vma was non-zero, so do that too. This patch was really in response to an addr2line buffer overflow processing a fuzzed mips relocatable object file. The file had a number of .debug_info sections with relocations that included lo16 and hi16 relocs, and in that order. At least one section VMA was non-zero. This resulted in processing of DWARF info twice, once via the call to _bfd_dwarf2_find_nearest_line in _bfd_mips_elf_find_nearest_line, and because that failed leaving VMAs altered, the second via the call in _bfd_elf_find_nearest_line. The first call left entries on mips_hi16_list pointing at buffers allocated during the first call, the second call processed the mips_hi16_list after the buffers had been freed. (At least when running with asan and under valgrind. Under gdb with a non-asan addr2line the second call allocated exactly the same buffer and the bug didn't show.) Now I don't really care too much what happens with fuzzed files, but the logic in _bfd_dwarf2_find_nearest_line is meant to result in only one read of .debug_info, not multiple reads of the same info when there are errors. This patch fixes that problem. * dwarf2.c (struct adjusted_section): Add orig_vma. (unset_sections): Reset vma to it. (place_sections): Handle non-zero vma too. Save orig_vma. (_bfd_dwarf2_slurp_debug_info): Tidy. Correct outdated comment. On error returns after calling place_sections, call unset_sections. (_bfd_dwarf2_find_nearest_line_with_alt): Simplify call to unset_sections. diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c index 835851e6afc..ab5a9f37ec1 100644 --- a/bfd/dwarf2.c +++ b/bfd/dwarf2.c @@ -82,6 +82,7 @@ struct adjusted_section { asection *section; bfd_vma adj_vma; + bfd_vma orig_vma; }; /* A trie to map quickly from address range to compilation unit. @@ -4952,7 +4953,7 @@ unset_sections (struct dwarf2_debug *stash) i = stash->adjusted_section_count; p = stash->adjusted_sections; for (; i > 0; i--, p++) - p->section->vma = 0; + p->section->vma = p->orig_vma; } /* Set VMAs for allocated and .debug_info sections in ORIG_BFD, a @@ -4993,10 +4994,9 @@ place_sections (bfd *orig_bfd, struct dwarf2_debug *stash) { int is_debug_info; - if ((sect->output_section != NULL - && sect->output_section != sect - && (sect->flags & SEC_DEBUGGING) == 0) - || sect->vma != 0) + if (sect->output_section != NULL + && sect->output_section != sect + && (sect->flags & SEC_DEBUGGING) == 0) continue; is_debug_info = (strcmp (sect->name, debug_info_name) == 0 @@ -5037,10 +5037,9 @@ place_sections (bfd *orig_bfd, struct dwarf2_debug *stash) bfd_size_type sz; int is_debug_info; - if ((sect->output_section != NULL - && sect->output_section != sect - && (sect->flags & SEC_DEBUGGING) == 0) - || sect->vma != 0) + if (sect->output_section != NULL + && sect->output_section != sect + && (sect->flags & SEC_DEBUGGING) == 0) continue; is_debug_info = (strcmp (sect->name, debug_info_name) == 0 @@ -5052,24 +5051,17 @@ place_sections (bfd *orig_bfd, struct dwarf2_debug *stash) sz = sect->rawsize ? sect->rawsize : sect->size; - if (is_debug_info) - { - BFD_ASSERT (sect->alignment_power == 0); - sect->vma = last_dwarf; - last_dwarf += sz; - } - else - { - /* Align the new address to the current section - alignment. */ - last_vma = ((last_vma - + ~(-((bfd_vma) 1 << sect->alignment_power))) - & (-((bfd_vma) 1 << sect->alignment_power))); - sect->vma = last_vma; - last_vma += sz; - } - p->section = sect; + p->orig_vma = sect->vma; + + bfd_vma *v = is_debug_info ? &last_dwarf : &last_vma; + /* Align the new address to the current section + alignment. */ + bfd_vma mask = -(bfd_vma) 1 << sect->alignment_power; + *v = (*v + ~mask) & mask; + sect->vma = *v; + *v += sz; + p->adj_vma = sect->vma; p++; } @@ -5379,7 +5371,6 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd, void **pinfo, bool do_place) { - size_t amt = sizeof (struct dwarf2_debug); bfd_size_type total_size; asection *msec; struct dwarf2_debug *stash = (struct dwarf2_debug *) *pinfo; @@ -5401,11 +5392,11 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd, return false; } _bfd_dwarf2_cleanup_debug_info (abfd, pinfo); - memset (stash, 0, amt); + memset (stash, 0, sizeof (*stash)); } else { - stash = (struct dwarf2_debug *) bfd_zalloc (abfd, amt); + stash = (struct dwarf2_debug *) bfd_zalloc (abfd, sizeof (*stash)); if (! stash) return false; *pinfo = stash; @@ -5482,14 +5473,11 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd, /* There can be more than one DWARF2 info section in a BFD these days. First handle the easy case when there's only one. If - there's more than one, try case two: none of the sections is - compressed. In that case, read them all in and produce one - large stash. We do this in two passes - in the first pass we + there's more than one, try case two: read them all in and produce + one large stash. We do this in two passes - in the first pass we just accumulate the section sizes, and in the second pass we read in the section's contents. (The allows us to avoid - reallocing the data as we add sections to the stash.) If - some or all sections are compressed, then do things the slow - way, with a bunch of reallocs. */ + reallocing the data as we add sections to the stash.) */ if (! find_debug_info (debug_bfd, debug_sections, msec)) { @@ -5498,7 +5486,7 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd, if (! read_section (debug_bfd, &stash->debug_sections[debug_info], symbols, 0, &stash->f.dwarf_info_buffer, &total_size)) - return false; + goto restore_vma; } else { @@ -5508,19 +5496,19 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd, msec = find_debug_info (debug_bfd, debug_sections, msec)) { if (_bfd_section_size_insane (debug_bfd, msec)) - return false; + goto restore_vma; /* Catch PR25070 testcase overflowing size calculation here. */ if (total_size + msec->size < total_size) { bfd_set_error (bfd_error_no_memory); - return false; + goto restore_vma; } total_size += msec->size; } stash->f.dwarf_info_buffer = (bfd_byte *) bfd_malloc (total_size); if (stash->f.dwarf_info_buffer == NULL) - return false; + goto restore_vma; total_size = 0; for (msec = find_debug_info (debug_bfd, debug_sections, NULL); @@ -5536,7 +5524,7 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd, if (!(bfd_simple_get_relocated_section_contents (debug_bfd, msec, stash->f.dwarf_info_buffer + total_size, symbols))) - return false; + goto restore_vma; total_size += size; } @@ -5545,6 +5533,10 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd, stash->f.info_ptr = stash->f.dwarf_info_buffer; stash->f.dwarf_info_size = total_size; return true; + + restore_vma: + unset_sections (stash); + return false; } /* Parse the next DWARF2 compilation unit at FILE->INFO_PTR. */ @@ -6038,8 +6030,7 @@ _bfd_dwarf2_find_nearest_line_with_alt } } - if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0) - unset_sections (stash); + unset_sections (stash); return found; } -- Alan Modra Australia Development Lab, IBM