From 82670cebd1fcecfc16c075c1bd9ec404e3f9af41 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Thu, 29 May 2025 02:41:27 -0700 Subject: [PATCH] Prevent illegal memory access when indexing into the sym_hashes array of the elf bfd cookie structure. PR 32636 (cherry picked from commit: f9978defb6fab0bd8583942d97c112b0932ac814) Upstream-Status: Backport [https://sourceware.org/git/?p=binutils-gdb.git;a=patch;h=f9978defb6fab0bd8583942d97c112b0932ac814] CVE: CVE-2025-1180 Signed-off-by: Harish Sadineni --- bfd/elflink.c | 90 ++++++++++++++++++++++++++------------------------- 1 file changed, 46 insertions(+), 44 deletions(-) diff --git a/bfd/elflink.c b/bfd/elflink.c index f8521426cad..4c21a0229e7 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -62,15 +62,16 @@ struct elf_find_verdep_info 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_ext_sym_hash (struct elf_reloc_cookie *cookie, unsigned long r_symndx) { - if (r_symndx >= cookie->locsymcount - || ELF_ST_BIND (cookie->locsyms[r_symndx].st_info) != STB_LOCAL) + struct elf_link_hash_entry *h = NULL; + + if ((r_symndx >= cookie->locsymcount + || ELF_ST_BIND (cookie->locsyms[r_symndx].st_info) != STB_LOCAL) + /* Guard against corrupt input. See PR 32636 for an example. */ + && r_symndx >= cookie->extsymoff) { - struct elf_link_hash_entry *h; h = cookie->sym_hashes[r_symndx - cookie->extsymoff]; @@ -78,6 +79,22 @@ _bfd_elf_section_for_symbol (struct elf_reloc_cookie *cookie, || h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; + } + + return h; +} + +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 (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)) @@ -85,21 +102,20 @@ _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; - /* 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; - } + /* 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; + return NULL; } @@ -13642,22 +13658,12 @@ _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 (cookie, r_symndx); + + if (h != NULL) { bool was_marked; - 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 @@ -14703,17 +14709,12 @@ 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 (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 @@ -14737,6 +14738,7 @@ bfd_elf_reloc_symbol_deleted_p (bfd_vma offset, void *cookie) || discarded_section (isec))) return true; } + return false; } return false; -- 2.49.0