Index: libexec/rtld-elf/rtld.c =================================================================== --- libexec/rtld-elf/rtld.c +++ libexec/rtld-elf/rtld.c @@ -134,6 +134,8 @@ int flags, RtldLockState *lockstate); static int relocate_objects(Obj_Entry *, bool, Obj_Entry *, int, RtldLockState *); +static int relocate_objects2(Obj_Entry *, bool, Obj_Entry *, int, + RtldLockState *); static int resolve_objects_ifunc(Obj_Entry *first, bool bind_now, int flags, RtldLockState *lockstate); static int rtld_dirname(const char *, char *); @@ -682,10 +684,6 @@ if (do_copy_relocations(obj_main) == -1) rtld_die(); - dbg("enforcing main obj relro"); - if (obj_enforce_relro(obj_main) == -1) - rtld_die(); - if (getenv(_LD("DUMP_REL_POST")) != NULL) { dump_relocations(obj_main); exit (0); @@ -714,6 +712,16 @@ map_stacks_exec(NULL); ifunc_init(aux); + if (relocate_objects2(obj_main, + ld_bind_now != NULL && *ld_bind_now != '\0', + &obj_rtld, SYMLOOK_EARLY, NULL) == -1) + rtld_die(); + + dbg("enforcing main obj relro"); + if (obj_enforce_relro(obj_main) == -1) + rtld_die(); + + dbg("resolving ifuncs"); if (resolve_objects_ifunc(obj_main, ld_bind_now != NULL && *ld_bind_now != '\0', SYMLOOK_EARLY, @@ -2849,6 +2857,22 @@ if (reloc_jmpslots(obj, flags, lockstate) == -1) return (-1); + /* + * Set up the magic number and version in the Obj_Entry. These + * were checked in the crt1.o from the original ElfKit, so we + * set them for backward compatibility. + */ + obj->magic = RTLD_MAGIC; + obj->version = RTLD_VERSION; + + return (0); +} + +static int +relocate_object2(Obj_Entry *obj, bool bind_now, Obj_Entry *rtldobj, + int flags, RtldLockState *lockstate) +{ + /* * Process the non-PLT IFUNC relocations. The relocations are * processed in two phases, because IFUNC resolvers may @@ -2862,21 +2886,14 @@ if (!obj->mainprog && obj_enforce_relro(obj) == -1) return (-1); - /* - * Set up the magic number and version in the Obj_Entry. These - * were checked in the crt1.o from the original ElfKit, so we - * set them for backward compatibility. - */ - obj->magic = RTLD_MAGIC; - obj->version = RTLD_VERSION; - return (0); } + /* - * Relocate newly-loaded shared objects. The argument is a pointer to - * the Obj_Entry for the first such object. All objects from the first - * to the end of the list of objects are relocated. Returns 0 on success, + * relocate newly-loaded shared objects. the argument is a pointer to + * the obj_entry for the first such object. all objects from the first + * to the end of the list of objects are relocated. returns 0 on success, * or -1 on failure. */ static int @@ -2898,6 +2915,30 @@ return (error); } +/* + * Phase 2 of object relocation. Once all objects are loaded and have had + * their relocations applied (but before any init functions are called), + * resolve ifuncs and make the relocations read only if relro is set. + */ +static int +relocate_objects2(Obj_Entry *first, bool bind_now, Obj_Entry *rtldobj, + int flags, RtldLockState *lockstate) +{ + Obj_Entry *obj; + int error; + + for (error = 0, obj = first; obj != NULL; + obj = TAILQ_NEXT(obj, next)) { + if (obj->marker) + continue; + error = relocate_object2(obj, bind_now, rtldobj, flags, + lockstate); + if (error == -1) + break; + } + return (error); +} + /* * The handling of R_MACHINE_IRELATIVE relocations and jumpslots * referencing STT_GNU_IFUNC symbols is postponed till the other