git: e0d7fe1a03d1 - stable/12 - link_elf_obj: Process global ifunc relocs after other global relocs

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Thu, 02 Dec 2021 14:15:52 UTC
The branch stable/12 has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=e0d7fe1a03d17b3f6dc03e1079d103ce5a366feb

commit e0d7fe1a03d17b3f6dc03e1079d103ce5a366feb
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2021-11-25 21:52:17 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2021-12-02 14:15:42 +0000

    link_elf_obj: Process global ifunc relocs after other global relocs
    
    This is needed to ensure that resolvers that reference global symbols
    return correct results.
    
    Reviewed by:    kib
    Sponsored by:   The FreeBSD Foundation
    
    (cherry picked from commit b11e6fd75b1bb9d337b0edab14d160ff65b11aae)
---
 sys/kern/link_elf_obj.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c
index c892c14833d6..5b79b0b4c17c 100644
--- a/sys/kern/link_elf_obj.c
+++ b/sys/kern/link_elf_obj.c
@@ -1244,7 +1244,7 @@ findbase(elf_file_t ef, int sec)
 }
 
 static int
-relocate_file(elf_file_t ef)
+relocate_file1(elf_file_t ef, bool ifuncs)
 {
 	const Elf_Rel *rellim;
 	const Elf_Rel *rel;
@@ -1278,6 +1278,9 @@ relocate_file(elf_file_t ef)
 			/* Local relocs are already done */
 			if (ELF_ST_BIND(sym->st_info) == STB_LOCAL)
 				continue;
+			if ((ELF_ST_TYPE(sym->st_info) == STT_GNU_IFUNC ||
+			    elf_is_ifunc_reloc(rel->r_info)) != ifuncs)
+				continue;
 			if (elf_reloc(&ef->lf, base, rel, ELF_RELOC_REL,
 			    elf_obj_lookup)) {
 				symname = symbol_name(ef, rel->r_info);
@@ -1310,6 +1313,9 @@ relocate_file(elf_file_t ef)
 			/* Local relocs are already done */
 			if (ELF_ST_BIND(sym->st_info) == STB_LOCAL)
 				continue;
+			if ((ELF_ST_TYPE(sym->st_info) == STT_GNU_IFUNC ||
+			    elf_is_ifunc_reloc(rela->r_info)) != ifuncs)
+				continue;
 			if (elf_reloc(&ef->lf, base, rela, ELF_RELOC_RELA,
 			    elf_obj_lookup)) {
 				symname = symbol_name(ef, rela->r_info);
@@ -1330,6 +1336,17 @@ relocate_file(elf_file_t ef)
 	return (0);
 }
 
+static int
+relocate_file(elf_file_t ef)
+{
+	int error;
+
+	error = relocate_file1(ef, false);
+	if (error == 0)
+		error = relocate_file1(ef, true);
+	return (error);
+}
+
 static int
 link_elf_lookup_symbol(linker_file_t lf, const char *name, c_linker_sym_t *sym)
 {