Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 10 Dec 2018 00:54:18 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org
Subject:   svn commit: r341772 - stable/12/libexec/rtld-elf
Message-ID:  <201812100054.wBA0sI59032226@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Mon Dec 10 00:54:18 2018
New Revision: 341772
URL: https://svnweb.freebsd.org/changeset/base/341772

Log:
  MFC r341441:
  Some fixes for LD_BIND_NOW + ifuncs.

Modified:
  stable/12/libexec/rtld-elf/rtld.c
  stable/12/libexec/rtld-elf/rtld.h
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/libexec/rtld-elf/rtld.c
==============================================================================
--- stable/12/libexec/rtld-elf/rtld.c	Sun Dec  9 22:42:22 2018	(r341771)
+++ stable/12/libexec/rtld-elf/rtld.c	Mon Dec 10 00:54:18 2018	(r341772)
@@ -103,6 +103,7 @@ static void init_pagesizes(Elf_Auxinfo **aux_info);
 static void init_rtld(caddr_t, Elf_Auxinfo **);
 static void initlist_add_neededs(Needed_Entry *, Objlist *);
 static void initlist_add_objects(Obj_Entry *, Obj_Entry *, Objlist *);
+static int initlist_objects_ifunc(Objlist *, bool, int, RtldLockState *);
 static void linkmap_add(Obj_Entry *);
 static void linkmap_delete(Obj_Entry *);
 static void load_filtees(Obj_Entry *, int flags, RtldLockState *);
@@ -111,6 +112,7 @@ static int load_needed_objects(Obj_Entry *, int);
 static int load_preload_objects(void);
 static Obj_Entry *load_object(const char *, int fd, const Obj_Entry *, int);
 static void map_stacks_exec(RtldLockState *);
+static int obj_disable_relro(Obj_Entry *);
 static int obj_enforce_relro(Obj_Entry *);
 static Obj_Entry *obj_from_addr(const void *);
 static void objlist_call_fini(Objlist *, Obj_Entry *, RtldLockState *);
@@ -135,8 +137,6 @@ static int relocate_object(Obj_Entry *obj, bool bind_n
 static int relocate_objects(Obj_Entry *, bool, Obj_Entry *, int,
     RtldLockState *);
 static int resolve_object_ifunc(Obj_Entry *, bool, int, RtldLockState *);
-static int resolve_objects_ifunc(Obj_Entry *first, bool bind_now,
-    int flags, RtldLockState *lockstate);
 static int rtld_dirname(const char *, char *);
 static int rtld_dirname_abs(const char *, char *);
 static void *rtld_dlopen(const char *name, int fd, int mode);
@@ -713,16 +713,6 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entr
 
     map_stacks_exec(NULL);
 
-    dbg("resolving ifuncs");
-    if (resolve_objects_ifunc(obj_main,
-      ld_bind_now != NULL && *ld_bind_now != '\0', SYMLOOK_EARLY,
-      NULL) == -1)
-	rtld_die();
-
-    dbg("enforcing main obj relro");
-    if (obj_enforce_relro(obj_main) == -1)
-	rtld_die();
-
     if (!obj_main->crt_no_init) {
 	/*
 	 * Make sure we don't call the main program's init and fini
@@ -741,6 +731,12 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entr
     pre_init();
 
     wlock_acquire(rtld_bind_lock, &lockstate);
+
+    dbg("resolving ifuncs");
+    if (initlist_objects_ifunc(&initlist, ld_bind_now != NULL &&
+      *ld_bind_now != '\0', SYMLOOK_EARLY, &lockstate) == -1)
+	rtld_die();
+
     if (obj_main->crt_no_init)
 	preinit_main();
     objlist_call_init(&initlist, &lockstate);
@@ -753,6 +749,11 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entr
 	if (ld_loadfltr || obj->z_loadfltr)
 	    load_filtees(obj, 0, &lockstate);
     }
+
+    dbg("enforcing main obj relro");
+    if (obj_enforce_relro(obj_main) == -1)
+	rtld_die();
+
     lock_release(rtld_bind_lock, &lockstate);
 
     dbg("transferring control to program entry point = %p", obj_main->entry);
@@ -2217,9 +2218,7 @@ initlist_add_objects(Obj_Entry *obj, Obj_Entry *tail, 
 	initlist_add_neededs(obj->needed_aux_filtees, list);
 
     /* Add the object to the init list. */
-    if (obj->preinit_array != (Elf_Addr)NULL || obj->init != (Elf_Addr)NULL ||
-      obj->init_array != (Elf_Addr)NULL)
-	objlist_push_tail(list, obj);
+    objlist_push_tail(list, obj);
 
     /* Add the object to the global fini list in the reverse order. */
     if ((obj->fini != (Elf_Addr)NULL || obj->fini_array != (Elf_Addr)NULL)
@@ -2868,11 +2867,9 @@ relocate_object(Obj_Entry *obj, bool bind_now, Obj_Ent
 	if (reloc_plt(obj) == -1)
 		return (-1);
 	/* Relocate the jump slots if we are doing immediate binding. */
-	if (obj->bind_now || bind_now) {
-		if (reloc_jmpslots(obj, flags, lockstate) == -1 ||
-		    resolve_object_ifunc(obj, true, flags, lockstate) == -1)
-			return (-1);
-	}
+	if ((obj->bind_now || bind_now) && reloc_jmpslots(obj, flags,
+	    lockstate) == -1)
+		return (-1);
 
 	/*
 	 * Process the non-PLT IFUNC relocations.  The relocations are
@@ -2938,24 +2935,16 @@ static int
 resolve_object_ifunc(Obj_Entry *obj, bool bind_now, int flags,
     RtldLockState *lockstate)
 {
+
+	if (obj->ifuncs_resolved)
+		return (0);
+	obj->ifuncs_resolved = true;
 	if (obj->irelative && reloc_iresolve(obj, lockstate) == -1)
 		return (-1);
-	if ((obj->bind_now || bind_now) && obj->gnu_ifunc &&
-	    reloc_gnu_ifunc(obj, flags, lockstate) == -1)
-		return (-1);
-	return (0);
-}
-
-static int
-resolve_objects_ifunc(Obj_Entry *first, bool bind_now, int flags,
-    RtldLockState *lockstate)
-{
-	Obj_Entry *obj;
-
-	for (obj = first; obj != NULL; obj = TAILQ_NEXT(obj, next)) {
-		if (obj->marker)
-			continue;
-		if (resolve_object_ifunc(obj, bind_now, flags, lockstate) == -1)
+	if ((obj->bind_now || bind_now) && obj->gnu_ifunc) {
+		if (obj_disable_relro(obj) ||
+		    reloc_gnu_ifunc(obj, flags, lockstate) == -1 ||
+		    obj_enforce_relro(obj))
 			return (-1);
 	}
 	return (0);
@@ -2966,9 +2955,13 @@ initlist_objects_ifunc(Objlist *list, bool bind_now, i
     RtldLockState *lockstate)
 {
 	Objlist_Entry *elm;
+	Obj_Entry *obj;
 
 	STAILQ_FOREACH(elm, list, link) {
-		if (resolve_object_ifunc(elm->obj, bind_now, flags,
+		obj = elm->obj;
+		if (obj->marker)
+			continue;
+		if (resolve_object_ifunc(obj, bind_now, flags,
 		    lockstate) == -1)
 			return (-1);
 	}
@@ -5328,17 +5321,31 @@ _rtld_is_dlopened(void *arg)
 	return (res);
 }
 
-int
-obj_enforce_relro(Obj_Entry *obj)
+static int
+obj_remap_relro(Obj_Entry *obj, int prot)
 {
 
 	if (obj->relro_size > 0 && mprotect(obj->relro_page, obj->relro_size,
-	    PROT_READ) == -1) {
-		_rtld_error("%s: Cannot enforce relro protection: %s",
-		    obj->path, rtld_strerror(errno));
+	    prot) == -1) {
+		_rtld_error("%s: Cannot set relro protection to %#x: %s",
+		    obj->path, prot, rtld_strerror(errno));
 		return (-1);
 	}
 	return (0);
+}
+
+static int
+obj_disable_relro(Obj_Entry *obj)
+{
+
+	return (obj_remap_relro(obj, PROT_READ | PROT_WRITE));
+}
+
+static int
+obj_enforce_relro(Obj_Entry *obj)
+{
+
+	return (obj_remap_relro(obj, PROT_READ));
 }
 
 static void

Modified: stable/12/libexec/rtld-elf/rtld.h
==============================================================================
--- stable/12/libexec/rtld-elf/rtld.h	Sun Dec  9 22:42:22 2018	(r341771)
+++ stable/12/libexec/rtld-elf/rtld.h	Mon Dec 10 00:54:18 2018	(r341772)
@@ -265,6 +265,7 @@ typedef struct Struct_Obj_Entry {
     bool irelative : 1;		/* Object has R_MACHDEP_IRELATIVE relocs */
     bool gnu_ifunc : 1;		/* Object has references to STT_GNU_IFUNC */
     bool non_plt_gnu_ifunc : 1;	/* Object has non-plt IFUNC references */
+    bool ifuncs_resolved : 1;	/* Object ifuncs were already resolved */
     bool crt_no_init : 1;	/* Object' crt does not call _init/_fini */
     bool valid_hash_sysv : 1;	/* A valid System V hash hash tag is available */
     bool valid_hash_gnu : 1;	/* A valid GNU hash tag is available */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201812100054.wBA0sI59032226>