diff options
-rw-r--r-- | ldso/include/dl-elf.h | 1 | ||||
-rw-r--r-- | ldso/include/ld_elf.h | 1 | ||||
-rw-r--r-- | ldso/ldso/dl-elf.c | 59 | ||||
-rw-r--r-- | ldso/ldso/ldso.c | 12 | ||||
-rw-r--r-- | ldso/ldso/readelflib1.c | 59 |
5 files changed, 102 insertions, 30 deletions
diff --git a/ldso/include/dl-elf.h b/ldso/include/dl-elf.h index 95de118f5..992a608b1 100644 --- a/ldso/include/dl-elf.h +++ b/ldso/include/dl-elf.h @@ -68,6 +68,7 @@ extern struct elf_resolve * _dl_load_shared_library(int secure, struct dyn_elf **rpnt, struct elf_resolve *tpnt, char *full_libname); extern struct elf_resolve * _dl_load_elf_shared_library(int secure, struct dyn_elf **rpnt, char *libname); +extern struct elf_resolve *_dl_check_if_named_library_is_loaded(const char *full_libname); extern int _dl_linux_resolve(void); diff --git a/ldso/include/ld_elf.h b/ldso/include/ld_elf.h index 95de118f5..992a608b1 100644 --- a/ldso/include/ld_elf.h +++ b/ldso/include/ld_elf.h @@ -68,6 +68,7 @@ extern struct elf_resolve * _dl_load_shared_library(int secure, struct dyn_elf **rpnt, struct elf_resolve *tpnt, char *full_libname); extern struct elf_resolve * _dl_load_elf_shared_library(int secure, struct dyn_elf **rpnt, char *libname); +extern struct elf_resolve *_dl_check_if_named_library_is_loaded(const char *full_libname); extern int _dl_linux_resolve(void); diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c index 3df8b1461..2f70621d1 100644 --- a/ldso/ldso/dl-elf.c +++ b/ldso/ldso/dl-elf.c @@ -166,29 +166,19 @@ search_for_named_library(char *name, int secure, const char *path_list, return NULL; } - -/* - * Used to return error codes back to dlopen et. al. - */ - -unsigned long _dl_error_number; -unsigned long _dl_internal_error_number; -extern char *_dl_ldsopath; - -struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt, - struct elf_resolve *tpnt, char *full_libname) +/* Check if the named library is already loaded... */ +struct elf_resolve *_dl_check_if_named_library_is_loaded(const char *full_libname) { - char *pnt, *pnt1; + const char *pnt, *pnt1; struct elf_resolve *tpnt1; - char *libname, *libname2; + const char *libname, *libname2; - _dl_internal_error_number = 0; pnt = libname = full_libname; /* quick hack to ensure mylibname buffer doesn't overflow. don't allow full_libname or any directory to be longer than 1024. */ if (_dl_strlen(full_libname) > 1024) - goto goof; + return NULL; /* Skip over any initial initial './' and '/' stuff to * get the short form libname with no path garbage */ @@ -215,8 +205,47 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt, return tpnt1; } } + return NULL; +} + +/* + * Used to return error codes back to dlopen et. al. + */ + +unsigned long _dl_error_number; +unsigned long _dl_internal_error_number; +extern char *_dl_ldsopath; + +struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt, + struct elf_resolve *tpnt, char *full_libname) +{ + char *pnt, *pnt1; + struct elf_resolve *tpnt1; + char *libname; + + _dl_internal_error_number = 0; + libname = full_libname; + + /* quick hack to ensure mylibname buffer doesn't overflow. don't + allow full_libname or any directory to be longer than 1024. */ + if (_dl_strlen(full_libname) > 1024) + goto goof; + + /* Skip over any initial initial './' and '/' stuff to + * get the short form libname with no path garbage */ + pnt1 = _dl_strrchr(libname, '/'); + if (pnt1) { + libname = pnt1 + 1; + } + + /* Critical step! Weed out duplicates early to avoid + * function aliasing, which wastes memory, and causes + * really bad things to happen with weaks and globals. */ + if ((tpnt1=_dl_check_if_named_library_is_loaded(libname))!=NULL) + return tpnt1; + #if defined (__SUPPORT_LD_DEBUG__) if(_dl_debug) _dl_dprintf(_dl_debug_file, "searching for library: '%s'\n", libname); #endif diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c index 2f8e611ba..b6f236d0b 100644 --- a/ldso/ldso/ldso.c +++ b/ldso/ldso/ldso.c @@ -902,6 +902,10 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a *str2 = '\0'; if (!_dl_secure || _dl_strchr(str, '/') == NULL) { + if ((tpnt1 = _dl_check_if_named_library_is_loaded(str))) + { + continue; + } tpnt1 = _dl_load_shared_library(_dl_secure, &rpnt, NULL, str); if (!tpnt1) { #ifdef __LDSO_LDD_SUPPORT__ @@ -978,6 +982,10 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a c = *cp; *cp = '\0'; + if ((tpnt1 = _dl_check_if_named_library_is_loaded(cp2))) + { + continue; + } tpnt1 = _dl_load_shared_library(0, &rpnt, NULL, cp2); if (!tpnt1) { #ifdef __LDSO_LDD_SUPPORT__ @@ -1068,6 +1076,10 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a tpnt = NULL; continue; } + if ((tpnt1 = _dl_check_if_named_library_is_loaded(lpntstr))) + { + continue; + } if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr))) { #ifdef __LDSO_LDD_SUPPORT__ diff --git a/ldso/ldso/readelflib1.c b/ldso/ldso/readelflib1.c index 3df8b1461..2f70621d1 100644 --- a/ldso/ldso/readelflib1.c +++ b/ldso/ldso/readelflib1.c @@ -166,29 +166,19 @@ search_for_named_library(char *name, int secure, const char *path_list, return NULL; } - -/* - * Used to return error codes back to dlopen et. al. - */ - -unsigned long _dl_error_number; -unsigned long _dl_internal_error_number; -extern char *_dl_ldsopath; - -struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt, - struct elf_resolve *tpnt, char *full_libname) +/* Check if the named library is already loaded... */ +struct elf_resolve *_dl_check_if_named_library_is_loaded(const char *full_libname) { - char *pnt, *pnt1; + const char *pnt, *pnt1; struct elf_resolve *tpnt1; - char *libname, *libname2; + const char *libname, *libname2; - _dl_internal_error_number = 0; pnt = libname = full_libname; /* quick hack to ensure mylibname buffer doesn't overflow. don't allow full_libname or any directory to be longer than 1024. */ if (_dl_strlen(full_libname) > 1024) - goto goof; + return NULL; /* Skip over any initial initial './' and '/' stuff to * get the short form libname with no path garbage */ @@ -215,8 +205,47 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt, return tpnt1; } } + return NULL; +} + +/* + * Used to return error codes back to dlopen et. al. + */ + +unsigned long _dl_error_number; +unsigned long _dl_internal_error_number; +extern char *_dl_ldsopath; + +struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt, + struct elf_resolve *tpnt, char *full_libname) +{ + char *pnt, *pnt1; + struct elf_resolve *tpnt1; + char *libname; + + _dl_internal_error_number = 0; + libname = full_libname; + + /* quick hack to ensure mylibname buffer doesn't overflow. don't + allow full_libname or any directory to be longer than 1024. */ + if (_dl_strlen(full_libname) > 1024) + goto goof; + + /* Skip over any initial initial './' and '/' stuff to + * get the short form libname with no path garbage */ + pnt1 = _dl_strrchr(libname, '/'); + if (pnt1) { + libname = pnt1 + 1; + } + + /* Critical step! Weed out duplicates early to avoid + * function aliasing, which wastes memory, and causes + * really bad things to happen with weaks and globals. */ + if ((tpnt1=_dl_check_if_named_library_is_loaded(libname))!=NULL) + return tpnt1; + #if defined (__SUPPORT_LD_DEBUG__) if(_dl_debug) _dl_dprintf(_dl_debug_file, "searching for library: '%s'\n", libname); #endif |