From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pj1-x102a.google.com (mail-pj1-x102a.google.com [IPv6:2607:f8b0:4864:20::102a]) by sourceware.org (Postfix) with ESMTPS id 0D6233858434 for ; Wed, 18 Jan 2023 06:27:11 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 0D6233858434 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-x102a.google.com with SMTP id y3-20020a17090a390300b00229add7bb36so1181688pjb.4 for ; Tue, 17 Jan 2023 22:27:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=UsKJSz+WFACq8AxeSkssyOpY7Fs6EeOs9sH5/Jwm6B8=; b=U5S4VeQ4QuWeqXogzW4WK2cXbQT7dY+qzs/tEund9Uku3ORuw69eJXmkdI9mckdPLh 2vEwGdjQMaMSRGIdzSPAC9Mq2Ob/DSU9pLX1ZZL5p9wfdOS5E5L+6HlGx5vN3dT/kd7t qjX9PopkPi1y8haRnWZcS3DBUkkrU/Woihiovf7ZV8uGoUKT3kxFnQZtqrpsoRatK8Ge Xb4leEK11zC/NoGhE2x/7NKG4MUTJNkkMOQbPF8OlJd6sgiSr86ORjpClbM7ShrzIG05 MmoJyiqFWR6uDH2WkWXO3mzvV9e/NRaPgQdLS3Sva72DlLs1P2FglErF9Un42HCTt59U ihrg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=UsKJSz+WFACq8AxeSkssyOpY7Fs6EeOs9sH5/Jwm6B8=; b=cfpluzU8G7fb6xKkttc3IyGjQgeRpN98rVW+VTtqsvLXC1byh65DutkpN0e1JDK7FO 1czZCgoW0XpM/c/Nn2P5CmHKHx4I37d/ockJuKpVx1xgoAejMwZzW5pf1f7lyaDOGoUI wU5uPjMLKczKokefhGpGs3UpQQZw/az6+XnhQWsWOzSI92Gsgxz77VBEhSYuAdRFQBTW A8uvUOPbNmWW+Wsuumovri7h7ursoHXqn9baoVlfKv25Yw7CiEFG55QsMh1G9gnnMvi1 YZ84rMs6zGVRCTeKI+t2D5KsCc4vSLS/wT95nMMp1ATU9J7iiELJL45FWBCzc4uoLeq8 KrFg== X-Gm-Message-State: AFqh2krane3SrMyIGcHvFvTTsiadNNAl/vKs6brUkp7LG6oUbQgNkPYn cAnU20wZprSF3aMZocMFdUzeyKQD1wQ= X-Google-Smtp-Source: AMrXdXvpW7Tk3QPkVQdLQLhZvM+i9rJi8gdFiSG6tomk1UD/p92no1+O91R3nZsXLmSH6DZS0spJLw== X-Received: by 2002:a05:6a20:491a:b0:b5:df4f:6731 with SMTP id ft26-20020a056a20491a00b000b5df4f6731mr6378337pzb.17.1674023229076; Tue, 17 Jan 2023 22:27:09 -0800 (PST) Received: from squeak.grove.modra.org ([2406:3400:51d:8cc0:195b:3277:b45:6442]) by smtp.gmail.com with ESMTPSA id i15-20020a62870f000000b005890c5ed925sm16645908pfe.198.2023.01.17.22.27.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 17 Jan 2023 22:27:08 -0800 (PST) From: Alan Modra To: binutils@sourceware.org Cc: Mark Harmstone Subject: [PATCH 4/4] The fuzzers have found the reloc special functions in coff-aarch64.c Date: Wed, 18 Jan 2023 16:56:57 +1030 Message-Id: <20230118062657.1125934-5-amodra@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230118062657.1125934-1-amodra@gmail.com> References: <20230118062657.1125934-1-amodra@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-3034.6 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: 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. 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. * 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 --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 @@ #include "libcoff.h" +/* For these howto special functions, + output_bfd == NULL => final link, or objdump -W and other calls to + bfd_simple_get_relocated_section_contents + output_bfd != NULL && output_bfd != abfd => ld -r + output_bfd != NULL && output_bfd == abfd => 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 != NULL && output_bfd != abfd) + return bfd_reloc_continue; - op = bfd_getl32 (data + reloc_entry->address); - param = reloc_entry->addend; + if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd, + input_section, reloc_entry->address)) + return bfd_reloc_outofrange; - if (param > 0xfffff || param < -0x100000) - return bfd_reloc_overflow; + uint32_t op = bfd_getl32 (data + reloc_entry->address); + bfd_vma relocation = reloc_entry->addend; + bfd_reloc_status_type ret = bfd_reloc_ok; + if (output_bfd == NULL) + { + if (bfd_is_und_section (symbol->section)) + { + if ((symbol->flags & BSF_WEAK) == 0) + ret = bfd_reloc_undefined; + } + else if (!bfd_is_com_section (symbol->section)) + relocation += (symbol->value + + symbol->section->output_offset + + symbol->section->output_section->vma); + bfd_vma addend = ((op >> 3) & 0x1ffffc) | ((op >> 29) & 0x3); + addend = (addend ^ 0x100000) - 0x100000; + relocation += addend; + relocation -= (reloc_entry->address + + input_section->output_offset + + input_section->output_section->vma); + relocation = (bfd_signed_vma) relocation >> reloc_entry->howto->rightshift; + } + if (relocation + 0x100000 > 0x1fffff) + ret = bfd_reloc_overflow; op &= 0x9f00001f; - op |= (param & 0x1ffffc) << 3; - op |= (param & 0x3) << 29; + op |= (relocation & 0x1ffffc) << 3; + op |= (relocation & 0x3) << 29; bfd_putl32 (op, data + reloc_entry->address); - return bfd_reloc_ok; + return ret; } 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 != NULL && output_bfd != abfd) + return bfd_reloc_continue; - op = bfd_getl32 (data + reloc_entry->address); - param = 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 = bfd_getl32 (data + reloc_entry->address); + bfd_vma relocation = reloc_entry->addend & 0xfff; + int shift; if ((op & 0xff800000) == 0x3d800000) { @@ -93,53 +130,120 @@ coff_aarch64_po12l_reloc (bfd *abfd ATTRIBUTE_UNUSED, shift = op >> 30; } - if (param & ((1 << shift) - 1)) - return bfd_reloc_overflow; + bfd_reloc_status_type ret = bfd_reloc_ok; + if (output_bfd == NULL) + { + if (bfd_is_und_section (symbol->section)) + { + if ((symbol->flags & BSF_WEAK) == 0) + ret = bfd_reloc_undefined; + } + else if (!bfd_is_com_section (symbol->section)) + relocation += (symbol->value + + symbol->section->output_offset + + symbol->section->output_section->vma); + bfd_vma addend = (op >> 10) & 0xfff; + addend <<= shift; + relocation += addend; + } - param >>= shift; + if (relocation & ((1 << shift) - 1)) + ret = bfd_reloc_overflow; op &= 0xffc003ff; - op |= param << 10; + op |= (relocation >> shift << 10) & 0x3ffc00; bfd_putl32 (op, data + reloc_entry->address); - return bfd_reloc_ok; + return ret; } 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 != NULL && output_bfd != abfd) + return bfd_reloc_continue; - 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; - val = reloc_entry->addend; + bfd_vma relocation = reloc_entry->addend; + bfd_reloc_status_type ret = bfd_reloc_ok; + if (output_bfd == NULL) + { + if (bfd_is_und_section (symbol->section)) + { + if ((symbol->flags & BSF_WEAK) == 0) + ret = bfd_reloc_undefined; + } + else if (!bfd_is_com_section (symbol->section)) + relocation += (symbol->value + + symbol->section->output_offset + + symbol->section->output_section->vma); + bfd_vma addend = bfd_getl_signed_32 (data + reloc_entry->address); + relocation += addend; + if (bfd_get_flavour (output_bfd) == bfd_target_coff_flavour + && obj_pe (output_bfd)) + relocation -= pe_data (output_bfd)->pe_opthdr.ImageBase; + else + { + *error_message = "unsupported"; + return bfd_reloc_dangerous; + } + } + + if (relocation + 0x80000000 > 0xffffffff) + ret = bfd_reloc_overflow; - bfd_putl32 ((uint32_t) val, data + reloc_entry->address); + bfd_putl32 (relocation, data + reloc_entry->address); - return bfd_reloc_ok; + return ret; } 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 != NULL && output_bfd != 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 = reloc_entry->addend; + bfd_reloc_status_type ret = bfd_reloc_ok; + if (output_bfd == NULL) + { + if (bfd_is_und_section (symbol->section)) + { + if ((symbol->flags & BSF_WEAK) == 0) + ret = bfd_reloc_undefined; + } + else if (!bfd_is_com_section (symbol->section)) + relocation += (symbol->value + + symbol->section->output_offset); + bfd_vma addend = bfd_getl_signed_32 (data + reloc_entry->address); + relocation += addend; + } + if (relocation > 0xffffffff) + ret = bfd_reloc_overflow; + + bfd_putl32 (relocation, data + reloc_entry->address); - return bfd_reloc_ok; + return ret; } #define coff_aarch64_NULL NULL @@ -438,6 +542,17 @@ coff_pe_aarch64_relocate_section (bfd *output_bfd, || (unsigned long) symndx >= obj_raw_syment_count (input_bfd)) continue; + /* 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: