1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-03 09:00:21 +00:00

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>
This commit is contained in:
John Polstra 1996-04-20 18:29:50 +00:00
parent c049096e82
commit dd2b076850
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=15326
6 changed files with 236 additions and 48 deletions

View File

@ -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

View File

@ -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;
@ -594,6 +606,48 @@ map_object(path, sodp, parent)
return smp;
}
/*
* 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
@ -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) = ':';
}
}
@ -1553,6 +1607,50 @@ rtfindlib(name, major, minor)
return path;
}
/*
* 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

View File

@ -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

View File

@ -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

View File

@ -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;
@ -594,6 +606,48 @@ map_object(path, sodp, parent)
return smp;
}
/*
* 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
@ -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) = ':';
}
}
@ -1553,6 +1607,50 @@ rtfindlib(name, major, minor)
return path;
}
/*
* 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

View File

@ -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