diff options
-rw-r--r-- | libexec/ld.so/library_subr.c | 61 | ||||
-rw-r--r-- | libexec/ld.so/resolve.c | 43 | ||||
-rw-r--r-- | libexec/ld.so/resolve.h | 3 |
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; |