[PATCH][Binutils][2_42] Backport fixes for (PR 32636, 32641, 32643, 32644)
Dora, Sunil Kumar
SunilKumar.Dora@windriver.com
Mon May 5 14:41:17 GMT 2025
Hi All,
Just a gentle reminder regarding the patch titled:
[PATCH][Binutils][2_42] Backport fixes for PR 32636, 32641, 32643, 32644
I'd greatly appreciate any feedback, review, or approval from the maintainers and the wider community.
Thank you for your time and support.
Thanks,
Sunil Dora
________________________________
From: Dora, Sunil Kumar
Sent: Tuesday, April 29, 2025 8:22 PM
To: binutils@sourceware.org <binutils@sourceware.org>
Cc: nickc@redhat.com <nickc@redhat.com>; amodra@gmail.com <amodra@gmail.com>; Dora, Sunil Kumar <SunilKumar.Dora@windriver.com>; Kokkonda, Sundeep <Sundeep.Kokkonda@windriver.com>; Sadineni, Harish <Harish.Sadineni@windriver.com>
Subject: [PATCH][Binutils][2_42] Backport fixes for (PR 32636, 32641, 32643, 32644)
From: Nick Clifton <nickc@redhat.com>
This commit backports the following fixes from master to the 2.42 branch:
Cherry pick from master:
1. PR 32636 - Fix heap-buffer-overflow in _bfd_elf_gc_mark_rsec when processing
corrupt ELF input with long paths and --gc-sections. Prevents illegal memory
access when indexing sym_hashes array.
(https://sourceware.org/bugzilla/show_bug.cgi?id=32636)
2. PR 32641 - Fix SEGV in _bfd_x86_elf_check_relocs when processing malformed
relocations with -w option. Adds validation for relocation/symbol integrity.
(https://sourceware.org/bugzilla/show_bug.cgi?id=32641)
3. PR 32643 - Fix SEGV in _bfd_elf_gc_mark_rsec with --gc-sections on corrupt
input. Strengthens relocation processing checks.
(https://sourceware.org/bugzilla/show_bug.cgi?id=32643)
4. PR 32644 - Fix SEGV in bfd_elf_reloc_symbol_deleted_p with combination of
--no-undefined, --orphan-handling and -w options. Adds missing validation.
(https://sourceware.org/bugzilla/show_bug.cgi?id=32644)
Signed-off-by: Sunil Dora <sunilkumar.dora@windriver.com>
---
bfd/elf-bfd.h | 3 +
bfd/elf64-x86-64.c | 10 +-
bfd/elflink.c | 270 ++++++++++++++++++++++++---------------------
bfd/elfxx-x86.c | 20 ++--
4 files changed, 162 insertions(+), 141 deletions(-)
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 3ed22fa6c52..07add7d0302 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -3126,6 +3126,9 @@ extern bool _bfd_elf_maybe_set_textrel
extern bool _bfd_elf_add_dynamic_tags
(bfd *, struct bfd_link_info *, bool);
+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 2ed120af780..74ff749c091 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -1665,7 +1665,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;
@@ -1831,6 +1831,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)
@@ -2127,10 +2130,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 0fd06d11c24..97555b166d6 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -49,22 +49,60 @@ struct elf_info_failed
static bool _bfd_elf_fix_symbol_flags
(struct elf_link_hash_entry *, struct elf_info_failed *);
-asection *
-_bfd_elf_section_for_symbol (struct elf_reloc_cookie *cookie,
- unsigned long r_symndx,
- bool discard)
+static struct elf_link_hash_entry *
+get_link_hash_entry (struct elf_link_hash_entry ** sym_hashes,
+ unsigned int symndx,
+ unsigned int ext_sym_start)
+{
+ if (sym_hashes == NULL
+ /* Guard against corrupt input. See PR 32636 for an example. */
+ || symndx < ext_sym_start)
+ return NULL;
+
+ struct elf_link_hash_entry *h = sym_hashes[symndx - ext_sym_start];
+
+ /* 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;
+}
+
+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 (r_symndx >= cookie->locsymcount
- || ELF_ST_BIND (cookie->locsyms[r_symndx].st_info) != STB_LOCAL)
- {
- struct elf_link_hash_entry *h;
+ if (symtab_hdr == NULL)
+ return NULL;
+ return get_link_hash_entry (sym_hashes, symndx, symtab_hdr->sh_info);
+}
- h = cookie->sym_hashes[r_symndx - cookie->extsymoff];
+static struct elf_link_hash_entry *
+get_ext_sym_hash_from_cookie (struct elf_reloc_cookie *cookie, unsigned long r_symndx)
+{
+ if (cookie == NULL || cookie->sym_hashes == 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;
+ if (r_symndx >= cookie->locsymcount
+ || ELF_ST_BIND (cookie->locsyms[r_symndx].st_info) != STB_LOCAL)
+ return get_link_hash_entry (cookie->sym_hashes, r_symndx, cookie->extsymoff);
+ return NULL;
+}
+asection *
+_bfd_elf_section_for_symbol (struct elf_reloc_cookie *cookie,
+ unsigned long r_symndx,
+ bool discard)
+{
+ struct elf_link_hash_entry *h;
+ h = get_ext_sym_hash_from_cookie (cookie, r_symndx);
+ if (h != NULL)
+ {
if ((h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
&& discarded_section (h->root.u.def.section))
@@ -72,21 +110,18 @@ _bfd_elf_section_for_symbol (struct elf_reloc_cookie *cookie,
else
return NULL;
}
- else
- {
- /* It's not a relocation against a global symbol,
- but it could be a relocation against a local
- symbol for a discarded section. */
- asection *isec;
- Elf_Internal_Sym *isym;
+ /* It's not a relocation against a global symbol,
+ but it could be a relocation against a local
+ symbol for a discarded section. */
+ asection *isec;
+ Elf_Internal_Sym *isym;
- /* Need to: get the symbol; get the section. */
- isym = &cookie->locsyms[r_symndx];
- isec = bfd_section_from_elf_index (cookie->abfd, isym->st_shndx);
- if (isec != NULL
- && discard ? discarded_section (isec) : 1)
- return isec;
- }
+ /* Need to: get the symbol; get the section. */
+ isym = &cookie->locsyms[r_symndx];
+ isec = bfd_section_from_elf_index (cookie->abfd, isym->st_shndx);
+ if (isec != NULL
+ && discard ? discarded_section (isec) : 1)
+ return isec;
return NULL;
}
@@ -8880,7 +8915,6 @@ set_symbol_value (bfd *bfd_with_globals,
size_t symidx,
bfd_vma val)
{
- struct elf_link_hash_entry **sym_hashes;
struct elf_link_hash_entry *h;
size_t extsymoff = locsymcount;
@@ -8904,11 +8938,12 @@ set_symbol_value (bfd *bfd_with_globals,
/* It is a global symbol: set its link type
to "defined" and give it a value. */
- sym_hashes = elf_sym_hashes (bfd_with_globals);
- h = sym_hashes [symidx - extsymoff];
- 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 = get_link_hash_entry (elf_sym_hashes (bfd_with_globals), symidx, extsymoff);
+ if (h == NULL)
+ {
+ /* FIXMEL What should we do ? */
+ return;
+ }
h->root.type = bfd_link_hash_defined;
h->root.u.def.value = val;
h->root.u.def.section = bfd_abs_section_ptr;
@@ -11379,10 +11414,19 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
|| (elf_bad_symtab (input_bfd)
&& flinfo->sections[symndx] == NULL))
{
- struct elf_link_hash_entry *h = sym_hashes[symndx - extsymoff];
- 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;
+ struct elf_link_hash_entry *h;
+
+ h = get_link_hash_entry (sym_hashes, symndx, extsymoff);
+ if (h == NULL)
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("error: %pB: unable to create group section symbol"),
+ input_bfd);
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
/* Arrange for symbol to be output. */
h->indx = -2;
elf_section_data (osec)->this_hdr.sh_info = -2;
@@ -11516,7 +11560,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
|| (elf_bad_symtab (input_bfd)
&& flinfo->sections[r_symndx] == NULL))
{
- h = sym_hashes[r_symndx - extsymoff];
+ h = get_link_hash_entry (sym_hashes, r_symndx, extsymoff);
/* Badly formatted input files can contain relocs that
reference non-existant symbols. Check here so that
@@ -11525,17 +11569,13 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
{
_bfd_error_handler
/* xgettext:c-format */
- (_("error: %pB contains a reloc (%#" PRIx64 ") for section %pA "
+ (_("error: %pB contains a reloc (%#" PRIx64 ") for section '%pA' "
"that references a non-existent global symbol"),
input_bfd, (uint64_t) rel->r_info, o);
bfd_set_error (bfd_error_bad_value);
return false;
}
- 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;
-
s_type = h->type;
/* If a plugin symbol is referenced from a non-IR file,
@@ -11751,7 +11791,6 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
&& flinfo->sections[r_symndx] == NULL))
{
struct elf_link_hash_entry *rh;
- unsigned long indx;
/* This is a reloc against a global symbol. We
have not yet output all the local symbols, so
@@ -11760,15 +11799,16 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
reloc to point to the global hash table entry
for this symbol. The symbol index is then
set at the end of bfd_elf_final_link. */
- indx = r_symndx - extsymoff;
- rh = elf_sym_hashes (input_bfd)[indx];
- while (rh->root.type == bfd_link_hash_indirect
- || rh->root.type == bfd_link_hash_warning)
- rh = (struct elf_link_hash_entry *) rh->root.u.i.link;
-
- /* Setting the index to -2 tells
- elf_link_output_extsym that this symbol is
- used by a reloc. */
+ rh = get_link_hash_entry (elf_sym_hashes (input_bfd),
+ r_symndx, extsymoff);
+ if (rh == NULL)
+ {
+ /* FIXME: Generate an error ? */
+ continue;
+ }
+
+ /* Setting the index to -2 tells elf_link_output_extsym
+ that this symbol is used by a reloc. */
BFD_ASSERT (rh->indx < 0);
rh->indx = -2;
*rel_hash = rh;
@@ -13732,25 +13772,21 @@ _bfd_elf_gc_mark_hook (asection *sec,
struct elf_link_hash_entry *h,
Elf_Internal_Sym *sym)
{
- if (h != NULL)
+ if (h == NULL)
+ return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
+
+ switch (h->root.type)
{
- switch (h->root.type)
- {
- case bfd_link_hash_defined:
- case bfd_link_hash_defweak:
- return h->root.u.def.section;
+ case bfd_link_hash_defined:
+ case bfd_link_hash_defweak:
+ return h->root.u.def.section;
- case bfd_link_hash_common:
- return h->root.u.c.p->section;
+ case bfd_link_hash_common:
+ return h->root.u.c.p->section;
- default:
- break;
- }
+ default:
+ return NULL;
}
- else
- return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
-
- return NULL;
}
/* Return the debug definition section. */
@@ -13799,56 +13835,45 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec,
if (r_symndx == STN_UNDEF)
return NULL;
- if (r_symndx >= cookie->locsymcount
- || ELF_ST_BIND (cookie->locsyms[r_symndx].st_info) != STB_LOCAL)
+ h = get_ext_sym_hash_from_cookie (cookie, r_symndx);
+ if (h == NULL)
{
- bool was_marked;
+ /* A corrup tinput file can lead to a situation where the index
+ does not reference either a local or an external symbol. */
+ if (r_symndx >= cookie->locsymcount)
+ return NULL;
- h = cookie->sym_hashes[r_symndx - cookie->extsymoff];
- if (h == NULL)
- {
- info->callbacks->einfo (_("%F%P: corrupt input: %pB\n"),
- sec->owner);
- 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;
-
- was_marked = h->mark;
- h->mark = 1;
- /* Keep all aliases of the symbol too. If an object symbol
- needs to be copied into .dynbss then all of its aliases
- should be present as dynamic symbols, not just the one used
- on the copy relocation. */
- hw = h;
- while (hw->is_weakalias)
- {
- hw = hw->u.alias;
- hw->mark = 1;
- }
-
- if (!was_marked && h->start_stop && !h->root.ldscript_def)
- {
- if (info->start_stop_gc)
- return NULL;
-
- /* To work around a glibc bug, mark XXX input sections
- when there is a reference to __start_XXX or __stop_XXX
- symbols. */
- else if (start_stop != NULL)
- {
- asection *s = h->u2.start_stop_section;
- *start_stop = true;
- return s;
- }
- }
-
- return (*gc_mark_hook) (sec, info, cookie->rel, h, NULL);
+ return (*gc_mark_hook) (sec, info, cookie->rel, NULL,
+ &cookie->locsyms[r_symndx]);
}
+ bool was_marked = h->mark;
+ h->mark = 1;
+ /* Keep all aliases of the symbol too. If an object symbol
+ needs to be copied into .dynbss then all of its aliases
+ should be present as dynamic symbols, not just the one used
+ on the copy relocation. */
+ hw = h;
+ while (hw->is_weakalias)
+ {
+ hw = hw->u.alias;
+ hw->mark = 1;
+ }
+ if (!was_marked && h->start_stop && !h->root.ldscript_def)
+ {
+ if (info->start_stop_gc)
+ return NULL;
- return (*gc_mark_hook) (sec, info, cookie->rel, NULL,
- &cookie->locsyms[r_symndx]);
+ /* To work around a glibc bug, mark XXX input sections
+ when there is a reference to __start_XXX or __stop_XXX
+ symbols. */
+ else if (start_stop != NULL)
+ {
+ asection *s = h->u2.start_stop_section;
+ *start_stop = true;
+ return s;
+ }
+ }
+ return (*gc_mark_hook) (sec, info, cookie->rel, h, NULL);
}
/* COOKIE->rel describes a relocation against section SEC, which is
@@ -14860,17 +14885,11 @@ bfd_elf_reloc_symbol_deleted_p (bfd_vma offset, void *cookie)
if (r_symndx == STN_UNDEF)
return true;
- if (r_symndx >= rcookie->locsymcount
- || ELF_ST_BIND (rcookie->locsyms[r_symndx].st_info) != STB_LOCAL)
- {
- struct elf_link_hash_entry *h;
-
- h = rcookie->sym_hashes[r_symndx - rcookie->extsymoff];
-
- 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;
+ struct elf_link_hash_entry *h;
+ h = get_ext_sym_hash_from_cookie (rcookie, r_symndx);
+ if (h != NULL)
+ {
if ((h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
&& (h->root.u.def.section->owner != rcookie->abfd
@@ -14880,6 +14899,10 @@ bfd_elf_reloc_symbol_deleted_p (bfd_vma offset, void *cookie)
}
else
{
+ if (r_symndx >= rcookie->locsymcount)
+ /* This can happen with corrupt input. */
+ return false;
+
/* It's not a relocation against a global symbol,
but it could be a relocation against a local
symbol for a discarded section. */
@@ -14894,6 +14917,7 @@ bfd_elf_reloc_symbol_deleted_p (bfd_vma offset, void *cookie)
|| discarded_section (isec)))
return true;
}
+
return false;
}
return false;
diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
index 508fd771da3..8c261cf840a 100644
--- a/bfd/elfxx-x86.c
+++ b/bfd/elfxx-x86.c
@@ -972,15 +972,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,
@@ -1205,10 +1197,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)
--
2.43.0
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://sourceware.org/pipermail/binutils/attachments/20250505/7fbf2220/attachment-0001.htm>
More information about the Binutils
mailing list