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:
parent
c049096e82
commit
dd2b076850
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=15326
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user