aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2025-02-05 14:31:10 +0000
committerNick Clifton <nickc@redhat.com>2025-02-05 14:31:10 +0000
commit18cc11a2771d9e40180485da9a4fb660c03efac3 (patch)
tree5d087b860ad440b4d147197cf1e70ec7dcbea2f6
parent557daf57cab4e1664101f988a7f64964ff056777 (diff)
downloadbinutils-18cc11a2771d9e40180485da9a4fb660c03efac3.zip
binutils-18cc11a2771d9e40180485da9a4fb660c03efac3.tar.gz
binutils-18cc11a2771d9e40180485da9a4fb660c03efac3.tar.bz2
Prevent illegal memory access when checking relocs in a corrupt ELF binary.
PR 32641
-rw-r--r--bfd/elf-bfd.h3
-rw-r--r--bfd/elf64-x86-64.c10
-rw-r--r--bfd/elflink.c24
-rw-r--r--bfd/elfxx-x86.c20
4 files changed, 39 insertions, 18 deletions
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 785a37d..d2bf8e5 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -3153,6 +3153,9 @@ extern bool _bfd_elf_link_mmap_section_contents
extern void _bfd_elf_link_munmap_section_contents
(asection *);
+extern struct elf_link_hash_entry * _bfd_elf_get_link_hash_entry
+ (struct elf_link_hash_entry **, unsigned int, Elf_Internal_Shdr *);
+
/* Large common section. */
extern asection _bfd_elf_large_com_section;
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 32db254..2d82c65 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -1784,7 +1784,7 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
bool to_reloc_pc32;
bool abs_symbol;
bool local_ref;
- asection *tsec;
+ asection *tsec = NULL;
bfd_signed_vma raddend;
unsigned int opcode;
unsigned int modrm;
@@ -1999,6 +1999,9 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
return true;
}
+ if (tsec == NULL)
+ return false;
+
/* Don't convert GOTPCREL relocation against large section. */
if (elf_section_data (tsec) != NULL
&& (elf_section_flags (tsec) & SHF_X86_64_LARGE) != 0)
@@ -2408,10 +2411,7 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info,
else
{
isym = NULL;
- h = sym_hashes[r_symndx - symtab_hdr->sh_info];
- while (h->root.type == bfd_link_hash_indirect
- || h->root.type == bfd_link_hash_warning)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ h = _bfd_elf_get_link_hash_entry (sym_hashes, r_symndx, symtab_hdr);
}
/* Check invalid x32 relocations. */
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 1f12630..eafbd13 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -96,6 +96,27 @@ _bfd_elf_link_keep_memory (struct bfd_link_info *info)
return true;
}
+struct elf_link_hash_entry *
+_bfd_elf_get_link_hash_entry (struct elf_link_hash_entry ** sym_hashes,
+ unsigned int symndx,
+ Elf_Internal_Shdr * symtab_hdr)
+{
+ if (symndx < symtab_hdr->sh_info)
+ return NULL;
+
+ struct elf_link_hash_entry *h = sym_hashes[symndx - symtab_hdr->sh_info];
+
+ /* The hash might be empty. See PR 32641 for an example of this. */
+ if (h == NULL)
+ return NULL;
+
+ while (h->root.type == bfd_link_hash_indirect
+ || h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+ return h;
+}
+
static struct elf_link_hash_entry *
get_ext_sym_hash (struct elf_reloc_cookie *cookie, unsigned long r_symndx)
{
@@ -108,6 +129,9 @@ get_ext_sym_hash (struct elf_reloc_cookie *cookie, unsigned long r_symndx)
{
h = cookie->sym_hashes[r_symndx - cookie->extsymoff];
+ if (h == NULL)
+ return NULL;
+
while (h->root.type == bfd_link_hash_indirect
|| h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
index 8e5a005..832a549 100644
--- a/bfd/elfxx-x86.c
+++ b/bfd/elfxx-x86.c
@@ -973,15 +973,7 @@ _bfd_x86_elf_check_relocs (bfd *abfd,
goto error_return;
}
- if (r_symndx < symtab_hdr->sh_info)
- h = NULL;
- else
- {
- h = sym_hashes[r_symndx - symtab_hdr->sh_info];
- while (h->root.type == bfd_link_hash_indirect
- || h->root.type == bfd_link_hash_warning)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
- }
+ h = _bfd_elf_get_link_hash_entry (sym_hashes, r_symndx, symtab_hdr);
if (X86_NEED_DYNAMIC_RELOC_TYPE_P (is_x86_64, r_type)
&& NEED_DYNAMIC_RELOCATION_P (is_x86_64, info, true, h, sec,
@@ -1209,10 +1201,12 @@ _bfd_x86_elf_link_relax_section (bfd *abfd ATTRIBUTE_UNUSED,
else
{
/* Get H and SEC for GENERATE_DYNAMIC_RELOCATION_P below. */
- h = sym_hashes[r_symndx - symtab_hdr->sh_info];
- while (h->root.type == bfd_link_hash_indirect
- || h->root.type == bfd_link_hash_warning)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ h = _bfd_elf_get_link_hash_entry (sym_hashes, r_symndx, symtab_hdr);
+ if (h == NULL)
+ {
+ /* FIXMEL: Issue an error message ? */
+ continue;
+ }
if (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)