From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pg1-x542.google.com (mail-pg1-x542.google.com [IPv6:2607:f8b0:4864:20::542]) by sourceware.org (Postfix) with ESMTPS id 7671F3857C44 for ; Thu, 17 Sep 2020 08:20:25 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 7671F3857C44 Received: by mail-pg1-x542.google.com with SMTP id s65so941916pgb.0 for ; Thu, 17 Sep 2020 01:20:25 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:mime-version :content-disposition:user-agent; bh=zaX7a8MC1WL22C0YB/BINHFITm1teMNyi/v9YVp8000=; b=KiXfTn2CUXKt35pd2qPqqw+pMf2nfhPM56soT2AbwiNYsN3A/5J3XGuKF1dw6KUuAC KzjMNQn6XMHrAFc26EfO75X1CpkklfR4pBnioRTiPk6VzoIyn2N+lfYhPXEDFnKmxZ62 UWJz9gTtBdWwX5alheL7Zd0AJM8Xr/pvIsmTLUiBqVFX9LD0ww1zLSlFR5VSadYRVfxX QpVbQCTbp73rjktl2MeI+Q2kWi+X475fP2YyryFqfe/n/3ZfcO0ugznk6sRBjE1zKyR9 rR25NY40krp6bezEbtrnuZP0BHBuTubN5Hue596rbjJiXRQO0qDftso7zkBzywEvaid8 F4OQ== X-Gm-Message-State: AOAM531oGHSIhlqp+0CQK2zLbECMRjwp/pOm5sjcOx1nHz2xny39zorP 15b949ADgqBi0Ry8nfFlBqugwpEBSFQ= X-Google-Smtp-Source: ABdhPJy6y7CQOkgW5rrcj3/pwji/ojoyXk/VxwjEv+OxDHWYC8Px3KH/TBhOqnqZ2TxP+9ElR53WoA== X-Received: by 2002:a05:6a00:15c8:b029:142:2501:35ca with SMTP id o8-20020a056a0015c8b0290142250135camr10306822pfu.42.1600330823024; Thu, 17 Sep 2020 01:20:23 -0700 (PDT) Received: from bubble.grove.modra.org ([2406:3400:51d:8cc0:5d86:d351:6129:ba7f]) by smtp.gmail.com with ESMTPSA id q13sm5320638pjj.14.2020.09.17.01.20.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 17 Sep 2020 01:20:22 -0700 (PDT) Received: by bubble.grove.modra.org (Postfix, from userid 1000) id A3228863B2; Thu, 17 Sep 2020 17:50:18 +0930 (ACST) Date: Thu, 17 Sep 2020 17:50:18 +0930 From: Alan Modra To: binutils@sourceware.org Subject: PR26569, R_RISCV_RVC_JUMP results in buffer overflow Message-ID: <20200917082018.GR5452@bubble.grove.modra.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.9.4 (2018-02-28) X-Spam-Status: No, score=-10.4 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.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) 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: Thu, 17 Sep 2020 08:20:27 -0000 This patch corrects "size" and "bitsize" in R_RISCV_RVC_* reloc howtos so that elfnn-riscv.c:perform_relocation doesn't access past the end of a section. I've also corrected "size" in the R_RISCV_CALL* reloc howtos since these relocs apply to two consecutive instructions. That caused fallout in the assembler with complaints about "fixup not contained within frag" due to tc-riscv.c:append_insn finishing off a frag after the auipc insn making up a "call" macro. Which is a little rude since the CALL reloc also relocates the following jalr. I wasn't game to change the frag handling, so worked around the error using TC_FIX_SIZE_SLACK, and adjusted fx_size for the RELAX reloc following a CALL. I've also changed R_RISCV_ALIGN and R_RISCV_TPREL_ADD marker reloc howtos to look like R_RISCV_NONE, and corrected dst_mask for numerous relocs, not that it matters very much. OK to apply? bfd/ PR 26569 * elfxx-riscv.c (howto_table): Correct size and bitsize of R_RISCV_RVC_BRANCH, R_RISCV_RVC_JUMP, and R_RISCV_RVC_LUI. Correct size for R_RISCV_TLS_DTPMOD32, R_RISCV_TLS_DTPREL32, R_RISCV_CALL, and R_RISCV_CALL_PLT. Make R_RISCV_TPREL_ADD and R_RISCV_ALIGN like R_RISCV_NONE. Correct dst_mask many relocs. gas/ * config/tc-riscv.c (md_apply_fix): Zero fx_size of RELAX fixup. * config/tc-riscv.g (TC_FX_SIZE_SLACK): Define. diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c index cfdd867e0d..181969521a 100644 --- a/bfd/elfxx-riscv.c +++ b/bfd/elfxx-riscv.c @@ -69,7 +69,7 @@ static reloc_howto_type howto_table[] = "R_RISCV_32", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ - MINUS_ONE, /* dst_mask */ + 0xffffffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* 64 bit relocation. */ @@ -99,7 +99,7 @@ static reloc_howto_type howto_table[] = "R_RISCV_RELATIVE", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ - MINUS_ONE, /* dst_mask */ + 0xffffffff, /* dst_mask */ FALSE), /* pcrel_offset */ HOWTO (R_RISCV_COPY, /* type */ @@ -133,7 +133,7 @@ static reloc_howto_type howto_table[] = /* Dynamic TLS relocations. */ HOWTO (R_RISCV_TLS_DTPMOD32, /* type */ 0, /* rightshift */ - 4, /* size */ + 2, /* size */ 32, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ @@ -142,7 +142,7 @@ static reloc_howto_type howto_table[] = "R_RISCV_TLS_DTPMOD32", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ - MINUS_ONE, /* dst_mask */ + 0xffffffff, /* dst_mask */ FALSE), /* pcrel_offset */ HOWTO (R_RISCV_TLS_DTPMOD64, /* type */ @@ -161,7 +161,7 @@ static reloc_howto_type howto_table[] = HOWTO (R_RISCV_TLS_DTPREL32, /* type */ 0, /* rightshift */ - 4, /* size */ + 2, /* size */ 32, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ @@ -170,7 +170,7 @@ static reloc_howto_type howto_table[] = "R_RISCV_TLS_DTPREL32", /* name */ TRUE, /* partial_inplace */ 0, /* src_mask */ - MINUS_ONE, /* dst_mask */ + 0xffffffff, /* dst_mask */ FALSE), /* pcrel_offset */ HOWTO (R_RISCV_TLS_DTPREL64, /* type */ @@ -198,7 +198,7 @@ static reloc_howto_type howto_table[] = "R_RISCV_TLS_TPREL32", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ - MINUS_ONE, /* dst_mask */ + 0xffffffff, /* dst_mask */ FALSE), /* pcrel_offset */ HOWTO (R_RISCV_TLS_TPREL64, /* type */ @@ -254,7 +254,7 @@ static reloc_howto_type howto_table[] = /* 32-bit PC-relative function call (AUIPC/JALR). */ HOWTO (R_RISCV_CALL, /* type */ 0, /* rightshift */ - 2, /* size */ + 4, /* size */ 64, /* bitsize */ TRUE, /* pc_relative */ 0, /* bitpos */ @@ -270,7 +270,7 @@ static reloc_howto_type howto_table[] = /* Like R_RISCV_CALL, but not locally binding. */ HOWTO (R_RISCV_CALL_PLT, /* type */ 0, /* rightshift */ - 2, /* size */ + 4, /* size */ 64, /* bitsize */ TRUE, /* pc_relative */ 0, /* bitpos */ @@ -466,14 +466,14 @@ static reloc_howto_type howto_table[] = /* TLS LE thread pointer usage. May be relaxed. */ HOWTO (R_RISCV_TPREL_ADD, /* type */ 0, /* rightshift */ - 2, /* size */ - 32, /* bitsize */ + 3, /* size */ + 0, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_RISCV_TPREL_ADD", /* name */ - TRUE, /* partial_inplace */ + FALSE, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ FALSE), /* pcrel_offset */ @@ -490,7 +490,7 @@ static reloc_howto_type howto_table[] = "R_RISCV_ADD8", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ - MINUS_ONE, /* dst_mask */ + 0xff, /* dst_mask */ FALSE), /* pcrel_offset */ /* 16-bit in-place addition, for local label subtraction. */ @@ -505,7 +505,7 @@ static reloc_howto_type howto_table[] = "R_RISCV_ADD16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ - MINUS_ONE, /* dst_mask */ + 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* 32-bit in-place addition, for local label subtraction. */ @@ -520,7 +520,7 @@ static reloc_howto_type howto_table[] = "R_RISCV_ADD32", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ - MINUS_ONE, /* dst_mask */ + 0xffffffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* 64-bit in-place addition, for local label subtraction. */ @@ -550,7 +550,7 @@ static reloc_howto_type howto_table[] = "R_RISCV_SUB8", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ - MINUS_ONE, /* dst_mask */ + 0xff, /* dst_mask */ FALSE), /* pcrel_offset */ /* 16-bit in-place addition, for local label subtraction. */ @@ -565,7 +565,7 @@ static reloc_howto_type howto_table[] = "R_RISCV_SUB16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ - MINUS_ONE, /* dst_mask */ + 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* 32-bit in-place addition, for local label subtraction. */ @@ -580,7 +580,7 @@ static reloc_howto_type howto_table[] = "R_RISCV_SUB32", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ - MINUS_ONE, /* dst_mask */ + 0xffffffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* 64-bit in-place addition, for local label subtraction. */ @@ -633,7 +633,7 @@ static reloc_howto_type howto_table[] = addend rounded up to the next power of two. */ HOWTO (R_RISCV_ALIGN, /* type */ 0, /* rightshift */ - 2, /* size */ + 3, /* size */ 0, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ @@ -648,8 +648,8 @@ static reloc_howto_type howto_table[] = /* 8-bit PC-relative branch offset. */ HOWTO (R_RISCV_RVC_BRANCH, /* type */ 0, /* rightshift */ - 2, /* size */ - 32, /* bitsize */ + 1, /* size */ + 16, /* bitsize */ TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ @@ -663,8 +663,8 @@ static reloc_howto_type howto_table[] = /* 11-bit PC-relative jump offset. */ HOWTO (R_RISCV_RVC_JUMP, /* type */ 0, /* rightshift */ - 2, /* size */ - 32, /* bitsize */ + 1, /* size */ + 16, /* bitsize */ TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ @@ -678,8 +678,8 @@ static reloc_howto_type howto_table[] = /* High 6 bits of 18-bit absolute address. */ HOWTO (R_RISCV_RVC_LUI, /* type */ 0, /* rightshift */ - 2, /* size */ - 32, /* bitsize */ + 1, /* size */ + 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ @@ -807,7 +807,7 @@ static reloc_howto_type howto_table[] = "R_RISCV_SET8", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ - MINUS_ONE, /* dst_mask */ + 0xff, /* dst_mask */ FALSE), /* pcrel_offset */ /* 16-bit in-place setting, for local label subtraction. */ @@ -822,7 +822,7 @@ static reloc_howto_type howto_table[] = "R_RISCV_SET16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ - MINUS_ONE, /* dst_mask */ + 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* 32-bit in-place setting, for local label subtraction. */ @@ -837,7 +837,7 @@ static reloc_howto_type howto_table[] = "R_RISCV_SET32", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ - MINUS_ONE, /* dst_mask */ + 0xffffffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* 32-bit PC relative. */ @@ -852,7 +852,7 @@ static reloc_howto_type howto_table[] = "R_RISCV_32_PCREL", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ - MINUS_ONE, /* dst_mask */ + 0xffffffff, /* dst_mask */ FALSE), /* pcrel_offset */ }; diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c index 9df6d3f415..e1f7673eb5 100644 --- a/gas/config/tc-riscv.c +++ b/gas/config/tc-riscv.c @@ -3031,6 +3031,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) fixP->fx_next = xmemdup (fixP, sizeof (*fixP), sizeof (*fixP)); fixP->fx_next->fx_addsy = fixP->fx_next->fx_subsy = NULL; fixP->fx_next->fx_r_type = BFD_RELOC_RISCV_RELAX; + fixP->fx_next->fx_size = 0; } } diff --git a/gas/config/tc-riscv.h b/gas/config/tc-riscv.h index 43d751ad0d..83cff8f2df 100644 --- a/gas/config/tc-riscv.h +++ b/gas/config/tc-riscv.h @@ -77,6 +77,14 @@ extern int riscv_parse_long_option (const char *); #define md_pre_output_hook riscv_pre_output_hook() extern void riscv_pre_output_hook (void); +/* Call macro frags are tied off wrongly at the auipc which has an + eight byte R_RISCV_CALL reloc covering both the auipc and + immediately following jalr. For now, work around this by allowing + CALL relocs to extend past the end of a frag. */ +#define TC_FX_SIZE_SLACK(FIX) \ + (((FIX)->fx_r_type == BFD_RELOC_RISCV_CALL \ + || (FIX)->fx_r_type == BFD_RELOC_RISCV_CALL_PLT) ? 4 : 0) + /* Let the linker resolve all the relocs due to relaxation. */ #define tc_fix_adjustable(fixp) 0 #define md_allow_local_subtract(l,r,s) 0 -- Alan Modra Australia Development Lab, IBM