From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pf1-x434.google.com (mail-pf1-x434.google.com [IPv6:2607:f8b0:4864:20::434]) by sourceware.org (Postfix) with ESMTPS id AB5013858C60 for ; Wed, 8 Sep 2021 11:00:27 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org AB5013858C60 Received: by mail-pf1-x434.google.com with SMTP id i24so1605997pfo.12 for ; Wed, 08 Sep 2021 04:00:27 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:from:to:cc:subject:message-id:mime-version :content-disposition; bh=/R1Qc1T9mysEfMIX8Pu6Z3Iwd4kp2Le1PppwoaVguQA=; b=vUIkoInCQ8hOhtAJTdQGj9m0/id6gp7qp7aEqLVIP5zi873m5cOfGfzkQUGxDTuQ5C Ap10gWVZZvBeaa1LaX3HC/UYNseDO2e+iUefF3wCgHbrv256425gPZG8ssSmEqk0YjKV 1ZZ+SHi4DIZlWE0SU4kDW+sd6R11WqcwA08wDQyssCwaxLP7PLhlfHHjqYUtD0FwqmTL UCVy5sROTLJeUyDwwQE+30qY3c7HyWjKEUYEprqFFCTLYuabON6Je6HbpVHOH9Niou/d XCIZdAQYiPJa/0m4h4Vb1JYjWFS5iVj7bW9RMrwqcxLM5EuE90z5JiDda0MmDcNCMIK7 sMHQ== X-Gm-Message-State: AOAM532NOUFEcJa+VvznnxWRx9sAwZFswmYvmnmGn/z60tuUgvy/csgl J2PjGAFKn4+bbxnQ2s+lU9Eag0gyDmM= X-Google-Smtp-Source: ABdhPJxxf+dN2KfdidVk5jxc4l3OolR9R28jJbUpoCrf53cjslkwSAULGpxKWB1Kj9bt7ApdOfCVvg== X-Received: by 2002:a65:5c83:: with SMTP id a3mr3115013pgt.287.1631098826586; Wed, 08 Sep 2021 04:00:26 -0700 (PDT) Received: from squeak.grove.modra.org (158.106.96.58.static.exetel.com.au. [58.96.106.158]) by smtp.gmail.com with ESMTPSA id x24sm2129021pfr.131.2021.09.08.04.00.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Sep 2021 04:00:25 -0700 (PDT) Received: by squeak.grove.modra.org (Postfix, from userid 1000) id 66BB411401F2; Wed, 8 Sep 2021 20:30:22 +0930 (ACST) Date: Wed, 8 Sep 2021 20:30:22 +0930 From: Alan Modra To: Chenghua Xu , "Maciej W. Rozycki" Cc: binutils@sourceware.org Subject: PR28306, segfault in _bfd_mips_elf_reloc_unshuffle Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline X-Spam-Status: No, score=-3039.1 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.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) 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-List-Received-Date: Wed, 08 Sep 2021 11:00:29 -0000 Protect the _bfd_mips_elf_reloc_unshuffle call in mips16_gprel_reloc by checking the reloc offset. The other changes catch potential buffer overflows when processing relocations near the end of a section. OK to apply? PR 28306 * elf64-mips.c (mips16_gprel_reloc): Sanity check reloc offset. (mips_elf64_gprel32_reloc): Use bfd_reloc_offset_in_range. * elfxx-mips.c (_bfd_mips_elf_gprel16_with_gp): Likewise. (_bfd_mips_elf_hi16_reloc, _bfd_mips_elf_lo16_reloc): Likewise. (_bfd_mips_elf_generic_reloc): Likewise. Comment. * elf32-mips.c (gprel32_with_gp): Use bfd_reloc_offset_in_range. * elfn32-mips.c (gprel32_with_gp): Likewise. (elf_mips_howto_table_rela ): Correct size. diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c index f8467de478b..100e6e57143 100644 --- a/bfd/elf32-mips.c +++ b/bfd/elf32-mips.c @@ -1858,7 +1858,8 @@ gprel32_with_gp (bfd *abfd, asymbol *symbol, arelent *reloc_entry, relocation += symbol->section->output_section->vma; relocation += symbol->section->output_offset; - if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) + if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd, + input_section, reloc_entry->address)) return bfd_reloc_outofrange; /* Set val to the offset into the section or symbol. */ diff --git a/bfd/elf64-mips.c b/bfd/elf64-mips.c index 9ad884fafb6..764c686c0e8 100644 --- a/bfd/elf64-mips.c +++ b/bfd/elf64-mips.c @@ -3581,7 +3581,8 @@ mips_elf64_gprel32_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, relocation += symbol->section->output_section->vma; relocation += symbol->section->output_offset; - if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) + if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd, + input_section, reloc_entry->address)) return bfd_reloc_outofrange; /* Set val to the offset into the section or symbol. */ @@ -3662,6 +3663,10 @@ mips16_gprel_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, if (ret != bfd_reloc_ok) return ret; + if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd, + input_section, reloc_entry->address)) + return bfd_reloc_outofrange; + location = (bfd_byte *) data + reloc_entry->address; _bfd_mips_elf_reloc_unshuffle (abfd, reloc_entry->howto->type, false, location); diff --git a/bfd/elfn32-mips.c b/bfd/elfn32-mips.c index dc607e776d1..2ab0bae976a 100644 --- a/bfd/elfn32-mips.c +++ b/bfd/elfn32-mips.c @@ -877,7 +877,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] = /* No relocation. */ HOWTO (R_MIPS_NONE, /* type */ 0, /* rightshift */ - 0, /* size (0 = byte, 1 = short, 2 = long) */ + 3, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ @@ -3412,7 +3412,8 @@ gprel32_with_gp (bfd *abfd, asymbol *symbol, arelent *reloc_entry, relocation += symbol->section->output_section->vma; relocation += symbol->section->output_offset; - if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) + if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd, + input_section, reloc_entry->address)) return bfd_reloc_outofrange; if (reloc_entry->howto->src_mask == 0) diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index e4827fd17de..aef5ede3ef0 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -2416,7 +2416,8 @@ _bfd_mips_elf_gprel16_with_gp (bfd *abfd, asymbol *symbol, relocation += symbol->section->output_section->vma; relocation += symbol->section->output_offset; - if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) + if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd, + input_section, reloc_entry->address)) return bfd_reloc_outofrange; /* Set val to the offset into the section or symbol. */ @@ -2475,14 +2476,15 @@ static struct mips_hi16 *mips_hi16_list; simplies the relocation handling in gcc. */ bfd_reloc_status_type -_bfd_mips_elf_hi16_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry, +_bfd_mips_elf_hi16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol ATTRIBUTE_UNUSED, void *data, asection *input_section, bfd *output_bfd, char **error_message ATTRIBUTE_UNUSED) { struct mips_hi16 *n; - if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) + if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd, + input_section, reloc_entry->address)) return bfd_reloc_outofrange; n = bfd_malloc (sizeof *n); @@ -2534,7 +2536,8 @@ _bfd_mips_elf_lo16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, bfd_vma vallo; bfd_byte *location = (bfd_byte *) data + reloc_entry->address; - if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) + if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd, + input_section, reloc_entry->address)) return bfd_reloc_outofrange; _bfd_mips_elf_reloc_unshuffle (abfd, reloc_entry->howto->type, false, @@ -2586,7 +2589,7 @@ _bfd_mips_elf_lo16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, bfd_perform_relocation and bfd_install_relocation. */ bfd_reloc_status_type -_bfd_mips_elf_generic_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry, +_bfd_mips_elf_generic_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, void *data ATTRIBUTE_UNUSED, asection *input_section, bfd *output_bfd, char **error_message ATTRIBUTE_UNUSED) @@ -2595,9 +2598,19 @@ _bfd_mips_elf_generic_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry, bfd_reloc_status_type status; bool relocatable; + /* ld -r or gas. */ relocatable = (output_bfd != NULL); - if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) + /* We only use bfd_reloc_offset_in_range for final linking because + mips object files may use relocations that seem to access beyond + section limits. gas/testsuite/gas/mips/dla-reloc.s is an example + that puts R_MIPS_SUB, a 64-bit relocation, on the last + instruction in the section. If final linking that object file + the R_MIPS_SUB won't be processed here since it applies to the + addend for the next reloc rather than the section contents. */ + if (!relocatable + && !bfd_reloc_offset_in_range (reloc_entry->howto, abfd, + input_section, reloc_entry->address)) return bfd_reloc_outofrange; /* Build up the field adjustment in VAL. */ -- Alan Modra Australia Development Lab, IBM