PR26569, R_RISCV_RVC_JUMP results in buffer overflow
authorAlan Modra <amodra@gmail.com>
Wed, 16 Sep 2020 22:14:53 +0000 (07:44 +0930)
committerAlan Modra <amodra@gmail.com>
Mon, 21 Sep 2020 00:11:05 +0000 (09:41 +0930)
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.

bfd/ChangeLog
bfd/elfxx-riscv.c
gas/ChangeLog
gas/config/tc-riscv.c

index 66463bdbabe3bc8a79d0e36aa5396c9d64b9e670..608e3c796c067e5e238652058732d12f9b3f3c44 100644 (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>
 
        PR ld/18808
index cfdd867e0dec697202d994d4c8eb9b1f50e5e65d..e5adea57b124489fadae67ef8aad47e978c03d1d 100644 (file)
@@ -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 */
@@ -643,13 +643,13 @@ static reloc_howto_type howto_table[] =
         FALSE,                         /* partial_inplace */
         0,                             /* src_mask */
         0,                             /* dst_mask */
-        TRUE),                         /* pcrel_offset */
+        FALSE),                        /* pcrel_offset */
 
   /* 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 */
 };
 
index cad6b5c57c1cb7387b1cab6289abf69534a9fa05..ff8fa2201c5405a4e6a12c13ce2bfc1af6a108ae 100644 (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>
 
        * testsuite/gas/bpf/alu-xbpf.d: New file.
index 9df6d3f41565f08e398df776be7c5a590dc42108..eb31e42a2e7ce92bd6dc00bc7e5230dbf1793674 100644 (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
      the assembler from computing static offsets across such an instruction.
      This is necessary to get correct EH info.  */
-  if (reloc_type == BFD_RELOC_RISCV_CALL
-      || reloc_type == BFD_RELOC_RISCV_CALL_PLT
-      || reloc_type == BFD_RELOC_RISCV_HI20
+  if (reloc_type == BFD_RELOC_RISCV_HI20
       || reloc_type == BFD_RELOC_RISCV_PCREL_HI20
       || reloc_type == BFD_RELOC_RISCV_TPREL_HI20
       || reloc_type == BFD_RELOC_RISCV_TPREL_ADD)
@@ -1311,8 +1309,13 @@ static void
 riscv_call (int destreg, int tempreg, expressionS *ep,
            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 (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.  */
@@ -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->fx_addsy = fixP->fx_next->fx_subsy = NULL;
       fixP->fx_next->fx_r_type = BFD_RELOC_RISCV_RELAX;
+      fixP->fx_next->fx_size = 0;
     }
 }