Import the DragonFly BSD commit 4f0bc915b65fcf5a23214f6d221d65c80be68ad4
by John Marino <draco@marino.st>, with the following (edited) commit message Date: Sat, 24 Mar 2012 06:40:50 +0100 Subject: [PATCH 1/1] rtld: Implement DT_RUNPATH and -z nodefaultlib DT_RUNPATH is incorrectly being considered as an alias of DT_RPATH. The purpose of DT_RUNPATH is to have two different types of rpath: one that can be overridden by the environment variable LD_LIBRARY_PATH and one that can't. With the currently implementation, LD_LIBRARY_PATH will always trump any embedded rpath or runpath tags. Current path search order by rtld: ================================== LD_LIBRARY_PATH DT_RPATH / DT_RUNPATH (always the same) ldconfig hints file (default: /var/run/ld-elf.so.hints) /usr/lib New path search order by rtld: ============================== DT_RPATH of the calling object if no DT_RUNPATH DT_RPATH of the main binary if no DT_RUNPATH and binary isn't calling obj LD_LIBRARY_PATH DT_RUNPATH ldconfig hints file /usr/lib The new path search matches how the linux runtime loader works. The other major added feature is support for linker flag "-z nodefaultlib". When this flag is passed to the linker, rtld will skip all references to the standard library search path ("/usr/lib" in this case but it could handle more color delimited paths) except in DT_RPATH and DT_RUNPATH. New path search order by rtld with -z nodefaultlib flag set: ============================================================ DT_RPATH of the calling object if no DT_RUNPATH DT_RPATH of the main binary if no DT_RUNPATH and binary isn't calling obj LD_LIBRARY_PATH DT_RUNPATH ldconfig hints file (skips all references to /usr/lib) FreeBSD notes: - we fixed some bugs which were submitted to DragonFly and merged there as commit 1ff8a2bd3eb6e5587174c6a983303ea3a79e0002; - we added LD_LIBRARY_PATH_RPATH environment variable to switch to the previous behaviour of considering DT_RPATH a synonym for DT_RUNPATH; - the FreeBSD default search path is /lib:/usr/lib and not /usr/lib. Reviewed by: kan MFC after: 1 month MFC note: flip the ld_library_path_rpath default value for stable/9
This commit is contained in:
parent
4d945ad412
commit
a78a2e3c36
@ -28,7 +28,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd April 1, 2009
|
||||
.Dd June 28, 2012
|
||||
.Dt RTLD 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -86,14 +86,39 @@ dynamic linker.
|
||||
After the dynamic linker has finished loading,
|
||||
relocating, and initializing the program and its required shared
|
||||
objects, it transfers control to the entry point of the program.
|
||||
The following search order is used to locate required shared objects:
|
||||
.Pp
|
||||
To locate the required shared objects in the file system,
|
||||
.Nm
|
||||
may use a
|
||||
.Dq hints
|
||||
file prepared by the
|
||||
.Bl -enum -offset indent -compact
|
||||
.It
|
||||
.Dv DT_RPATH
|
||||
of the referencing object unless that object also contains a
|
||||
.Dv DT_RUNPATH
|
||||
tag
|
||||
.It
|
||||
.Dv DT_RPATH
|
||||
of the program unless the referencing object contains a
|
||||
.Dv DT_RUNPATH
|
||||
tag
|
||||
.It
|
||||
Path indicated by
|
||||
.Ev LD_LIBRARY_PATH
|
||||
environment variable
|
||||
.It
|
||||
.Dv DT_RUNPATH
|
||||
of the referencing object
|
||||
.It
|
||||
Hints file produced by the
|
||||
.Xr ldconfig 8
|
||||
utility.
|
||||
utility
|
||||
.It
|
||||
The
|
||||
.Pa /lib
|
||||
and
|
||||
.Pa /usr/lib
|
||||
directories, unless the referencing object was linked using the
|
||||
.Dq Fl z Ar nodefaultlib
|
||||
option
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
@ -143,6 +168,20 @@ This variable is unset for set-user-ID and set-group-ID programs.
|
||||
A colon separated list of directories, overriding the default search path
|
||||
for shared libraries.
|
||||
This variable is unset for set-user-ID and set-group-ID programs.
|
||||
.It Ev LD_LIBRARY_PATH_RPATH
|
||||
If the variable is specified and has a value starting with
|
||||
any of \'y\', \'Y\' or \'1\' symbols, the path specified by
|
||||
.Ev LD_LIBRARY_PATH
|
||||
variable is allowed to override the path from
|
||||
.Dv DT_RPATH
|
||||
for binaries which does not contain
|
||||
.Dv DT_RUNPATH
|
||||
tag.
|
||||
For such binaries, when the variable
|
||||
.Ev LD_LIBRARY_PATH_RPATH
|
||||
is set,
|
||||
.Dq Fl z Ar nodefaultlib
|
||||
link-time option is ignored as well.
|
||||
.It Ev LD_PRELOAD
|
||||
A list of shared libraries, separated by colons and/or white space,
|
||||
to be linked in before any
|
||||
|
@ -80,8 +80,9 @@ typedef void * (*path_enum_proc) (const char *path, size_t len, void *arg);
|
||||
static const char *basename(const char *);
|
||||
static void die(void) __dead2;
|
||||
static void digest_dynamic1(Obj_Entry *, int, const Elf_Dyn **,
|
||||
const Elf_Dyn **);
|
||||
static void digest_dynamic2(Obj_Entry *, const Elf_Dyn *, const Elf_Dyn *);
|
||||
const Elf_Dyn **, const Elf_Dyn **);
|
||||
static void digest_dynamic2(Obj_Entry *, const Elf_Dyn *, const Elf_Dyn *,
|
||||
const Elf_Dyn *);
|
||||
static void digest_dynamic(Obj_Entry *, int);
|
||||
static Obj_Entry *digest_phdr(const Elf_Phdr *, int, caddr_t, const char *);
|
||||
static Obj_Entry *dlcheck(void *);
|
||||
@ -94,7 +95,7 @@ static void errmsg_restore(char *);
|
||||
static char *errmsg_save(void);
|
||||
static void *fill_search_info(const char *, size_t, void *);
|
||||
static char *find_library(const char *, const Obj_Entry *);
|
||||
static const char *gethints(void);
|
||||
static const char *gethints(bool);
|
||||
static void init_dag(Obj_Entry *);
|
||||
static void init_rtld(caddr_t, Elf_Auxinfo **);
|
||||
static void initlist_add_neededs(Needed_Entry *, Objlist *);
|
||||
@ -233,6 +234,8 @@ size_t tls_static_space; /* Static TLS space allocated */
|
||||
int tls_dtv_generation = 1; /* Used to detect when dtv size changes */
|
||||
int tls_max_index = 1; /* Largest module index allocated */
|
||||
|
||||
bool ld_library_path_rpath = false;
|
||||
|
||||
/*
|
||||
* Fill in a DoneList with an allocation large enough to hold all of
|
||||
* the currently-loaded objects. Keep this as a macro since it calls
|
||||
@ -323,6 +326,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
|
||||
Obj_Entry **preload_tail;
|
||||
Objlist initlist;
|
||||
RtldLockState lockstate;
|
||||
char *library_path_rpath;
|
||||
int mib[2];
|
||||
size_t len;
|
||||
|
||||
@ -394,7 +398,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
|
||||
if (unsetenv(LD_ "PRELOAD") || unsetenv(LD_ "LIBMAP") ||
|
||||
unsetenv(LD_ "LIBRARY_PATH") || unsetenv(LD_ "LIBMAP_DISABLE") ||
|
||||
unsetenv(LD_ "DEBUG") || unsetenv(LD_ "ELF_HINTS_PATH") ||
|
||||
unsetenv(LD_ "LOADFLTR")) {
|
||||
unsetenv(LD_ "LOADFLTR") || unsetenv(LD_ "LIBRARY_PATH_RPATH")) {
|
||||
_rtld_error("environment corrupt; aborting");
|
||||
die();
|
||||
}
|
||||
@ -406,6 +410,15 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
|
||||
ld_preload = getenv(LD_ "PRELOAD");
|
||||
ld_elf_hints_path = getenv(LD_ "ELF_HINTS_PATH");
|
||||
ld_loadfltr = getenv(LD_ "LOADFLTR") != NULL;
|
||||
library_path_rpath = getenv(LD_ "LIBRARY_PATH_RPATH");
|
||||
if (library_path_rpath != NULL) {
|
||||
if (library_path_rpath[0] == 'y' ||
|
||||
library_path_rpath[0] == 'Y' ||
|
||||
library_path_rpath[0] == '1')
|
||||
ld_library_path_rpath = true;
|
||||
else
|
||||
ld_library_path_rpath = false;
|
||||
}
|
||||
dangerous_ld_env = libmap_disable || (libmap_override != NULL) ||
|
||||
(ld_library_path != NULL) || (ld_preload != NULL) ||
|
||||
(ld_elf_hints_path != NULL) || ld_loadfltr;
|
||||
@ -828,7 +841,7 @@ die(void)
|
||||
*/
|
||||
static void
|
||||
digest_dynamic1(Obj_Entry *obj, int early, const Elf_Dyn **dyn_rpath,
|
||||
const Elf_Dyn **dyn_soname)
|
||||
const Elf_Dyn **dyn_soname, const Elf_Dyn **dyn_runpath)
|
||||
{
|
||||
const Elf_Dyn *dynp;
|
||||
Needed_Entry **needed_tail = &obj->needed;
|
||||
@ -843,6 +856,7 @@ digest_dynamic1(Obj_Entry *obj, int early, const Elf_Dyn **dyn_rpath,
|
||||
|
||||
*dyn_rpath = NULL;
|
||||
*dyn_soname = NULL;
|
||||
*dyn_runpath = NULL;
|
||||
|
||||
obj->bind_now = false;
|
||||
for (dynp = obj->dynamic; dynp->d_tag != DT_NULL; dynp++) {
|
||||
@ -1009,7 +1023,6 @@ digest_dynamic1(Obj_Entry *obj, int early, const Elf_Dyn **dyn_rpath,
|
||||
break;
|
||||
|
||||
case DT_RPATH:
|
||||
case DT_RUNPATH: /* XXX: process separately */
|
||||
/*
|
||||
* We have to wait until later to process this, because we
|
||||
* might not have gotten the address of the string table yet.
|
||||
@ -1021,6 +1034,10 @@ digest_dynamic1(Obj_Entry *obj, int early, const Elf_Dyn **dyn_rpath,
|
||||
*dyn_soname = dynp;
|
||||
break;
|
||||
|
||||
case DT_RUNPATH:
|
||||
*dyn_runpath = dynp;
|
||||
break;
|
||||
|
||||
case DT_INIT:
|
||||
obj->init = (Elf_Addr) (obj->relocbase + dynp->d_un.d_ptr);
|
||||
break;
|
||||
@ -1114,6 +1131,8 @@ digest_dynamic1(Obj_Entry *obj, int early, const Elf_Dyn **dyn_rpath,
|
||||
obj->z_nodelete = true;
|
||||
if (dynp->d_un.d_val & DF_1_LOADFLTR)
|
||||
obj->z_loadfltr = true;
|
||||
if (dynp->d_un.d_val & DF_1_NODEFLIB)
|
||||
obj->z_nodeflib = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1153,7 +1172,7 @@ digest_dynamic1(Obj_Entry *obj, int early, const Elf_Dyn **dyn_rpath,
|
||||
|
||||
static void
|
||||
digest_dynamic2(Obj_Entry *obj, const Elf_Dyn *dyn_rpath,
|
||||
const Elf_Dyn *dyn_soname)
|
||||
const Elf_Dyn *dyn_soname, const Elf_Dyn *dyn_runpath)
|
||||
{
|
||||
|
||||
if (obj->z_origin && obj->origin_path == NULL) {
|
||||
@ -1162,7 +1181,12 @@ digest_dynamic2(Obj_Entry *obj, const Elf_Dyn *dyn_rpath,
|
||||
die();
|
||||
}
|
||||
|
||||
if (dyn_rpath != NULL) {
|
||||
if (dyn_runpath != NULL) {
|
||||
obj->runpath = (char *)obj->strtab + dyn_runpath->d_un.d_val;
|
||||
if (obj->z_origin)
|
||||
obj->runpath = origin_subst(obj->runpath, obj->origin_path);
|
||||
}
|
||||
else if (dyn_rpath != NULL) {
|
||||
obj->rpath = (char *)obj->strtab + dyn_rpath->d_un.d_val;
|
||||
if (obj->z_origin)
|
||||
obj->rpath = origin_subst(obj->rpath, obj->origin_path);
|
||||
@ -1177,9 +1201,10 @@ digest_dynamic(Obj_Entry *obj, int early)
|
||||
{
|
||||
const Elf_Dyn *dyn_rpath;
|
||||
const Elf_Dyn *dyn_soname;
|
||||
const Elf_Dyn *dyn_runpath;
|
||||
|
||||
digest_dynamic1(obj, early, &dyn_rpath, &dyn_soname);
|
||||
digest_dynamic2(obj, dyn_rpath, dyn_soname);
|
||||
digest_dynamic1(obj, early, &dyn_rpath, &dyn_soname, &dyn_runpath);
|
||||
digest_dynamic2(obj, dyn_rpath, dyn_soname, dyn_runpath);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1389,43 +1414,71 @@ gnu_hash(const char *s)
|
||||
* loaded shared object, whose library search path will be searched.
|
||||
*
|
||||
* The search order is:
|
||||
* DT_RPATH in the referencing file _unless_ DT_RUNPATH is present (1)
|
||||
* DT_RPATH of the main object if DSO without defined DT_RUNPATH (1)
|
||||
* LD_LIBRARY_PATH
|
||||
* rpath in the referencing file
|
||||
* ldconfig hints
|
||||
* /lib:/usr/lib
|
||||
* DT_RUNPATH in the referencing file
|
||||
* ldconfig hints (if -z nodefaultlib, filter out default library directories
|
||||
* from list)
|
||||
* /lib:/usr/lib _unless_ the referencing file is linked with -z nodefaultlib
|
||||
*
|
||||
* (1) Handled in digest_dynamic2 - rpath left NULL if runpath defined.
|
||||
*/
|
||||
static char *
|
||||
find_library(const char *xname, const Obj_Entry *refobj)
|
||||
{
|
||||
char *pathname;
|
||||
char *name;
|
||||
bool objgiven;
|
||||
|
||||
objgiven = refobj != NULL;
|
||||
if (strchr(xname, '/') != NULL) { /* Hard coded pathname */
|
||||
if (xname[0] != '/' && !trust) {
|
||||
_rtld_error("Absolute pathname required for shared object \"%s\"",
|
||||
xname);
|
||||
return NULL;
|
||||
}
|
||||
if (refobj != NULL && refobj->z_origin)
|
||||
if (objgiven && refobj->z_origin)
|
||||
return origin_subst(xname, refobj->origin_path);
|
||||
else
|
||||
return xstrdup(xname);
|
||||
}
|
||||
|
||||
if (libmap_disable || (refobj == NULL) ||
|
||||
if (libmap_disable || !objgiven ||
|
||||
(name = lm_find(refobj->path, xname)) == NULL)
|
||||
name = (char *)xname;
|
||||
|
||||
dbg(" Searching for \"%s\"", name);
|
||||
|
||||
if ((pathname = search_library_path(name, ld_library_path)) != NULL ||
|
||||
(refobj != NULL &&
|
||||
(pathname = search_library_path(name, refobj->rpath)) != NULL) ||
|
||||
(pathname = search_library_path(name, gethints())) != NULL ||
|
||||
(pathname = search_library_path(name, STANDARD_LIBRARY_PATH)) != NULL)
|
||||
return pathname;
|
||||
/*
|
||||
* If refobj->rpath != NULL, then refobj->runpath is NULL. Fall
|
||||
* back to pre-conforming behaviour if user requested so with
|
||||
* LD_LIBRARY_PATH_RPATH environment variable and ignore -z
|
||||
* nodeflib.
|
||||
*/
|
||||
if (objgiven && refobj->rpath != NULL && ld_library_path_rpath) {
|
||||
if ((pathname = search_library_path(name, ld_library_path)) != NULL ||
|
||||
(refobj != NULL &&
|
||||
(pathname = search_library_path(name, refobj->rpath)) != NULL) ||
|
||||
(pathname = search_library_path(name, gethints(false))) != NULL ||
|
||||
(pathname = search_library_path(name, STANDARD_LIBRARY_PATH)) != NULL)
|
||||
return (pathname);
|
||||
} else {
|
||||
if ((objgiven &&
|
||||
(pathname = search_library_path(name, refobj->rpath)) != NULL) ||
|
||||
(objgiven && refobj->runpath == NULL && refobj != obj_main &&
|
||||
(pathname = search_library_path(name, obj_main->rpath)) != NULL) ||
|
||||
(pathname = search_library_path(name, ld_library_path)) != NULL ||
|
||||
(objgiven &&
|
||||
(pathname = search_library_path(name, refobj->runpath)) != NULL) ||
|
||||
(pathname = search_library_path(name, gethints(refobj->z_nodeflib)))
|
||||
!= NULL ||
|
||||
(objgiven && !refobj->z_nodeflib &&
|
||||
(pathname = search_library_path(name, STANDARD_LIBRARY_PATH)) != NULL))
|
||||
return (pathname);
|
||||
}
|
||||
|
||||
if(refobj != NULL && refobj->path != NULL) {
|
||||
if (objgiven && refobj->path != NULL) {
|
||||
_rtld_error("Shared object \"%s\" not found, required by \"%s\"",
|
||||
name, basename(refobj->path));
|
||||
} else {
|
||||
@ -1520,41 +1573,142 @@ find_symdef(unsigned long symnum, const Obj_Entry *refobj,
|
||||
|
||||
/*
|
||||
* Return the search path from the ldconfig hints file, reading it if
|
||||
* necessary. Returns NULL if there are problems with the hints file,
|
||||
* necessary. If nostdlib is true, then the default search paths are
|
||||
* not added to result.
|
||||
*
|
||||
* Returns NULL if there are problems with the hints file,
|
||||
* or if the search path there is empty.
|
||||
*/
|
||||
static const char *
|
||||
gethints(void)
|
||||
gethints(bool nostdlib)
|
||||
{
|
||||
static char *hints;
|
||||
|
||||
if (hints == NULL) {
|
||||
int fd;
|
||||
static char *hints, *filtered_path;
|
||||
struct elfhints_hdr hdr;
|
||||
struct fill_search_info_args sargs, hargs;
|
||||
struct dl_serinfo smeta, hmeta, *SLPinfo, *hintinfo;
|
||||
struct dl_serpath *SLPpath, *hintpath;
|
||||
char *p;
|
||||
unsigned int SLPndx, hintndx, fndx, fcount;
|
||||
int fd;
|
||||
size_t flen;
|
||||
bool skip;
|
||||
|
||||
/* Keep from trying again in case the hints file is bad. */
|
||||
hints = "";
|
||||
/* First call, read the hints file */
|
||||
if (hints == NULL) {
|
||||
/* Keep from trying again in case the hints file is bad. */
|
||||
hints = "";
|
||||
|
||||
if ((fd = open(ld_elf_hints_path, O_RDONLY)) == -1)
|
||||
return NULL;
|
||||
if (read(fd, &hdr, sizeof hdr) != sizeof hdr ||
|
||||
hdr.magic != ELFHINTS_MAGIC ||
|
||||
hdr.version != 1) {
|
||||
close(fd);
|
||||
return NULL;
|
||||
if ((fd = open(ld_elf_hints_path, O_RDONLY)) == -1)
|
||||
return (NULL);
|
||||
if (read(fd, &hdr, sizeof hdr) != sizeof hdr ||
|
||||
hdr.magic != ELFHINTS_MAGIC ||
|
||||
hdr.version != 1) {
|
||||
close(fd);
|
||||
return (NULL);
|
||||
}
|
||||
p = xmalloc(hdr.dirlistlen + 1);
|
||||
if (lseek(fd, hdr.strtab + hdr.dirlist, SEEK_SET) == -1 ||
|
||||
read(fd, p, hdr.dirlistlen + 1) !=
|
||||
(ssize_t)hdr.dirlistlen + 1) {
|
||||
free(p);
|
||||
close(fd);
|
||||
return (NULL);
|
||||
}
|
||||
hints = p;
|
||||
close(fd);
|
||||
}
|
||||
p = xmalloc(hdr.dirlistlen + 1);
|
||||
if (lseek(fd, hdr.strtab + hdr.dirlist, SEEK_SET) == -1 ||
|
||||
read(fd, p, hdr.dirlistlen + 1) != (ssize_t)hdr.dirlistlen + 1) {
|
||||
free(p);
|
||||
close(fd);
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* If caller agreed to receive list which includes the default
|
||||
* paths, we are done. Otherwise, if we still did not
|
||||
* calculated filtered result, do it now.
|
||||
*/
|
||||
if (!nostdlib)
|
||||
return (hints[0] != '\0' ? hints : NULL);
|
||||
if (filtered_path != NULL)
|
||||
goto filt_ret;
|
||||
|
||||
/*
|
||||
* Obtain the list of all configured search paths, and the
|
||||
* list of the default paths.
|
||||
*
|
||||
* First estimate the size of the results.
|
||||
*/
|
||||
smeta.dls_size = __offsetof(struct dl_serinfo, dls_serpath);
|
||||
smeta.dls_cnt = 0;
|
||||
hmeta.dls_size = __offsetof(struct dl_serinfo, dls_serpath);
|
||||
hmeta.dls_cnt = 0;
|
||||
|
||||
sargs.request = RTLD_DI_SERINFOSIZE;
|
||||
sargs.serinfo = &smeta;
|
||||
hargs.request = RTLD_DI_SERINFOSIZE;
|
||||
hargs.serinfo = &hmeta;
|
||||
|
||||
path_enumerate(STANDARD_LIBRARY_PATH, fill_search_info, &sargs);
|
||||
path_enumerate(p, fill_search_info, &hargs);
|
||||
|
||||
SLPinfo = xmalloc(smeta.dls_size);
|
||||
hintinfo = xmalloc(hmeta.dls_size);
|
||||
|
||||
/*
|
||||
* Next fetch both sets of paths.
|
||||
*/
|
||||
sargs.request = RTLD_DI_SERINFO;
|
||||
sargs.serinfo = SLPinfo;
|
||||
sargs.serpath = &SLPinfo->dls_serpath[0];
|
||||
sargs.strspace = (char *)&SLPinfo->dls_serpath[smeta.dls_cnt];
|
||||
|
||||
hargs.request = RTLD_DI_SERINFO;
|
||||
hargs.serinfo = hintinfo;
|
||||
hargs.serpath = &hintinfo->dls_serpath[0];
|
||||
hargs.strspace = (char *)&hintinfo->dls_serpath[hmeta.dls_cnt];
|
||||
|
||||
path_enumerate(STANDARD_LIBRARY_PATH, fill_search_info, &sargs);
|
||||
path_enumerate(p, fill_search_info, &hargs);
|
||||
|
||||
/*
|
||||
* Now calculate the difference between two sets, by excluding
|
||||
* standard paths from the full set.
|
||||
*/
|
||||
fndx = 0;
|
||||
fcount = 0;
|
||||
filtered_path = xmalloc(hdr.dirlistlen + 1);
|
||||
hintpath = &hintinfo->dls_serpath[0];
|
||||
for (hintndx = 0; hintndx < hmeta.dls_cnt; hintndx++, hintpath++) {
|
||||
skip = false;
|
||||
SLPpath = &SLPinfo->dls_serpath[0];
|
||||
/*
|
||||
* Check each standard path against current.
|
||||
*/
|
||||
for (SLPndx = 0; SLPndx < smeta.dls_cnt; SLPndx++, SLPpath++) {
|
||||
/* matched, skip the path */
|
||||
if (!strcmp(hintpath->dls_name, SLPpath->dls_name)) {
|
||||
skip = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (skip)
|
||||
continue;
|
||||
/*
|
||||
* Not matched against any standard path, add the path
|
||||
* to result. Separate consequtive paths with ':'.
|
||||
*/
|
||||
if (fcount > 0) {
|
||||
filtered_path[fndx] = ':';
|
||||
fndx++;
|
||||
}
|
||||
fcount++;
|
||||
flen = strlen(hintpath->dls_name);
|
||||
strncpy((filtered_path + fndx), hintpath->dls_name, flen);
|
||||
fndx += flen;
|
||||
}
|
||||
hints = p;
|
||||
close(fd);
|
||||
}
|
||||
return hints[0] != '\0' ? hints : NULL;
|
||||
filtered_path[fndx] = '\0';
|
||||
|
||||
free(SLPinfo);
|
||||
free(hintinfo);
|
||||
|
||||
filt_ret:
|
||||
return (filtered_path[0] != '\0' ? filtered_path : NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1600,6 +1754,7 @@ init_rtld(caddr_t mapbase, Elf_Auxinfo **aux_info)
|
||||
Obj_Entry objtmp; /* Temporary rtld object */
|
||||
const Elf_Dyn *dyn_rpath;
|
||||
const Elf_Dyn *dyn_soname;
|
||||
const Elf_Dyn *dyn_runpath;
|
||||
|
||||
/*
|
||||
* Conjure up an Obj_Entry structure for the dynamic linker.
|
||||
@ -1616,7 +1771,7 @@ init_rtld(caddr_t mapbase, Elf_Auxinfo **aux_info)
|
||||
#endif
|
||||
if (RTLD_IS_DYNAMIC()) {
|
||||
objtmp.dynamic = rtld_dynamic(&objtmp);
|
||||
digest_dynamic1(&objtmp, 1, &dyn_rpath, &dyn_soname);
|
||||
digest_dynamic1(&objtmp, 1, &dyn_rpath, &dyn_soname, &dyn_runpath);
|
||||
assert(objtmp.needed == NULL);
|
||||
#if !defined(__mips__)
|
||||
/* MIPS has a bogus DT_TEXTREL. */
|
||||
@ -1642,7 +1797,7 @@ init_rtld(caddr_t mapbase, Elf_Auxinfo **aux_info)
|
||||
if (aux_info[AT_OSRELDATE] != NULL)
|
||||
osreldate = aux_info[AT_OSRELDATE]->a_un.a_val;
|
||||
|
||||
digest_dynamic2(&obj_rtld, dyn_rpath, dyn_soname);
|
||||
digest_dynamic2(&obj_rtld, dyn_rpath, dyn_soname, dyn_runpath);
|
||||
|
||||
/* Replace the path with a dynamically allocated copy. */
|
||||
obj_rtld.path = xstrdup(PATH_RTLD);
|
||||
@ -3070,14 +3225,6 @@ dl_iterate_phdr(__dl_iterate_hdr_callback callback, void *param)
|
||||
return (error);
|
||||
}
|
||||
|
||||
struct fill_search_info_args {
|
||||
int request;
|
||||
unsigned int flags;
|
||||
Dl_serinfo *serinfo;
|
||||
Dl_serpath *serpath;
|
||||
char *strspace;
|
||||
};
|
||||
|
||||
static void *
|
||||
fill_search_info(const char *dir, size_t dirlen, void *param)
|
||||
{
|
||||
@ -3087,7 +3234,7 @@ fill_search_info(const char *dir, size_t dirlen, void *param)
|
||||
|
||||
if (arg->request == RTLD_DI_SERINFOSIZE) {
|
||||
arg->serinfo->dls_cnt ++;
|
||||
arg->serinfo->dls_size += sizeof(Dl_serpath) + dirlen + 1;
|
||||
arg->serinfo->dls_size += sizeof(struct dl_serpath) + dirlen + 1;
|
||||
} else {
|
||||
struct dl_serpath *s_entry;
|
||||
|
||||
@ -3117,10 +3264,12 @@ do_search_info(const Obj_Entry *obj, int request, struct dl_serinfo *info)
|
||||
_info.dls_size = __offsetof(struct dl_serinfo, dls_serpath);
|
||||
_info.dls_cnt = 0;
|
||||
|
||||
path_enumerate(ld_library_path, fill_search_info, &args);
|
||||
path_enumerate(obj->rpath, fill_search_info, &args);
|
||||
path_enumerate(gethints(), fill_search_info, &args);
|
||||
path_enumerate(STANDARD_LIBRARY_PATH, fill_search_info, &args);
|
||||
path_enumerate(ld_library_path, fill_search_info, &args);
|
||||
path_enumerate(obj->runpath, fill_search_info, &args);
|
||||
path_enumerate(gethints(obj->z_nodeflib), fill_search_info, &args);
|
||||
if (!obj->z_nodeflib)
|
||||
path_enumerate(STANDARD_LIBRARY_PATH, fill_search_info, &args);
|
||||
|
||||
|
||||
if (request == RTLD_DI_SERINFOSIZE) {
|
||||
@ -3139,20 +3288,26 @@ do_search_info(const Obj_Entry *obj, int request, struct dl_serinfo *info)
|
||||
args.serpath = &info->dls_serpath[0];
|
||||
args.strspace = (char *)&info->dls_serpath[_info.dls_cnt];
|
||||
|
||||
args.flags = LA_SER_RUNPATH;
|
||||
if (path_enumerate(obj->rpath, fill_search_info, &args) != NULL)
|
||||
return (-1);
|
||||
|
||||
args.flags = LA_SER_LIBPATH;
|
||||
if (path_enumerate(ld_library_path, fill_search_info, &args) != NULL)
|
||||
return (-1);
|
||||
|
||||
args.flags = LA_SER_RUNPATH;
|
||||
if (path_enumerate(obj->rpath, fill_search_info, &args) != NULL)
|
||||
if (path_enumerate(obj->runpath, fill_search_info, &args) != NULL)
|
||||
return (-1);
|
||||
|
||||
args.flags = LA_SER_CONFIG;
|
||||
if (path_enumerate(gethints(), fill_search_info, &args) != NULL)
|
||||
if (path_enumerate(gethints(obj->z_nodeflib), fill_search_info, &args)
|
||||
!= NULL)
|
||||
return (-1);
|
||||
|
||||
args.flags = LA_SER_DEFAULT;
|
||||
if (path_enumerate(STANDARD_LIBRARY_PATH, fill_search_info, &args) != NULL)
|
||||
if (!obj->z_nodeflib &&
|
||||
path_enumerate(STANDARD_LIBRARY_PATH, fill_search_info, &args) != NULL)
|
||||
return (-1);
|
||||
return (0);
|
||||
}
|
||||
|
@ -222,6 +222,7 @@ typedef struct Struct_Obj_Entry {
|
||||
const Elf_Hashelt *chain_zero_gnu; /* GNU hash table value array (Zeroed) */
|
||||
|
||||
char *rpath; /* Search path specified in object */
|
||||
char *runpath; /* Search path with different priority */
|
||||
Needed_Entry *needed; /* Shared objects needed by this one (%) */
|
||||
Needed_Entry *needed_filtees;
|
||||
Needed_Entry *needed_aux_filtees;
|
||||
@ -258,6 +259,7 @@ typedef struct Struct_Obj_Entry {
|
||||
bool z_nodelete : 1; /* Do not unload the object and dependencies */
|
||||
bool z_noopen : 1; /* Do not load on dlopen */
|
||||
bool z_loadfltr : 1; /* Immediately load filtees */
|
||||
bool z_nodeflib : 1; /* Don't search default library path */
|
||||
bool ref_nodel : 1; /* Refcount increased to prevent dlclose */
|
||||
bool init_scanned: 1; /* Object is already on init list. */
|
||||
bool on_fini_list: 1; /* Object is already on fini list. */
|
||||
@ -321,6 +323,14 @@ struct Struct_RtldLockState {
|
||||
sigjmp_buf env;
|
||||
};
|
||||
|
||||
struct fill_search_info_args {
|
||||
int request;
|
||||
unsigned int flags;
|
||||
struct dl_serinfo *serinfo;
|
||||
struct dl_serpath *serpath;
|
||||
char *strspace;
|
||||
};
|
||||
|
||||
/*
|
||||
* The pack of arguments and results for the symbol lookup functions.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user