From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1062) id AD69B3858C52; Thu, 19 Jan 2023 07:14:33 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org AD69B3858C52 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Alan Modra To: bfd-cvs@sourceware.org Subject: [binutils-gdb] The fuzzers have found the reloc special functions in coff-aarch64.c X-Act-Checkin: binutils-gdb X-Git-Author: Alan Modra X-Git-Refname: refs/heads/master X-Git-Oldrev: f07170eb86314cbb9ef3e10d19381779a4656d19 X-Git-Newrev: 066bd434118044487e69a9fbc5cacdee60326595 Message-Id: <20230119071433.AD69B3858C52@sourceware.org> Date: Thu, 19 Jan 2023 07:14:33 +0000 (GMT) X-BeenThere: binutils-cvs@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Binutils-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 19 Jan 2023 07:14:33 -0000 https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3D066bd4341180= 44487e69a9fbc5cacdee60326595 commit 066bd434118044487e69a9fbc5cacdee60326595 Author: Alan Modra Date: Tue Jan 17 21:53:00 2023 +1030 The fuzzers have found the reloc special functions in coff-aarch64.c =20 All of them need a bfd_reloc_offset_in_range check before accessing data + reloc_entry->address. This patch adds the missing checks and sanity checks reloc offsets in coff_pe_aarch64_relocate_section too. =20 All of them also need changing to support objdump -W calls to bfd_simple_get_relocated_section_contents. At least, secrel_reloc needs the support, the others might not be present in dwarf debug sections. =20 * coff-aarch64.c (coff_aarch64_rel21_reloc): Range check reloc offset. Support final-linking. (coff_aarch64_po12l_reloc): Likewise. (coff_aarch64_addr32nb_reloc): Likewise. (coff_aarch64_secrel_reloc): Likewise. (coff_pe_aarch64_relocate_section): Range check reloc offset. Diff: --- bfd/coff-aarch64.c | 199 ++++++++++++++++++++++++++++++++++++++++++-------= ---- 1 file changed, 157 insertions(+), 42 deletions(-) diff --git a/bfd/coff-aarch64.c b/bfd/coff-aarch64.c index 7057396f6dd..73fa2442dfe 100644 --- a/bfd/coff-aarch64.c +++ b/bfd/coff-aarch64.c @@ -39,48 +39,85 @@ =20 #include "libcoff.h" =20 +/* For these howto special functions, + output_bfd =3D=3D NULL =3D> final link, or objdump -W and other calls to + bfd_simple_get_relocated_section_contents + output_bfd !=3D NULL && output_bfd !=3D abfd =3D> ld -r + output_bfd !=3D NULL && output_bfd =3D=3D abfd =3D> gas. + FIXME: ld -r is punted to bfd_perform_relocation. This won't be + correct for cases where the addend needs to be adjusted, eg. for + relocations against section symbols, and the field is split because + bfd_perform_relocation can't write addends to split relocation fields. = */ + static bfd_reloc_status_type -coff_aarch64_rel21_reloc (bfd *abfd ATTRIBUTE_UNUSED, +coff_aarch64_rel21_reloc (bfd *abfd, arelent *reloc_entry, - asymbol *symbol ATTRIBUTE_UNUSED, + asymbol *symbol, void *data, - asection *input_section ATTRIBUTE_UNUSED, - bfd *output_bfd ATTRIBUTE_UNUSED, + asection *input_section, + bfd *output_bfd, char **error_message ATTRIBUTE_UNUSED) { - uint32_t op; - int32_t param; + if (output_bfd !=3D NULL && output_bfd !=3D abfd) + return bfd_reloc_continue; =20 - op =3D bfd_getl32 (data + reloc_entry->address); - param =3D reloc_entry->addend; + if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd, + input_section, reloc_entry->address)) + return bfd_reloc_outofrange; =20 - if (param > 0xfffff || param < -0x100000) - return bfd_reloc_overflow; + uint32_t op =3D bfd_getl32 (data + reloc_entry->address); + bfd_vma relocation =3D reloc_entry->addend; + bfd_reloc_status_type ret =3D bfd_reloc_ok; + if (output_bfd =3D=3D NULL) + { + if (bfd_is_und_section (symbol->section)) + { + if ((symbol->flags & BSF_WEAK) =3D=3D 0) + ret =3D bfd_reloc_undefined; + } + else if (!bfd_is_com_section (symbol->section)) + relocation +=3D (symbol->value + + symbol->section->output_offset + + symbol->section->output_section->vma); + bfd_vma addend =3D ((op >> 3) & 0x1ffffc) | ((op >> 29) & 0x3); + addend =3D (addend ^ 0x100000) - 0x100000; + relocation +=3D addend; + relocation -=3D (reloc_entry->address + + input_section->output_offset + + input_section->output_section->vma); + relocation =3D (bfd_signed_vma) relocation >> reloc_entry->howto->ri= ghtshift; + } + if (relocation + 0x100000 > 0x1fffff) + ret =3D bfd_reloc_overflow; =20 op &=3D 0x9f00001f; - op |=3D (param & 0x1ffffc) << 3; - op |=3D (param & 0x3) << 29; + op |=3D (relocation & 0x1ffffc) << 3; + op |=3D (relocation & 0x3) << 29; =20 bfd_putl32 (op, data + reloc_entry->address); =20 - return bfd_reloc_ok; + return ret; } =20 static bfd_reloc_status_type -coff_aarch64_po12l_reloc (bfd *abfd ATTRIBUTE_UNUSED, +coff_aarch64_po12l_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol ATTRIBUTE_UNUSED, void *data, - asection *input_section ATTRIBUTE_UNUSED, - bfd *output_bfd ATTRIBUTE_UNUSED, + asection *input_section, + bfd *output_bfd, char **error_message ATTRIBUTE_UNUSED) { - uint32_t op; - int32_t param; - uint8_t shift; + if (output_bfd !=3D NULL && output_bfd !=3D abfd) + return bfd_reloc_continue; =20 - op =3D bfd_getl32 (data + reloc_entry->address); - param =3D reloc_entry->addend & 0xfff; + if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd, + input_section, reloc_entry->address)) + return bfd_reloc_outofrange; + + uint32_t op =3D bfd_getl32 (data + reloc_entry->address); + bfd_vma relocation =3D reloc_entry->addend & 0xfff; + int shift; =20 if ((op & 0xff800000) =3D=3D 0x3d800000) { @@ -93,53 +130,120 @@ coff_aarch64_po12l_reloc (bfd *abfd ATTRIBUTE_UNUSED, shift =3D op >> 30; } =20 - if (param & ((1 << shift) - 1)) - return bfd_reloc_overflow; + bfd_reloc_status_type ret =3D bfd_reloc_ok; + if (output_bfd =3D=3D NULL) + { + if (bfd_is_und_section (symbol->section)) + { + if ((symbol->flags & BSF_WEAK) =3D=3D 0) + ret =3D bfd_reloc_undefined; + } + else if (!bfd_is_com_section (symbol->section)) + relocation +=3D (symbol->value + + symbol->section->output_offset + + symbol->section->output_section->vma); + bfd_vma addend =3D (op >> 10) & 0xfff; + addend <<=3D shift; + relocation +=3D addend; + } =20 - param >>=3D shift; + if (relocation & ((1 << shift) - 1)) + ret =3D bfd_reloc_overflow; =20 op &=3D 0xffc003ff; - op |=3D param << 10; + op |=3D (relocation >> shift << 10) & 0x3ffc00; =20 bfd_putl32 (op, data + reloc_entry->address); =20 - return bfd_reloc_ok; + return ret; } =20 static bfd_reloc_status_type -coff_aarch64_addr32nb_reloc (bfd *abfd ATTRIBUTE_UNUSED, +coff_aarch64_addr32nb_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol ATTRIBUTE_UNUSED, void *data, - asection *input_section ATTRIBUTE_UNUSED, - bfd *output_bfd ATTRIBUTE_UNUSED, - char **error_message ATTRIBUTE_UNUSED) + asection *input_section, + bfd *output_bfd, + char **error_message) { - uint64_t val; + if (output_bfd !=3D NULL && output_bfd !=3D abfd) + return bfd_reloc_continue; =20 - if ((int64_t) reloc_entry->addend > 0x7fffffff - || (int64_t) reloc_entry->addend < -0x7fffffff) - return bfd_reloc_overflow; + if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd, + input_section, reloc_entry->address)) + return bfd_reloc_outofrange; =20 - val =3D reloc_entry->addend; + bfd_vma relocation =3D reloc_entry->addend; + bfd_reloc_status_type ret =3D bfd_reloc_ok; + if (output_bfd =3D=3D NULL) + { + if (bfd_is_und_section (symbol->section)) + { + if ((symbol->flags & BSF_WEAK) =3D=3D 0) + ret =3D bfd_reloc_undefined; + } + else if (!bfd_is_com_section (symbol->section)) + relocation +=3D (symbol->value + + symbol->section->output_offset + + symbol->section->output_section->vma); + bfd_vma addend =3D bfd_getl_signed_32 (data + reloc_entry->address); + relocation +=3D addend; + if (bfd_get_flavour (output_bfd) =3D=3D bfd_target_coff_flavour + && obj_pe (output_bfd)) + relocation -=3D pe_data (output_bfd)->pe_opthdr.ImageBase; + else + { + *error_message =3D "unsupported"; + return bfd_reloc_dangerous; + } + } + + if (relocation + 0x80000000 > 0xffffffff) + ret =3D bfd_reloc_overflow; =20 - bfd_putl32 ((uint32_t) val, data + reloc_entry->address); + bfd_putl32 (relocation, data + reloc_entry->address); =20 - return bfd_reloc_ok; + return ret; } =20 static bfd_reloc_status_type -coff_aarch64_secrel_reloc (bfd *abfd ATTRIBUTE_UNUSED, +coff_aarch64_secrel_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol ATTRIBUTE_UNUSED, void *data, - asection *input_section ATTRIBUTE_UNUSED, - bfd *output_bfd ATTRIBUTE_UNUSED, + asection *input_section, + bfd *output_bfd, char **error_message ATTRIBUTE_UNUSED) { - bfd_putl32 (reloc_entry->addend, data + reloc_entry->address); + if (output_bfd !=3D NULL && output_bfd !=3D abfd) + return bfd_reloc_continue; + + if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd, + input_section, reloc_entry->address)) + return bfd_reloc_outofrange; + + bfd_vma relocation =3D reloc_entry->addend; + bfd_reloc_status_type ret =3D bfd_reloc_ok; + if (output_bfd =3D=3D NULL) + { + if (bfd_is_und_section (symbol->section)) + { + if ((symbol->flags & BSF_WEAK) =3D=3D 0) + ret =3D bfd_reloc_undefined; + } + else if (!bfd_is_com_section (symbol->section)) + relocation +=3D (symbol->value + + symbol->section->output_offset); + bfd_vma addend =3D bfd_getl_signed_32 (data + reloc_entry->address); + relocation +=3D addend; + } + if (relocation > 0xffffffff) + ret =3D bfd_reloc_overflow; + + bfd_putl32 (relocation, data + reloc_entry->address); =20 - return bfd_reloc_ok; + return ret; } =20 #define coff_aarch64_NULL NULL @@ -438,6 +542,17 @@ coff_pe_aarch64_relocate_section (bfd *output_bfd, || (unsigned long) symndx >=3D obj_raw_syment_count (input_bfd)) continue; =20 + /* All the relocs handled below operate on 4 bytes. */ + if (input_section->size < rel->r_vaddr + || input_section->size - rel->r_vaddr < 4) + { + _bfd_error_handler + /* xgettext: c-format */ + (_("%pB: bad reloc address %#" PRIx64 " in section `%pA'"), + input_bfd, (uint64_t) rel->r_vaddr, input_section); + continue; + } + switch (rel->r_type) { case IMAGE_REL_ARM64_ADDR32NB: