diff options
author | Dale Rahn <drahn@cvs.openbsd.org> | 2005-09-17 03:02:38 +0000 |
---|---|---|
committer | Dale Rahn <drahn@cvs.openbsd.org> | 2005-09-17 03:02:38 +0000 |
commit | 2b31496aeb1173cbe9e0274af630f14b4f8ba501 (patch) | |
tree | 1d2b2a81d1cd9794a01bba552e78dc4c8e7277ed /libexec | |
parent | 25c77fcd29b14091d6629dca40aba5058fc8c961 (diff) |
Cleanly handle the case where a dynamic object is opened, but one of it's
dependant libraries is missing. return NULL for a handle instead of
causing the program to exit.
Diffstat (limited to 'libexec')
-rw-r--r-- | libexec/ld.so/dlfcn.c | 38 | ||||
-rw-r--r-- | libexec/ld.so/resolve.h | 3 |
2 files changed, 29 insertions, 12 deletions
diff --git a/libexec/ld.so/dlfcn.c b/libexec/ld.so/dlfcn.c index c7e6a5e65b7..c307ceab0cc 100644 --- a/libexec/ld.so/dlfcn.c +++ b/libexec/ld.so/dlfcn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dlfcn.c,v 1.50 2005/09/16 23:19:41 drahn Exp $ */ +/* $OpenBSD: dlfcn.c,v 1.51 2005/09/17 03:02:37 drahn Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -50,6 +50,8 @@ dlopen(const char *libname, int flags) elf_object_t *object, *dynobj; Elf_Dyn *dynp; struct dep_node *n; + int failed = 0; + const char *deplibname = NULL; if (libname == NULL) return _dl_objects; @@ -60,6 +62,7 @@ dlopen(const char *libname, int flags) object = _dl_load_shlib(libname, _dl_objects, OBJTYPE_DLO, flags); if (object == 0) { + DL_DEB(("dlopen: failed to open %s\n", libname)); _dl_thread_kern_go(); return((void *)0); } @@ -92,7 +95,6 @@ dlopen(const char *libname, int flags) elf_object_t *tmpobj = dynobj; for (dynp = dynobj->load_dyn; dynp->d_tag; dynp++) { - const char *deplibname; elf_object_t *depobj; if (dynp->d_tag != DT_NEEDED) @@ -103,8 +105,10 @@ dlopen(const char *libname, int flags) deplibname, libname)); depobj = _dl_load_shlib(deplibname, dynobj, OBJTYPE_LIB, flags|RTLD_GLOBAL); - if (!depobj) - _dl_exit(4); + if (!depobj) { + failed = 1; + break; + } /* this add_object should not be here, XXX */ _dl_add_object(depobj); _dl_link_sub(depobj, dynobj); @@ -116,13 +120,21 @@ dlopen(const char *libname, int flags) dynobj = dynobj->next; } - _dl_link_dlopen(object); - _dl_rtld(object); - _dl_call_init(object); - - _dl_loading_object = NULL; - DL_DEB(("tail %s\n", object->load_name )); + + if (failed == 1) { + if (deplibname != NULL) { + DL_DEB(("dlopen: failed to open %s\n", deplibname)); + } + _dl_real_close(object); + object = NULL; + _dl_errno = DL_CANT_LOAD_OBJ; + } else { + DL_DEB(("tail %s\n", object->load_name )); + _dl_link_dlopen(object); + _dl_rtld(object); + _dl_call_init(object); + } if (_dl_debug_map->r_brk) { _dl_debug_map->r_state = RT_ADD; @@ -133,7 +145,8 @@ dlopen(const char *libname, int flags) _dl_thread_kern_go(); - DL_DEB(("dlopen: %s: done.\n", libname)); + DL_DEB(("dlopen: %s: done (%s).\n", libname, + failed ? "failed" : "success")); return((void *)object); } @@ -308,6 +321,9 @@ dlerror(void) case DL_CANT_FIND_OBJ: errmsg = "Cannot determine caller's shared object"; break; + case DL_CANT_LOAD_OBJ: + errmsg = "Cannot load specified object"; + break; default: errmsg = "Unknown error"; } diff --git a/libexec/ld.so/resolve.h b/libexec/ld.so/resolve.h index 94445ccf595..7ca2bb65b14 100644 --- a/libexec/ld.so/resolve.h +++ b/libexec/ld.so/resolve.h @@ -1,4 +1,4 @@ -/* $OpenBSD: resolve.h,v 1.37 2005/09/16 23:19:41 drahn Exp $ */ +/* $OpenBSD: resolve.h,v 1.38 2005/09/17 03:02:37 drahn Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -237,6 +237,7 @@ extern char *_dl_debug; #define DL_INVALID_CTL 8 #define DL_NO_OBJECT 9 #define DL_CANT_FIND_OBJ 10 +#define DL_CANT_LOAD_OBJ 11 #define ELF_ROUND(x,malign) (((x) + (malign)-1) & ~((malign)-1)) #define ELF_TRUNC(x,malign) ((x) & ~((malign)-1)) |