Date: Thu, 5 Jul 2012 15:34:56 +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-9@freebsd.org Subject: svn commit: r238133 - stable/9/libexec/rtld-elf Message-ID: <201207051534.q65FYuwK081299@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kib Date: Thu Jul 5 15:34:55 2012 New Revision: 238133 URL: http://svn.freebsd.org/changeset/base/238133 Log: MFC r237659: Ensure that for the object which is a dependency for some filtee, relocations are performed before the object's initializer is called. Approved by: re (kensmith) Modified: stable/9/libexec/rtld-elf/rtld.c Directory Properties: stable/9/libexec/rtld-elf/ (props changed) Modified: stable/9/libexec/rtld-elf/rtld.c ============================================================================== --- stable/9/libexec/rtld-elf/rtld.c Thu Jul 5 15:34:04 2012 (r238132) +++ stable/9/libexec/rtld-elf/rtld.c Thu Jul 5 15:34:55 2012 (r238133) @@ -117,6 +117,10 @@ static void objlist_push_head(Objlist *, static void objlist_push_tail(Objlist *, Obj_Entry *); static void objlist_remove(Objlist *, Obj_Entry *); static void *path_enumerate(const char *, path_enum_proc, void *); +static int relocate_object_dag(Obj_Entry *root, bool bind_now, + Obj_Entry *rtldobj, int flags, RtldLockState *lockstate); +static int relocate_object(Obj_Entry *obj, bool bind_now, Obj_Entry *rtldobj, + int flags, RtldLockState *lockstate); static int relocate_objects(Obj_Entry *, bool, Obj_Entry *, int, RtldLockState *); static int resolve_objects_ifunc(Obj_Entry *first, bool bind_now, @@ -2217,52 +2221,70 @@ objlist_remove(Objlist *list, Obj_Entry } /* - * 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. + * Relocate dag rooted in the specified object. + * Returns 0 on success, or -1 on failure. */ + static int -relocate_objects(Obj_Entry *first, bool bind_now, Obj_Entry *rtldobj, +relocate_object_dag(Obj_Entry *root, bool bind_now, Obj_Entry *rtldobj, + int flags, RtldLockState *lockstate) +{ + Objlist_Entry *elm; + int error; + + error = 0; + STAILQ_FOREACH(elm, &root->dagmembers, link) { + error = relocate_object(elm->obj, bind_now, rtldobj, flags, + lockstate); + if (error == -1) + break; + } + return (error); +} + +/* + * Relocate single object. + * Returns 0 on success, or -1 on failure. + */ +static int +relocate_object(Obj_Entry *obj, bool bind_now, Obj_Entry *rtldobj, int flags, RtldLockState *lockstate) { - Obj_Entry *obj; - for (obj = first; obj != NULL; obj = obj->next) { if (obj->relocated) - continue; + return (0); obj->relocated = true; if (obj != rtldobj) - dbg("relocating \"%s\"", obj->path); + dbg("relocating \"%s\"", obj->path); if (obj->symtab == NULL || obj->strtab == NULL || - !(obj->valid_hash_sysv || obj->valid_hash_gnu)) { - _rtld_error("%s: Shared object has no run-time symbol table", - obj->path); - return -1; + !(obj->valid_hash_sysv || obj->valid_hash_gnu)) { + _rtld_error("%s: Shared object has no run-time symbol table", + obj->path); + return (-1); } if (obj->textrel) { - /* There are relocations to the write-protected text segment. */ - if (mprotect(obj->mapbase, obj->textsize, - PROT_READ|PROT_WRITE|PROT_EXEC) == -1) { - _rtld_error("%s: Cannot write-enable text segment: %s", - obj->path, rtld_strerror(errno)); - return -1; - } + /* There are relocations to the write-protected text segment. */ + if (mprotect(obj->mapbase, obj->textsize, + PROT_READ|PROT_WRITE|PROT_EXEC) == -1) { + _rtld_error("%s: Cannot write-enable text segment: %s", + obj->path, rtld_strerror(errno)); + return (-1); + } } /* Process the non-PLT relocations. */ if (reloc_non_plt(obj, rtldobj, flags, lockstate)) - return -1; + return (-1); if (obj->textrel) { /* Re-protected the text segment. */ - if (mprotect(obj->mapbase, obj->textsize, - PROT_READ|PROT_EXEC) == -1) { - _rtld_error("%s: Cannot write-protect text segment: %s", - obj->path, rtld_strerror(errno)); - return -1; - } + if (mprotect(obj->mapbase, obj->textsize, + PROT_READ|PROT_EXEC) == -1) { + _rtld_error("%s: Cannot write-protect text segment: %s", + obj->path, rtld_strerror(errno)); + return (-1); + } } @@ -2271,18 +2293,19 @@ relocate_objects(Obj_Entry *first, bool /* Process the PLT relocations. */ if (reloc_plt(obj) == -1) - return -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) - return -1; + if (reloc_jmpslots(obj, flags, lockstate) == -1) + return (-1); if (obj->relro_size > 0) { - if (mprotect(obj->relro_page, obj->relro_size, PROT_READ) == -1) { - _rtld_error("%s: Cannot enforce relro protection: %s", - obj->path, rtld_strerror(errno)); - return -1; - } + if (mprotect(obj->relro_page, obj->relro_size, + PROT_READ) == -1) { + _rtld_error("%s: Cannot enforce relro protection: %s", + obj->path, rtld_strerror(errno)); + return (-1); + } } /* @@ -2292,9 +2315,30 @@ relocate_objects(Obj_Entry *first, bool */ obj->magic = RTLD_MAGIC; obj->version = RTLD_VERSION; - } - return (0); + 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, + * or -1 on failure. + */ +static int +relocate_objects(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 = obj->next) { + error = relocate_object(obj, bind_now, rtldobj, flags, + lockstate); + if (error == -1) + break; + } + return (error); } /* @@ -2614,10 +2658,10 @@ dlopen_object(const char *name, int fd, result = rtld_verify_versions(&obj->dagmembers); if (result != -1 && ld_tracing) goto trace; - if (result == -1 || (relocate_objects(obj, - (mode & RTLD_MODEMASK) == RTLD_NOW, &obj_rtld, + if (result == -1 || relocate_object_dag(obj, + (mode & RTLD_MODEMASK) == RTLD_NOW, &obj_rtld, (lo_flags & RTLD_LO_EARLY) ? SYMLOOK_EARLY : 0, - lockstate)) == -1) { + lockstate) == -1) { dlopen_cleanup(obj); obj = NULL; } else if (lo_flags & RTLD_LO_EARLY) {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201207051534.q65FYuwK081299>