From patchwork Thu Jun 1 00:33:05 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Modra X-Patchwork-Id: 101628 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:6358:3046:b0:115:7a1d:dabb with SMTP id p6csp798178rwl; Wed, 31 May 2023 17:33:21 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ7IK6yAdUmO9Bbwj4C4QNQNq2hGiODB81OmqGo+AOmPSNIsI93BNxz3/1cpNgBol4nWGlej X-Received: by 2002:a17:907:26ca:b0:969:f433:9b54 with SMTP id bp10-20020a17090726ca00b00969f4339b54mr6768735ejc.39.1685579600985; Wed, 31 May 2023 17:33:20 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1685579600; cv=none; d=google.com; s=arc-20160816; b=HKwepb/vilkYyYcJj2vh7Bc5wMWbtPuaGC3PYzggn0NJOHzrUVX0TuGfehG/6GMmSt qcntQXXhMp+oM5kdwdH6bFvma1GeXwVirAPkFcAD+WX0n3ler5ksF0tx8Mp8gJu9egcg n1b6KTaup56Zen/jemYK3b2V/gXZJmezvJnQD8Emb8XWX5bkGnXH9Hk2ogVPM01MJPwP KSHEeE6U/L/qoSw4OFEmsWUVJm3l65LcyzRuKWwIPLEzHwoxM56EkYTaoTbvIGpMrWDU 5n885+R6W39Z30OFSWcAWOMVnR4gRdPFZmM+vEx5nM2uLRaseKN6wKSMY/38O28pUE+J sfyw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:from:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence :content-disposition:mime-version:message-id:subject:to:date :dmarc-filter:delivered-to:dkim-signature:dkim-filter; bh=2ZhgpT6E4yMl+WeyKXMjGYY1SpL41ovoCEAuRQV0Coo=; b=p2gukUihwjYCkfh3AKDXbC2Bwa4LyUDpQ3ifJFZPmYhBgf7phho3luXd0DnLFNEB91 nnrymhUTi4ynfg5BRAZ3/XvySdk3roEqDB3GbF1zWlrYKXwpZdHTBqHaxrzgWvVYdiPO OiGaULZ/z/P9fcyotpcjQxoMDlXlIh/1iEbvVMYYp5hDEf9WrFADeYbN8or7zZclYRv6 kDiIKRYgFacLHvgoorUS6qYDYgcP32XNFW+eUoQuW6UwvH0Q7DMQYwEdVxaopCy5bni1 C8U2XyCGg0xZtNjun9ZmyuNs194IeXK1uszh91TVqQl/+pRUq3u8EU07FjmevummKQP/ ybsw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@sourceware.org header.s=default header.b=Bq+rOwrC; spf=pass (google.com: domain of binutils-bounces+ouuuleilei=gmail.com@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="binutils-bounces+ouuuleilei=gmail.com@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=sourceware.org Received: from sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id m21-20020a1709060d9500b0096f6945e712si2534337eji.1011.2023.05.31.17.33.20 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 31 May 2023 17:33:20 -0700 (PDT) Received-SPF: pass (google.com: domain of binutils-bounces+ouuuleilei=gmail.com@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@sourceware.org header.s=default header.b=Bq+rOwrC; spf=pass (google.com: domain of binutils-bounces+ouuuleilei=gmail.com@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="binutils-bounces+ouuuleilei=gmail.com@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 9B78A3858C30 for ; Thu, 1 Jun 2023 00:33:19 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9B78A3858C30 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1685579599; bh=2ZhgpT6E4yMl+WeyKXMjGYY1SpL41ovoCEAuRQV0Coo=; h=Date:To:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=Bq+rOwrCOV/eybJAzwlA9KRTjP4nCI+fLKjEolQ8SAZGf+g5QN/IN0ZIQy6hK4YTK onnVNyxB521rs3EihtDfSEXHOhwujYPflGCsknpbynNXImsXBnUcpOwSYZXrNdn9kw DWZVwk6AYCUfMYI6AiPAGZ+FchKsjghTaqx19kfo= X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from mail-pl1-x632.google.com (mail-pl1-x632.google.com [IPv6:2607:f8b0:4864:20::632]) by sourceware.org (Postfix) with ESMTPS id 55CAC3858D20 for ; Thu, 1 Jun 2023 00:33:10 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 55CAC3858D20 Received: by mail-pl1-x632.google.com with SMTP id d9443c01a7336-1b04706c974so2193955ad.2 for ; Wed, 31 May 2023 17:33:10 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685579589; x=1688171589; 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=2ZhgpT6E4yMl+WeyKXMjGYY1SpL41ovoCEAuRQV0Coo=; b=F7Mn+o2m8z3tp5vRBR4b4AQ61O3tbzRQqhanO5CxcBSKnO2pEH/IwlUeOqluB7yeMx AIrlQMzom4S6h+I1cKngNE3by92mbnY/M/DRMkrYiFQkvb83doER6o0jo7/87sxlAbwD NzJqhrvPDMsE/cT4/IBJu1AhmDBqZ2jZLSS8hiWmMIBrG5g7CKSfVe9sYj6w+ACtrflx xw9+XIvG02JxUQHx87IY6kJrwXe/a8QdqqCbjUtbMrJsqxIMuuJFPkPwmJYusGq0xOBY 5w9IzvobfoWauFqrPu/tEfxZ/pB4laRVlFmvNrKAbUsGLIKZDdD/x7n1rLo6lWhLHly0 KY7A== X-Gm-Message-State: AC+VfDysy5Ed8fKEzS2iYJeHmNzzPixCeOJlAAcltUrowr2dTtqoGSLN p6ecSCMrTMG7GHTADXtFHLxrqbOM08A= X-Received: by 2002:a17:902:ec8b:b0:1b0:4b65:79db with SMTP id x11-20020a170902ec8b00b001b04b6579dbmr8230981plg.63.1685579588737; Wed, 31 May 2023 17:33:08 -0700 (PDT) Received: from squeak.grove.modra.org ([2406:3400:51d:8cc0:a6ee:d9ea:e91a:eec4]) by smtp.gmail.com with ESMTPSA id y6-20020a17090322c600b001a9b29b6759sm2002685plg.183.2023.05.31.17.33.07 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 31 May 2023 17:33:08 -0700 (PDT) Received: by squeak.grove.modra.org (Postfix, from userid 1000) id 191D4114209E; Thu, 1 Jun 2023 10:03:05 +0930 (ACST) Date: Thu, 1 Jun 2023 10:03:05 +0930 To: binutils@sourceware.org Subject: Harden PowerPC64 OPD handling against fuzzers Message-ID: MIME-Version: 1.0 Content-Disposition: inline X-Spam-Status: No, score=-3034.2 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, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Alan Modra via Binutils From: Alan Modra Reply-To: Alan Modra Errors-To: binutils-bounces+ouuuleilei=gmail.com@sourceware.org Sender: "Binutils" X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1767458315851575349?= X-GMAIL-MSGID: =?utf-8?q?1767458315851575349?= PowerPC64 ELFv1 object files should have at most one .opd section, and OPD handling in elf64-ppc.c makes use of this fact by caching some .opd section info in the per-object bfd.tdata. This was done to avoid another word in the target specific section data. Of course, fuzzers don't respect the ABI, and even non-malicious users can accidentally create multiple .opd sections. So it is better to avoid possible buffer overflows and other confusion when OPD handling for a second .opd section references data for the first .opd section, by keeping the data per-section. The patch also fixes a memory leak, and a corner case where I think we could hit an assertion in opd_entry_value or read out of bounds in ppc64_elf_branch_reloc doing a final link producing non-ppc64 output. (It's a really rare corner case because not only would you need to be linking ppc64 objects to non-ppc64 output, you'd also need a branch reloc symbol to be defined in a .opd section of a non-ppc64 input.) * elf64-ppc.c (is_ppc64_elf): Move earlier in file. (ppc64_elf_branch_reloc): Check symbol bfd before accessing ppc64 elf specific data structures. (struct ppc64_elf_obj_tdata): Move opd union.. (struct _ppc64_elf_section_data): ..to here. (ppc64_elf_before_check_relocs): Allow for opd sec_type already set to sec_opd. (ppc64_elf_check_relocs): Only set sec_type to sec_toc when unset. Error for unexpected toc relocs. (opd_entry_value): Return -1 when non-ppc64 rather than asserting. Check and set sec_type too. Adjust for changed location of contents and relocs. (ppc64_elf_relocate_section): Adjust for changed location of cached .opd relocs. (ppc64_elf_free_cached_info): New function. (bfd_elf64_bfd_free_cached_info): Define. diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 33f4275261d..a977bec2f50 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -90,6 +90,7 @@ static bfd_vma opd_entry_value #define elf_backend_default_execstack 0 #define bfd_elf64_mkobject ppc64_elf_mkobject +#define bfd_elf64_bfd_free_cached_info ppc64_elf_free_cached_info #define bfd_elf64_bfd_reloc_type_lookup ppc64_elf_reloc_type_lookup #define bfd_elf64_bfd_reloc_name_lookup ppc64_elf_reloc_name_lookup #define bfd_elf64_bfd_merge_private_bfd_data ppc64_elf_merge_private_bfd_data @@ -296,6 +297,10 @@ set_abiversion (bfd *abfd, int ver) elf_elfheader (abfd)->e_flags &= ~EF_PPC64_ABI; elf_elfheader (abfd)->e_flags |= ver & EF_PPC64_ABI; } + +#define is_ppc64_elf(bfd) \ + (bfd_get_flavour (bfd) == bfd_target_elf_flavour \ + && elf_object_id (bfd) == PPC64_ELF_DATA) /* Relocation HOWTO's. */ /* Like other ELF RELA targets that don't apply multiple @@ -1462,6 +1467,10 @@ ppc64_elf_branch_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message); + if (symbol->section->owner == NULL + || !is_ppc64_elf (symbol->section->owner)) + return bfd_reloc_continue; + if (strcmp (symbol->section->name, ".opd") == 0 && (symbol->section->owner->flags & DYNAMIC) == 0) { @@ -1478,7 +1487,6 @@ ppc64_elf_branch_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, elf_symbol_type *elfsym = (elf_symbol_type *) symbol; if (symbol->section->owner != abfd - && symbol->section->owner != NULL && abiversion (symbol->section->owner) >= 2) { unsigned int i; @@ -1817,15 +1825,6 @@ struct ppc64_elf_obj_tdata sections means we potentially need one of these for each input bfd. */ struct got_entry tlsld_got; - union - { - /* A copy of relocs before they are modified for --emit-relocs. */ - Elf_Internal_Rela *relocs; - - /* Section contents. */ - bfd_byte *contents; - } opd; - /* Nonzero if this bfd has small toc/got relocs, ie. that expect the reloc to be in the range -32768 to 32767. */ unsigned int has_small_toc_reloc : 1; @@ -1845,10 +1844,6 @@ struct ppc64_elf_obj_tdata #define ppc64_tlsld_got(bfd) \ (&ppc64_elf_tdata (bfd)->tlsld_got) -#define is_ppc64_elf(bfd) \ - (bfd_get_flavour (bfd) == bfd_target_elf_flavour \ - && elf_object_id (bfd) == PPC64_ELF_DATA) - /* Override the generic function because we store some extras. */ static bool @@ -2016,6 +2011,15 @@ struct _ppc64_elf_section_data /* After editing .opd, adjust references to opd local syms. */ long *adjust; + + union + { + /* A copy of relocs before they are modified for --emit-relocs. */ + Elf_Internal_Rela *relocs; + + /* Section contents. */ + bfd_byte *contents; + } u; } opd; /* An array for toc sections, indexed by offset/8. */ @@ -4479,8 +4483,10 @@ ppc64_elf_before_check_relocs (bfd *ibfd, struct bfd_link_info *info) if (opd != NULL && opd->size != 0) { - BFD_ASSERT (ppc64_elf_section_data (opd)->sec_type == sec_normal); - ppc64_elf_section_data (opd)->sec_type = sec_opd; + if (ppc64_elf_section_data (opd)->sec_type == sec_normal) + ppc64_elf_section_data (opd)->sec_type = sec_opd; + else if (ppc64_elf_section_data (opd)->sec_type != sec_opd) + BFD_FAIL (); if (abiversion (ibfd) == 0) set_abiversion (ibfd, 1); @@ -5234,7 +5240,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, return false; ppc64_sec = ppc64_elf_section_data (sec); - if (ppc64_sec->sec_type != sec_toc) + if (ppc64_sec->sec_type == sec_normal) { bfd_size_type amt; @@ -5247,10 +5253,17 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, ppc64_sec->u.toc.add = bfd_zalloc (abfd, amt); if (ppc64_sec->u.toc.add == NULL) return false; - BFD_ASSERT (ppc64_sec->sec_type == sec_normal); ppc64_sec->sec_type = sec_toc; } - BFD_ASSERT (rel->r_offset % 8 == 0); + if (ppc64_sec->sec_type != sec_toc + || rel->r_offset % 8 != 0) + { + info->callbacks->einfo (_("%H: %s reloc unsupported here\n"), + abfd, sec, rel->r_offset, + ppc64_elf_howto_table[r_type]->name); + bfd_set_error (bfd_error_bad_value); + return false; + } ppc64_sec->u.toc.symndx[rel->r_offset / 8] = r_symndx; ppc64_sec->u.toc.add[rel->r_offset / 8] = rel->r_addend; @@ -5531,18 +5544,26 @@ opd_entry_value (asection *opd_sec, Elf_Internal_Rela *lo, *hi, *look; bfd_vma val; + if (!is_ppc64_elf (opd_bfd)) + return (bfd_vma) -1; + + if (ppc64_elf_section_data (opd_sec)->sec_type == sec_normal) + ppc64_elf_section_data (opd_sec)->sec_type = sec_opd; + else if (ppc64_elf_section_data (opd_sec)->sec_type != sec_opd) + return (bfd_vma) -1; + /* No relocs implies we are linking a --just-symbols object, or looking at a final linked executable with addr2line or somesuch. */ if (opd_sec->reloc_count == 0) { - bfd_byte *contents = ppc64_elf_tdata (opd_bfd)->opd.contents; + bfd_byte *contents = ppc64_elf_section_data (opd_sec)->u.opd.u.contents; if (contents == NULL) { if ((opd_sec->flags & SEC_HAS_CONTENTS) == 0 || !bfd_malloc_and_get_section (opd_bfd, opd_sec, &contents)) return (bfd_vma) -1; - ppc64_elf_tdata (opd_bfd)->opd.contents = contents; + ppc64_elf_section_data (opd_sec)->u.opd.u.contents = contents; } /* PR 17512: file: 64b9dfbb. */ @@ -5579,9 +5600,7 @@ opd_entry_value (asection *opd_sec, return val; } - BFD_ASSERT (is_ppc64_elf (opd_bfd)); - - relocs = ppc64_elf_tdata (opd_bfd)->opd.relocs; + relocs = ppc64_elf_section_data (opd_sec)->u.opd.u.relocs; if (relocs == NULL) relocs = _bfd_elf_link_read_relocs (opd_bfd, opd_sec, NULL, NULL, true); /* PR 17512: file: df8e1fd6. */ @@ -18055,13 +18074,14 @@ ppc64_elf_relocate_section (bfd *output_bfd, adjusted. Worse, reloc symbol indices will be for the output file rather than the input. Save a copy of the relocs for opd_entry_value. */ - if (is_opd && (info->emitrelocations || bfd_link_relocatable (info))) + if (is_opd + && (info->emitrelocations || bfd_link_relocatable (info)) + && input_section->reloc_count != 0) { bfd_size_type amt; amt = input_section->reloc_count * sizeof (Elf_Internal_Rela); rel = bfd_alloc (input_bfd, amt); - BFD_ASSERT (ppc64_elf_tdata (input_bfd)->opd.relocs == NULL); - ppc64_elf_tdata (input_bfd)->opd.relocs = rel; + ppc64_elf_section_data (input_section)->u.opd.u.relocs = rel; if (rel == NULL) return false; memcpy (rel, relocs, amt); @@ -18376,6 +18396,19 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd, return true; } +static bool +ppc64_elf_free_cached_info (bfd *abfd) +{ + if (abfd->sections) + for (asection *opd = bfd_get_section_by_name (abfd, ".opd"); + opd != NULL; + opd = bfd_get_next_section_by_name (NULL, opd)) + if (opd->reloc_count == 0) + free (ppc64_elf_section_data (opd)->u.opd.u.contents); + + return _bfd_free_cached_info (abfd); +} + #include "elf64-target.h" /* FreeBSD support */