summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjdp <jdp@FreeBSD.org>1996-04-20 18:29:50 +0000
committerjdp <jdp@FreeBSD.org>1996-04-20 18:29:50 +0000
commitbdd60b12a416606d70dc3e0708a9f82893051bcf (patch)
treefab07625d67382bc73375d28eaf464385addf4ff
parent442c49eed881daec1430fe104b241beeb6d2de00 (diff)
downloadFreeBSD-src-bdd60b12a416606d70dc3e0708a9f82893051bcf.zip
FreeBSD-src-bdd60b12a416606d70dc3e0708a9f82893051bcf.tar.gz
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 <ambrisko@ambrisko.roble.com>
-rw-r--r--gnu/usr.bin/ld/rtld/rtld.118
-rw-r--r--gnu/usr.bin/ld/rtld/rtld.c106
-rw-r--r--libexec/rtld-aout/rtld.118
-rw-r--r--libexec/rtld-aout/rtld.1aout18
-rw-r--r--libexec/rtld-aout/rtld.c106
-rw-r--r--libexec/rtld-elf/rtld.118
6 files changed, 236 insertions, 48 deletions
diff --git a/gnu/usr.bin/ld/rtld/rtld.1 b/gnu/usr.bin/ld/rtld/rtld.1
index 2b3c75a..a66a861 100644
--- a/gnu/usr.bin/ld/rtld/rtld.1
+++ b/gnu/usr.bin/ld/rtld/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/gnu/usr.bin/ld/rtld/rtld.c b/gnu/usr.bin/ld/rtld/rtld.c
index 3300538..bade56e 100644
--- a/gnu/usr.bin/ld/rtld/rtld.c
+++ b/gnu/usr.bin/ld/rtld/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 <sys/param.h>
@@ -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-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 <sys/param.h>
@@ -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
OpenPOWER on IntegriCloud