PR26569, R_RISCV_RVC_JUMP results in buffer overflow

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.  Fixed by
changing the frag handling a little.

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.

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 (append_insn): Don't tie off frags at CALL
	relocs.
	(riscv_call): Tie them off after the jalr.
	(md_apply_fix): Zero fx_size of RELAX fixup.
This commit is contained in:
Alan Modra
2020-09-17 07:44:53 +09:30
parent 4f94229e83
commit b1b11e922b
4 changed files with 54 additions and 33 deletions

View File

@ -1,3 +1,12 @@
2020-09-21 Alan Modra <amodra@gmail.com>
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.
2020-09-17 Mikael Pettersson <mikpelinux@gmail.com> 2020-09-17 Mikael Pettersson <mikpelinux@gmail.com>
PR ld/18808 PR ld/18808

View File

@ -69,7 +69,7 @@ static reloc_howto_type howto_table[] =
"R_RISCV_32", /* name */ "R_RISCV_32", /* name */
FALSE, /* partial_inplace */ FALSE, /* partial_inplace */
0, /* src_mask */ 0, /* src_mask */
MINUS_ONE, /* dst_mask */ 0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */ FALSE), /* pcrel_offset */
/* 64 bit relocation. */ /* 64 bit relocation. */
@ -99,7 +99,7 @@ static reloc_howto_type howto_table[] =
"R_RISCV_RELATIVE", /* name */ "R_RISCV_RELATIVE", /* name */
FALSE, /* partial_inplace */ FALSE, /* partial_inplace */
0, /* src_mask */ 0, /* src_mask */
MINUS_ONE, /* dst_mask */ 0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */ FALSE), /* pcrel_offset */
HOWTO (R_RISCV_COPY, /* type */ HOWTO (R_RISCV_COPY, /* type */
@ -133,7 +133,7 @@ static reloc_howto_type howto_table[] =
/* Dynamic TLS relocations. */ /* Dynamic TLS relocations. */
HOWTO (R_RISCV_TLS_DTPMOD32, /* type */ HOWTO (R_RISCV_TLS_DTPMOD32, /* type */
0, /* rightshift */ 0, /* rightshift */
4, /* size */ 2, /* size */
32, /* bitsize */ 32, /* bitsize */
FALSE, /* pc_relative */ FALSE, /* pc_relative */
0, /* bitpos */ 0, /* bitpos */
@ -142,7 +142,7 @@ static reloc_howto_type howto_table[] =
"R_RISCV_TLS_DTPMOD32", /* name */ "R_RISCV_TLS_DTPMOD32", /* name */
FALSE, /* partial_inplace */ FALSE, /* partial_inplace */
0, /* src_mask */ 0, /* src_mask */
MINUS_ONE, /* dst_mask */ 0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */ FALSE), /* pcrel_offset */
HOWTO (R_RISCV_TLS_DTPMOD64, /* type */ HOWTO (R_RISCV_TLS_DTPMOD64, /* type */
@ -161,7 +161,7 @@ static reloc_howto_type howto_table[] =
HOWTO (R_RISCV_TLS_DTPREL32, /* type */ HOWTO (R_RISCV_TLS_DTPREL32, /* type */
0, /* rightshift */ 0, /* rightshift */
4, /* size */ 2, /* size */
32, /* bitsize */ 32, /* bitsize */
FALSE, /* pc_relative */ FALSE, /* pc_relative */
0, /* bitpos */ 0, /* bitpos */
@ -170,7 +170,7 @@ static reloc_howto_type howto_table[] =
"R_RISCV_TLS_DTPREL32", /* name */ "R_RISCV_TLS_DTPREL32", /* name */
TRUE, /* partial_inplace */ TRUE, /* partial_inplace */
0, /* src_mask */ 0, /* src_mask */
MINUS_ONE, /* dst_mask */ 0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */ FALSE), /* pcrel_offset */
HOWTO (R_RISCV_TLS_DTPREL64, /* type */ HOWTO (R_RISCV_TLS_DTPREL64, /* type */
@ -198,7 +198,7 @@ static reloc_howto_type howto_table[] =
"R_RISCV_TLS_TPREL32", /* name */ "R_RISCV_TLS_TPREL32", /* name */
FALSE, /* partial_inplace */ FALSE, /* partial_inplace */
0, /* src_mask */ 0, /* src_mask */
MINUS_ONE, /* dst_mask */ 0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */ FALSE), /* pcrel_offset */
HOWTO (R_RISCV_TLS_TPREL64, /* type */ HOWTO (R_RISCV_TLS_TPREL64, /* type */
@ -254,7 +254,7 @@ static reloc_howto_type howto_table[] =
/* 32-bit PC-relative function call (AUIPC/JALR). */ /* 32-bit PC-relative function call (AUIPC/JALR). */
HOWTO (R_RISCV_CALL, /* type */ HOWTO (R_RISCV_CALL, /* type */
0, /* rightshift */ 0, /* rightshift */
2, /* size */ 4, /* size */
64, /* bitsize */ 64, /* bitsize */
TRUE, /* pc_relative */ TRUE, /* pc_relative */
0, /* bitpos */ 0, /* bitpos */
@ -270,7 +270,7 @@ static reloc_howto_type howto_table[] =
/* Like R_RISCV_CALL, but not locally binding. */ /* Like R_RISCV_CALL, but not locally binding. */
HOWTO (R_RISCV_CALL_PLT, /* type */ HOWTO (R_RISCV_CALL_PLT, /* type */
0, /* rightshift */ 0, /* rightshift */
2, /* size */ 4, /* size */
64, /* bitsize */ 64, /* bitsize */
TRUE, /* pc_relative */ TRUE, /* pc_relative */
0, /* bitpos */ 0, /* bitpos */
@ -466,14 +466,14 @@ static reloc_howto_type howto_table[] =
/* TLS LE thread pointer usage. May be relaxed. */ /* TLS LE thread pointer usage. May be relaxed. */
HOWTO (R_RISCV_TPREL_ADD, /* type */ HOWTO (R_RISCV_TPREL_ADD, /* type */
0, /* rightshift */ 0, /* rightshift */
2, /* size */ 3, /* size */
32, /* bitsize */ 0, /* bitsize */
FALSE, /* pc_relative */ FALSE, /* pc_relative */
0, /* bitpos */ 0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */ complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */ bfd_elf_generic_reloc, /* special_function */
"R_RISCV_TPREL_ADD", /* name */ "R_RISCV_TPREL_ADD", /* name */
TRUE, /* partial_inplace */ FALSE, /* partial_inplace */
0, /* src_mask */ 0, /* src_mask */
0, /* dst_mask */ 0, /* dst_mask */
FALSE), /* pcrel_offset */ FALSE), /* pcrel_offset */
@ -490,7 +490,7 @@ static reloc_howto_type howto_table[] =
"R_RISCV_ADD8", /* name */ "R_RISCV_ADD8", /* name */
FALSE, /* partial_inplace */ FALSE, /* partial_inplace */
0, /* src_mask */ 0, /* src_mask */
MINUS_ONE, /* dst_mask */ 0xff, /* dst_mask */
FALSE), /* pcrel_offset */ FALSE), /* pcrel_offset */
/* 16-bit in-place addition, for local label subtraction. */ /* 16-bit in-place addition, for local label subtraction. */
@ -505,7 +505,7 @@ static reloc_howto_type howto_table[] =
"R_RISCV_ADD16", /* name */ "R_RISCV_ADD16", /* name */
FALSE, /* partial_inplace */ FALSE, /* partial_inplace */
0, /* src_mask */ 0, /* src_mask */
MINUS_ONE, /* dst_mask */ 0xffff, /* dst_mask */
FALSE), /* pcrel_offset */ FALSE), /* pcrel_offset */
/* 32-bit in-place addition, for local label subtraction. */ /* 32-bit in-place addition, for local label subtraction. */
@ -520,7 +520,7 @@ static reloc_howto_type howto_table[] =
"R_RISCV_ADD32", /* name */ "R_RISCV_ADD32", /* name */
FALSE, /* partial_inplace */ FALSE, /* partial_inplace */
0, /* src_mask */ 0, /* src_mask */
MINUS_ONE, /* dst_mask */ 0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */ FALSE), /* pcrel_offset */
/* 64-bit in-place addition, for local label subtraction. */ /* 64-bit in-place addition, for local label subtraction. */
@ -550,7 +550,7 @@ static reloc_howto_type howto_table[] =
"R_RISCV_SUB8", /* name */ "R_RISCV_SUB8", /* name */
FALSE, /* partial_inplace */ FALSE, /* partial_inplace */
0, /* src_mask */ 0, /* src_mask */
MINUS_ONE, /* dst_mask */ 0xff, /* dst_mask */
FALSE), /* pcrel_offset */ FALSE), /* pcrel_offset */
/* 16-bit in-place addition, for local label subtraction. */ /* 16-bit in-place addition, for local label subtraction. */
@ -565,7 +565,7 @@ static reloc_howto_type howto_table[] =
"R_RISCV_SUB16", /* name */ "R_RISCV_SUB16", /* name */
FALSE, /* partial_inplace */ FALSE, /* partial_inplace */
0, /* src_mask */ 0, /* src_mask */
MINUS_ONE, /* dst_mask */ 0xffff, /* dst_mask */
FALSE), /* pcrel_offset */ FALSE), /* pcrel_offset */
/* 32-bit in-place addition, for local label subtraction. */ /* 32-bit in-place addition, for local label subtraction. */
@ -580,7 +580,7 @@ static reloc_howto_type howto_table[] =
"R_RISCV_SUB32", /* name */ "R_RISCV_SUB32", /* name */
FALSE, /* partial_inplace */ FALSE, /* partial_inplace */
0, /* src_mask */ 0, /* src_mask */
MINUS_ONE, /* dst_mask */ 0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */ FALSE), /* pcrel_offset */
/* 64-bit in-place addition, for local label subtraction. */ /* 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. */ addend rounded up to the next power of two. */
HOWTO (R_RISCV_ALIGN, /* type */ HOWTO (R_RISCV_ALIGN, /* type */
0, /* rightshift */ 0, /* rightshift */
2, /* size */ 3, /* size */
0, /* bitsize */ 0, /* bitsize */
FALSE, /* pc_relative */ FALSE, /* pc_relative */
0, /* bitpos */ 0, /* bitpos */
@ -643,13 +643,13 @@ static reloc_howto_type howto_table[] =
FALSE, /* partial_inplace */ FALSE, /* partial_inplace */
0, /* src_mask */ 0, /* src_mask */
0, /* dst_mask */ 0, /* dst_mask */
TRUE), /* pcrel_offset */ FALSE), /* pcrel_offset */
/* 8-bit PC-relative branch offset. */ /* 8-bit PC-relative branch offset. */
HOWTO (R_RISCV_RVC_BRANCH, /* type */ HOWTO (R_RISCV_RVC_BRANCH, /* type */
0, /* rightshift */ 0, /* rightshift */
2, /* size */ 1, /* size */
32, /* bitsize */ 16, /* bitsize */
TRUE, /* pc_relative */ TRUE, /* pc_relative */
0, /* bitpos */ 0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */ complain_overflow_signed, /* complain_on_overflow */
@ -663,8 +663,8 @@ static reloc_howto_type howto_table[] =
/* 11-bit PC-relative jump offset. */ /* 11-bit PC-relative jump offset. */
HOWTO (R_RISCV_RVC_JUMP, /* type */ HOWTO (R_RISCV_RVC_JUMP, /* type */
0, /* rightshift */ 0, /* rightshift */
2, /* size */ 1, /* size */
32, /* bitsize */ 16, /* bitsize */
TRUE, /* pc_relative */ TRUE, /* pc_relative */
0, /* bitpos */ 0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */ complain_overflow_dont, /* complain_on_overflow */
@ -678,8 +678,8 @@ static reloc_howto_type howto_table[] =
/* High 6 bits of 18-bit absolute address. */ /* High 6 bits of 18-bit absolute address. */
HOWTO (R_RISCV_RVC_LUI, /* type */ HOWTO (R_RISCV_RVC_LUI, /* type */
0, /* rightshift */ 0, /* rightshift */
2, /* size */ 1, /* size */
32, /* bitsize */ 16, /* bitsize */
FALSE, /* pc_relative */ FALSE, /* pc_relative */
0, /* bitpos */ 0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */ complain_overflow_dont, /* complain_on_overflow */
@ -807,7 +807,7 @@ static reloc_howto_type howto_table[] =
"R_RISCV_SET8", /* name */ "R_RISCV_SET8", /* name */
FALSE, /* partial_inplace */ FALSE, /* partial_inplace */
0, /* src_mask */ 0, /* src_mask */
MINUS_ONE, /* dst_mask */ 0xff, /* dst_mask */
FALSE), /* pcrel_offset */ FALSE), /* pcrel_offset */
/* 16-bit in-place setting, for local label subtraction. */ /* 16-bit in-place setting, for local label subtraction. */
@ -822,7 +822,7 @@ static reloc_howto_type howto_table[] =
"R_RISCV_SET16", /* name */ "R_RISCV_SET16", /* name */
FALSE, /* partial_inplace */ FALSE, /* partial_inplace */
0, /* src_mask */ 0, /* src_mask */
MINUS_ONE, /* dst_mask */ 0xffff, /* dst_mask */
FALSE), /* pcrel_offset */ FALSE), /* pcrel_offset */
/* 32-bit in-place setting, for local label subtraction. */ /* 32-bit in-place setting, for local label subtraction. */
@ -837,7 +837,7 @@ static reloc_howto_type howto_table[] =
"R_RISCV_SET32", /* name */ "R_RISCV_SET32", /* name */
FALSE, /* partial_inplace */ FALSE, /* partial_inplace */
0, /* src_mask */ 0, /* src_mask */
MINUS_ONE, /* dst_mask */ 0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */ FALSE), /* pcrel_offset */
/* 32-bit PC relative. */ /* 32-bit PC relative. */
@ -852,7 +852,7 @@ static reloc_howto_type howto_table[] =
"R_RISCV_32_PCREL", /* name */ "R_RISCV_32_PCREL", /* name */
FALSE, /* partial_inplace */ FALSE, /* partial_inplace */
0, /* src_mask */ 0, /* src_mask */
MINUS_ONE, /* dst_mask */ 0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */ FALSE), /* pcrel_offset */
}; };

View File

@ -1,3 +1,11 @@
2020-09-21 Alan Modra <amodra@gmail.com>
PR 26569
* config/tc-riscv.c (append_insn): Don't tie off frags at CALL
relocs.
(riscv_call): Tie them off after the jalr.
(md_apply_fix): Zero fx_size of RELAX fixup.
2020-09-018 David Faust <david.faust@oracle.com> 2020-09-018 David Faust <david.faust@oracle.com>
* testsuite/gas/bpf/alu-xbpf.d: New file. * testsuite/gas/bpf/alu-xbpf.d: New file.

View File

@ -1133,9 +1133,7 @@ append_insn (struct riscv_cl_insn *ip, expressionS *address_expr,
optimized away or compressed by the linker during relaxation, to prevent optimized away or compressed by the linker during relaxation, to prevent
the assembler from computing static offsets across such an instruction. the assembler from computing static offsets across such an instruction.
This is necessary to get correct EH info. */ This is necessary to get correct EH info. */
if (reloc_type == BFD_RELOC_RISCV_CALL if (reloc_type == BFD_RELOC_RISCV_HI20
|| reloc_type == BFD_RELOC_RISCV_CALL_PLT
|| reloc_type == BFD_RELOC_RISCV_HI20
|| reloc_type == BFD_RELOC_RISCV_PCREL_HI20 || reloc_type == BFD_RELOC_RISCV_PCREL_HI20
|| reloc_type == BFD_RELOC_RISCV_TPREL_HI20 || reloc_type == BFD_RELOC_RISCV_TPREL_HI20
|| reloc_type == BFD_RELOC_RISCV_TPREL_ADD) || reloc_type == BFD_RELOC_RISCV_TPREL_ADD)
@ -1311,8 +1309,13 @@ static void
riscv_call (int destreg, int tempreg, expressionS *ep, riscv_call (int destreg, int tempreg, expressionS *ep,
bfd_reloc_code_real_type reloc) bfd_reloc_code_real_type reloc)
{ {
/* Ensure the jalr is emitted to the same frag as the auipc. */
frag_grow (8);
macro_build (ep, "auipc", "d,u", tempreg, reloc); macro_build (ep, "auipc", "d,u", tempreg, reloc);
macro_build (NULL, "jalr", "d,s", destreg, tempreg); macro_build (NULL, "jalr", "d,s", destreg, tempreg);
/* See comment at end of append_insn. */
frag_wane (frag_now);
frag_new (0);
} }
/* Load an integer constant into a register. */ /* Load an integer constant into a register. */
@ -3031,6 +3034,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
fixP->fx_next = xmemdup (fixP, sizeof (*fixP), sizeof (*fixP)); fixP->fx_next = xmemdup (fixP, sizeof (*fixP), sizeof (*fixP));
fixP->fx_next->fx_addsy = fixP->fx_next->fx_subsy = NULL; 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_r_type = BFD_RELOC_RISCV_RELAX;
fixP->fx_next->fx_size = 0;
} }
} }