From bdd60b12a416606d70dc3e0708a9f82893051bcf Mon Sep 17 00:00:00 2001 From: jdp Date: Sat, 20 Apr 1996 18:29:50 +0000 Subject: Implement support for LD_PRELOAD in the dynamic linker. Remove descriptions of LD_NO_INTERN_SEARCH and LD_NOSTD_PATH from the manual page, since they are not supported. Submitted by: Doug Ambrisko --- libexec/rtld-aout/rtld.1 | 18 ++++---- libexec/rtld-aout/rtld.1aout | 18 ++++---- libexec/rtld-aout/rtld.c | 106 +++++++++++++++++++++++++++++++++++++++++-- libexec/rtld-elf/rtld.1 | 18 ++++---- 4 files changed, 126 insertions(+), 34 deletions(-) (limited to 'libexec') diff --git a/libexec/rtld-aout/rtld.1 b/libexec/rtld-aout/rtld.1 index 2b3c75a..a66a861 100644 --- a/libexec/rtld-aout/rtld.1 +++ b/libexec/rtld-aout/rtld.1 @@ -1,4 +1,4 @@ -.\" $Id$ +.\" $Id: rtld.1,v 1.2 1995/10/05 05:16:52 nate Exp $ .\" .\" Copyright (c) 1995 Paul Kranenburg .\" All rights reserved. @@ -110,6 +110,13 @@ its behaviour as follows: .It Ev LD_LIBRARY_PATH A colon separated list of directories, overriding the default search path for shared libraries. +This is ignored for set-user-ID and set-group-ID programs. +.It Ev LD_PRELOAD +A colon separated list of shared libraries, to be linked in before any +other shared libraries. If the directory is not specified then +the directories specified by LD_LIBRARY_PATH will be searched first +followed by the set of built-in standard directories. +This is ignored for set-user-ID and set-group-ID programs. .It Ev LD_WARN_NON_PURE_CODE When set, issue a warning whenever a link-editing operation requires modification of the text segment of some loaded object. This is usually @@ -122,15 +129,6 @@ When set, causes .Nm to exit after loading the shared objects and printing a summary which includes the absolute pathnames of all objects, to standard output. -.It Ev LD_NO_INTERN_SEARCH -When set, -.Nm -does not process any internal search paths that were recorded in the -executable. -.It Ev LD_NOSTD_PATH -When set, do not include a set of built-in standard directory paths for -searching. This might be useful when running on a system with a completely -non-standard filesystem layout. .El .Pp .Sh FILES diff --git a/libexec/rtld-aout/rtld.1aout b/libexec/rtld-aout/rtld.1aout index 2b3c75a..a66a861 100644 --- a/libexec/rtld-aout/rtld.1aout +++ b/libexec/rtld-aout/rtld.1aout @@ -1,4 +1,4 @@ -.\" $Id$ +.\" $Id: rtld.1,v 1.2 1995/10/05 05:16:52 nate Exp $ .\" .\" Copyright (c) 1995 Paul Kranenburg .\" All rights reserved. @@ -110,6 +110,13 @@ its behaviour as follows: .It Ev LD_LIBRARY_PATH A colon separated list of directories, overriding the default search path for shared libraries. +This is ignored for set-user-ID and set-group-ID programs. +.It Ev LD_PRELOAD +A colon separated list of shared libraries, to be linked in before any +other shared libraries. If the directory is not specified then +the directories specified by LD_LIBRARY_PATH will be searched first +followed by the set of built-in standard directories. +This is ignored for set-user-ID and set-group-ID programs. .It Ev LD_WARN_NON_PURE_CODE When set, issue a warning whenever a link-editing operation requires modification of the text segment of some loaded object. This is usually @@ -122,15 +129,6 @@ When set, causes .Nm to exit after loading the shared objects and printing a summary which includes the absolute pathnames of all objects, to standard output. -.It Ev LD_NO_INTERN_SEARCH -When set, -.Nm -does not process any internal search paths that were recorded in the -executable. -.It Ev LD_NOSTD_PATH -When set, do not include a set of built-in standard directory paths for -searching. This might be useful when running on a system with a completely -non-standard filesystem layout. .El .Pp .Sh FILES diff --git a/libexec/rtld-aout/rtld.c b/libexec/rtld-aout/rtld.c index 3300538..bade56e 100644 --- a/libexec/rtld-aout/rtld.c +++ b/libexec/rtld-aout/rtld.c @@ -27,7 +27,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: rtld.c,v 1.31.1.5 1995/11/28 01:15:45 jdp Exp jdp $ + * $Id: rtld.c,v 1.32 1996/01/13 00:15:25 jdp Exp $ */ #include @@ -163,6 +163,7 @@ static char *main_progname = __main_progname; static char us[] = "/usr/libexec/ld.so"; static int anon_fd = -1; static char *ld_library_path; +static char *ld_preload; static int tracing; struct so_map *link_map_head; @@ -183,6 +184,7 @@ static struct ld_entry ld_entry = { static struct so_map *map_object __P(( char *, struct sod *, struct so_map *)); +static int map_preload __P((void)); static int map_sods __P((struct so_map *)); static int reloc_and_init __P((struct so_map *)); static void unmap_object __P((struct so_map *, int)); @@ -200,6 +202,7 @@ static void init_sods __P((struct so_list *)); static int call_map __P((struct so_map *, char *)); static char *findhint __P((char *, int, int *)); static char *rtfindlib __P((char *, int, int)); +static char *rtfindfile __P((char *)); void binder_entry __P((void)); long binder __P((jmpslot_t *)); static struct nzlist *lookup __P((char *, struct so_map **, int)); @@ -280,8 +283,10 @@ struct _dynamic *dp; if (careful) { unsetenv("LD_LIBRARY_PATH"); unsetenv("LD_PRELOAD"); - } else + } else { ld_library_path = getenv("LD_LIBRARY_PATH"); + ld_preload = getenv("LD_PRELOAD"); + } tracing = getenv("LD_TRACE_LOADED_OBJECTS") != NULL; @@ -312,6 +317,13 @@ struct _dynamic *dp; crtp->crt_dp->d_entry = &ld_entry; crtp->crt_dp->d_un.d_sdt->sdt_loaded = link_map_head->som_next; + /* Map in LD_PRELOADs before the main program's shared objects so we + can intercept those calls */ + if (ld_preload != NULL && *ld_preload != '\0') { + if(map_preload() == -1) /* Failed */ + return -1; + } + /* Map all the shared objects that the main program depends upon */ if(map_sods(main_map) == -1) return -1; @@ -595,6 +607,48 @@ map_object(path, sodp, parent) } /* + * Map all the shared libraries named in the LD_PRELOAD environment + * variable. + * + * Returns 0 on success, -1 on failure. On failure, an error message can + * be gotten via dlerror(). + */ + static int +map_preload __P((void)) { + char *ld_name = ld_preload; + char *name; + + while ((name = strsep(&ld_name, ":")) != NULL) { + char *path = NULL; + struct so_map *smp = NULL; + + if (*name != '\0') { + path = (strchr(name, '/') != NULL) ? strdup(name) : + rtfindfile(name); + } + if (path == NULL) { + generror("Can't find LD_PRELOAD shared" + " library \"%s\"", name); + } else { + smp = map_object(path, (struct sod *) NULL, + (struct so_map *) NULL); + free(path); + } + if (ld_name != NULL) + *(ld_name - 1) = ':'; + if (smp == NULL) { + /* + * We don't bother to unmap already-loaded libraries + * on failure, because in that case the program is + * about to die anyway. + */ + return -1; + } + } + return 0; +} + +/* * Map all of the shared objects that a given object depends upon. PARENT is * a pointer to the link map for the shared object whose dependencies are * to be mapped. @@ -1531,8 +1585,8 @@ rtfindlib(name, major, minor) while (path == NULL && (dir = strsep(&ld_path, ":")) != NULL) { path = search_lib_dir(dir, name, &major, &realminor, 0); - if (ld_path) - *(ld_path-1) = ':'; + if (ld_path != NULL) + *(ld_path - 1) = ':'; } } @@ -1554,6 +1608,50 @@ rtfindlib(name, major, minor) } /* + * Search for the given shared library file. This is similar to rtfindlib, + * except that the argument is the actual name of the desired library file. + * Thus there is no need to worry about version numbers. The return value + * is a string containing the full pathname for the library. This string + * is always dynamically allocated on the heap. + * + * Returns NULL if the library cannot be found. + */ + static char * +rtfindfile(name) + char *name; +{ + char *ld_path = ld_library_path; + char *path = NULL; + + if (ld_path != NULL) { /* First, search the directories in ld_path */ + char *dir; + + while (path == NULL && (dir = strsep(&ld_path, ":")) != NULL) { + struct stat sb; + + path = concat(dir, "/", name); + if (lstat(path, &sb) == -1) { /* Does not exist */ + free(path); + path = NULL; + } + if (ld_path != NULL) + *(ld_path - 1) = ':'; + } + } + + /* + * We don't search the hints file. It is organized around major + * and minor version numbers, so it is not suitable for finding + * a specific file name. + */ + + if (path == NULL) /* Search the standard directories */ + path = find_lib_file(name); + + return path; +} + +/* * Buffer for error messages and a pointer that is set to point to the buffer * when a error occurs. It acts as a last error flag, being set to NULL * after an error is returned. diff --git a/libexec/rtld-elf/rtld.1 b/libexec/rtld-elf/rtld.1 index 2b3c75a..a66a861 100644 --- a/libexec/rtld-elf/rtld.1 +++ b/libexec/rtld-elf/rtld.1 @@ -1,4 +1,4 @@ -.\" $Id$ +.\" $Id: rtld.1,v 1.2 1995/10/05 05:16:52 nate Exp $ .\" .\" Copyright (c) 1995 Paul Kranenburg .\" All rights reserved. @@ -110,6 +110,13 @@ its behaviour as follows: .It Ev LD_LIBRARY_PATH A colon separated list of directories, overriding the default search path for shared libraries. +This is ignored for set-user-ID and set-group-ID programs. +.It Ev LD_PRELOAD +A colon separated list of shared libraries, to be linked in before any +other shared libraries. If the directory is not specified then +the directories specified by LD_LIBRARY_PATH will be searched first +followed by the set of built-in standard directories. +This is ignored for set-user-ID and set-group-ID programs. .It Ev LD_WARN_NON_PURE_CODE When set, issue a warning whenever a link-editing operation requires modification of the text segment of some loaded object. This is usually @@ -122,15 +129,6 @@ When set, causes .Nm to exit after loading the shared objects and printing a summary which includes the absolute pathnames of all objects, to standard output. -.It Ev LD_NO_INTERN_SEARCH -When set, -.Nm -does not process any internal search paths that were recorded in the -executable. -.It Ev LD_NOSTD_PATH -When set, do not include a set of built-in standard directory paths for -searching. This might be useful when running on a system with a completely -non-standard filesystem layout. .El .Pp .Sh FILES -- cgit v1.1