[PATCH 1/2] RISC-V: Reject invalid relocation types

Tsukasa OI research_trasio@irq.a4lg.com
Mon Oct 16 06:02:36 GMT 2023


From: Tsukasa OI <research_trasio@irq.a4lg.com>

In RISC-V BFD, there are several internal-only relocation types.  Such
relocation fed from the outside can be a cause of unexpected behaviors
and should be rejected before being parsed further.

This commit adds checks to make sure that we only handle known
relocation types.  For maintainability, internal-only relocation types
are listed separately.

Changes to riscv_elf_check_relocs applies to the linker (ld) and changes
to riscv_info_to_howto_rela and riscv_elf_rtype_to_howto applies to
other tools such like objdump and objcopy.

bfd/ChangeLog:

	* elfnn-riscv.c (riscv_reloc_is_internal_use_only): New to detect
	internal use only relocation type.
	(riscv_info_to_howto_rela): Reject invalid relocation types
	while handling ELF files but linking.
	(riscv_elf_check_relocs): Reject invalid relocation types
	while linking.
	* elfxx-riscv.c (riscv_elf_rtype_to_howto): Also reject types
	without name meaning unknown relocation type.
---
 bfd/elfnn-riscv.c | 77 +++++++++++++++++++++++++++++++++++++++++++++--
 bfd/elfxx-riscv.c |  2 +-
 2 files changed, 76 insertions(+), 3 deletions(-)

diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c
index 09aa7be225ef..dedfabe131ba 100644
--- a/bfd/elfnn-riscv.c
+++ b/bfd/elfnn-riscv.c
@@ -262,12 +262,37 @@ riscv_elfNN_set_options (struct bfd_link_info *link_info,
   riscv_elf_hash_table (link_info)->params = params;
 }
 
+static bool
+riscv_reloc_is_internal_use_only (unsigned int r_type)
+{
+  switch (r_type)
+    {
+      case R_RISCV_RVC_LUI:
+      case R_RISCV_GPREL_I:
+      case R_RISCV_GPREL_S:
+      case R_RISCV_TPREL_I:
+      case R_RISCV_TPREL_S:
+      case R_RISCV_DELETE:
+	return true;
+      default:
+	return false;
+    }
+}
+
 static bool
 riscv_info_to_howto_rela (bfd *abfd,
 			  arelent *cache_ptr,
 			  Elf_Internal_Rela *dst)
 {
-  cache_ptr->howto = riscv_elf_rtype_to_howto (abfd, ELFNN_R_TYPE (dst->r_info));
+  unsigned int r_type = ELFNN_R_TYPE (dst->r_info);
+  cache_ptr->howto = riscv_elf_rtype_to_howto (abfd, r_type);
+  if (cache_ptr->howto && riscv_reloc_is_internal_use_only (r_type))
+    {
+      (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"),
+			     abfd, r_type);
+      bfd_set_error (bfd_error_bad_value);
+      cache_ptr->howto = NULL;
+    }
   return cache_ptr->howto != NULL;
 }
 
@@ -834,8 +859,53 @@ riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	  h->ref_regular = 1;
 	}
 
+      /* Explicitly reject internal use only relocation types.  */
+      if (riscv_reloc_is_internal_use_only (r_type))
+	{
+	  _bfd_error_handler
+	    (_("%pB: internal error: unsupported relocation type %#x"),
+	     abfd, r_type);
+	  return false;
+	}
+
       switch (r_type)
 	{
+	case R_RISCV_NONE:
+	case R_RISCV_TLS_DTPMOD32:
+	case R_RISCV_TLS_DTPMOD64:
+	case R_RISCV_TLS_DTPREL32:
+	case R_RISCV_TLS_DTPREL64:
+	case R_RISCV_TLS_TPREL32:
+	case R_RISCV_TLS_TPREL64:
+	case R_RISCV_PCREL_LO12_I:
+	case R_RISCV_PCREL_LO12_S:
+	case R_RISCV_LO12_I:
+	case R_RISCV_LO12_S:
+	case R_RISCV_TPREL_LO12_I:
+	case R_RISCV_TPREL_LO12_S:
+	case R_RISCV_TPREL_ADD:
+	case R_RISCV_ADD8:
+	case R_RISCV_ADD16:
+	case R_RISCV_ADD32:
+	case R_RISCV_ADD64:
+	case R_RISCV_SUB8:
+	case R_RISCV_SUB16:
+	case R_RISCV_SUB32:
+	case R_RISCV_SUB64:
+	case R_RISCV_ALIGN:
+	case R_RISCV_RELAX:
+	case R_RISCV_SUB6:
+	case R_RISCV_SET6:
+	case R_RISCV_SET8:
+	case R_RISCV_SET16:
+	case R_RISCV_SET32:
+	case R_RISCV_32_PCREL:
+	case R_RISCV_IRELATIVE:
+	case R_RISCV_SET_ULEB128:
+	case R_RISCV_SUB_ULEB128:
+	  /* Known relocation types without additional checks here.  */
+	  break;
+
 	case R_RISCV_TLS_GD_HI20:
 	  if (!riscv_elf_record_got_reference (abfd, info, h, r_symndx)
 	      || !riscv_elf_record_tls_type (abfd, h, r_symndx, GOT_TLS_GD))
@@ -1064,7 +1134,10 @@ riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	  break;
 
 	default:
-	  break;
+	  _bfd_error_handler
+	    (_("%pB: internal error: unsupported relocation type %#x"),
+	     abfd, r_type);
+	  return false;
 	}
     }
 
diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c
index c070394a3667..ffcdae341b2f 100644
--- a/bfd/elfxx-riscv.c
+++ b/bfd/elfxx-riscv.c
@@ -975,7 +975,7 @@ riscv_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
 reloc_howto_type *
 riscv_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
 {
-  if (r_type >= ARRAY_SIZE (howto_table))
+  if (r_type >= ARRAY_SIZE (howto_table) || !howto_table[r_type].name)
     {
       (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"),
 			     abfd, r_type);
-- 
2.42.0



More information about the Binutils mailing list