[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