summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Guenther <guenther@cvs.openbsd.org>2017-01-22 01:20:37 +0000
committerPhilip Guenther <guenther@cvs.openbsd.org>2017-01-22 01:20:37 +0000
commitfd2dbb2a985b7ad84b5cddd16df0e5f341a6f368 (patch)
treeb41d8c858eeac40e0a09db26307d19c544b26799
parent50aa824955f4311ecdc302cf17976bddbd2aa2b2 (diff)
Add support for DT_RUNPATH and DT_FLAGS
ok kettenis@
-rw-r--r--libexec/ld.so/library_subr.c61
-rw-r--r--libexec/ld.so/resolve.c43
-rw-r--r--libexec/ld.so/resolve.h3
3 files changed, 69 insertions, 38 deletions
diff --git a/libexec/ld.so/library_subr.c b/libexec/ld.so/library_subr.c
index 07631c5c104..da476b8d309 100644
--- a/libexec/ld.so/library_subr.c
+++ b/libexec/ld.so/library_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: library_subr.c,v 1.45 2016/01/24 03:54:34 guenther Exp $ */
+/* $OpenBSD: library_subr.c,v 1.46 2017/01/22 01:20:36 guenther Exp $ */
/*
* Copyright (c) 2002 Dale Rahn
@@ -286,21 +286,24 @@ _dl_find_loaded_shlib(const char *req_name, struct sod req_sod, int flags)
* this will only match specific library version.
* search path preceding library name
* this will find largest minor version in path provided
- * try the LD_LIBRARY_PATH specification (if present)
- * search hints for match in LD_LIBRARY_PATH dirs
- * this will only match specific library version.
- * search LD_LIBRARY_PATH dirs for match.
- * this will find largest minor version in first dir found.
- * check DT_RPATH paths, (if present)
- * search hints for match in DT_RPATH dirs
- * this will only match specific library version.
- * search DT_RPATH dirs for match.
- * this will find largest minor version in first dir found.
- * last look in default search directory, either as specified
- * by ldconfig or default to '/usr/lib'
+ *
+ * Otherwise, the name doesn't contain a '/':
+ * search hints for the specific library version, trying in turn
+ * paths from the following:
+ * - the LD_LIBRARY_PATH environment variable (if set)
+ * - the library's own DT_RUNPATH
+ * - if DT_RUNPATH wasn't set, then:
+ * - the library's own DT_RPATH
+ * - the executable's own DT_RPATH
+ * - the default search path set by ldconfig, or /usr/lib if unset
+ *
+ * If the hints doesn't have an exact match, then we search
+ * that exact same list of directories again, looking for a
+ * lib with the correct major version. If we find a match on
+ * the major, then we take the match *in that directory* which
+ * has the largest minor version
*/
-
elf_object_t *
_dl_load_shlib(const char *libname, elf_object_t *parent, int type, int flags)
{
@@ -371,18 +374,28 @@ again:
goto done;
}
- /* Check DT_RPATH. */
- if (parent->rpath != NULL) {
- hint = _dl_find_shlib(&req_sod, parent->rpath, ignore_hints);
- if (hint != NULL)
- goto done;
- }
-
- /* Check main program's DT_RPATH, if parent != main program */
- if (parent != _dl_objects && _dl_objects->rpath != NULL) {
- hint = _dl_find_shlib(&req_sod, _dl_objects->rpath, ignore_hints);
+ /* Check DT_RUNPATH */
+ if (parent->runpath != NULL) {
+ hint = _dl_find_shlib(&req_sod, parent->runpath, ignore_hints);
if (hint != NULL)
goto done;
+ } else {
+ /*
+ * If DT_RUNPATH wasn't set then first check DT_RPATH,
+ * followed by the main program's DT_RPATH.
+ */
+ if (parent->rpath != NULL) {
+ hint = _dl_find_shlib(&req_sod, parent->rpath,
+ ignore_hints);
+ if (hint != NULL)
+ goto done;
+ }
+ if (parent != _dl_objects && _dl_objects->rpath != NULL) {
+ hint = _dl_find_shlib(&req_sod, _dl_objects->rpath,
+ ignore_hints);
+ if (hint != NULL)
+ goto done;
+ }
}
/* check 'standard' locations */
diff --git a/libexec/ld.so/resolve.c b/libexec/ld.so/resolve.c
index 02d96833cb2..e2e2267efe2 100644
--- a/libexec/ld.so/resolve.c
+++ b/libexec/ld.so/resolve.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: resolve.c,v 1.75 2016/08/23 06:46:17 kettenis Exp $ */
+/* $OpenBSD: resolve.c,v 1.76 2017/01/22 01:20:36 guenther Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -221,7 +221,7 @@ _dl_origin_path(elf_object_t *object, char *origin_path)
}
/*
- * Perform $ORIGIN substitutions on rpath
+ * Perform $ORIGIN substitutions on runpath and rpath
*/
static void
_dl_origin_subst(elf_object_t *object)
@@ -232,7 +232,10 @@ _dl_origin_subst(elf_object_t *object)
if (_dl_origin_path(object, origin_path) != 0)
return;
- /* perform path substitutions on each segment of rpath */
+ /* perform path substitutions on each segment of runpath and rpath */
+ for (pp = object->runpath; *pp != NULL; pp++) {
+ _dl_origin_subst_path(object, origin_path, pp);
+ }
for (pp = object->rpath; *pp != NULL; pp++) {
_dl_origin_subst_path(object, origin_path, pp);
}
@@ -272,6 +275,15 @@ _dl_finalize_object(const char *objname, Elf_Dyn *dynp, Elf_Phdr *phdrp,
object->obj_flags |= DF_1_NOW;
if (dynp->d_tag == DT_FLAGS_1)
object->obj_flags |= dynp->d_un.d_val;
+ if (dynp->d_tag == DT_FLAGS) {
+ object->dyn.flags |= dynp->d_un.d_val;
+ if (dynp->d_un.d_val & DF_SYMBOLIC)
+ object->dyn.symbolic = 1;
+ if (dynp->d_un.d_val & DF_ORIGIN)
+ object->obj_flags |= DF_1_ORIGIN;
+ if (dynp->d_un.d_val & DF_BIND_NOW)
+ object->obj_flags |= DF_1_NOW;
+ }
if (dynp->d_tag == DT_RELACOUNT)
object->relacount = dynp->d_un.d_val;
if (dynp->d_tag == DT_RELCOUNT)
@@ -362,11 +374,18 @@ _dl_finalize_object(const char *objname, Elf_Dyn *dynp, Elf_Phdr *phdrp,
TAILQ_INIT(&object->grpsym_list);
TAILQ_INIT(&object->grpref_list);
- if (object->dyn.rpath) {
+ if (object->dyn.runpath)
+ object->runpath = _dl_split_path(object->dyn.runpath);
+ /*
+ * DT_RPATH is ignored if DT_RUNPATH is present...except in
+ * the exe, whose DT_RPATH is a fallback for libs that don't
+ * use DT_RUNPATH
+ */
+ if (object->dyn.rpath && (object->runpath == NULL ||
+ objtype == OBJTYPE_EXE))
object->rpath = _dl_split_path(object->dyn.rpath);
- if ((object->obj_flags & DF_1_ORIGIN) && _dl_trust)
- _dl_origin_subst(object);
- }
+ if ((object->obj_flags & DF_1_ORIGIN) && _dl_trust)
+ _dl_origin_subst(object);
_dl_trace_object_setup(object);
@@ -406,12 +425,10 @@ _dl_cleanup_objects()
head = free_objects;
free_objects = NULL;
while (head != NULL) {
- if (head->load_name)
- _dl_free(head->load_name);
- if (head->sod.sod_name)
- _dl_free((char *)head->sod.sod_name);
- if (head->rpath)
- _dl_free_path(head->rpath);
+ _dl_free(head->load_name);
+ _dl_free((char *)head->sod.sod_name);
+ _dl_free_path(head->runpath);
+ _dl_free_path(head->rpath);
_dl_tailq_free(TAILQ_FIRST(&head->grpsym_list));
_dl_tailq_free(TAILQ_FIRST(&head->child_list));
_dl_tailq_free(TAILQ_FIRST(&head->grpref_list));
diff --git a/libexec/ld.so/resolve.h b/libexec/ld.so/resolve.h
index 2e35fc888cc..c8917f88037 100644
--- a/libexec/ld.so/resolve.h
+++ b/libexec/ld.so/resolve.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: resolve.h,v 1.81 2016/08/30 12:47:19 kettenis Exp $ */
+/* $OpenBSD: resolve.h,v 1.82 2017/01/22 01:20:36 guenther Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -169,6 +169,7 @@ struct elf_object {
unsigned int grpsym_gen;
char **rpath;
+ char **runpath;
/* nonzero if trace enabled for this object */
int traced;