diff options
author | Andy Polyakov <appro@openssl.org> | 2005-12-30 22:53:59 +0000 |
---|---|---|
committer | Andy Polyakov <appro@openssl.org> | 2005-12-30 22:53:59 +0000 |
commit | 68b64fb6102737bf84de9e25168abbf7e969b54b (patch) | |
tree | fbd215080bb8f241fead7db2d4524f923d146b07 | |
parent | 34b537ee66eb7d327ff04121ccb7b9cc6b07ab3e (diff) |
Add DSO_global_lookup_func implementation. See commentary in dso_lib.c
for further details.
-rw-r--r-- | crypto/dso/dso.h | 4 | ||||
-rw-r--r-- | crypto/dso/dso_dl.c | 12 | ||||
-rw-r--r-- | crypto/dso/dso_dlfcn.c | 18 | ||||
-rw-r--r-- | crypto/dso/dso_err.c | 1 | ||||
-rw-r--r-- | crypto/dso/dso_lib.c | 21 | ||||
-rw-r--r-- | crypto/dso/dso_win32.c | 65 |
6 files changed, 118 insertions, 3 deletions
diff --git a/crypto/dso/dso.h b/crypto/dso/dso.h index 5da0a55f2a..10efa4ac8d 100644 --- a/crypto/dso/dso.h +++ b/crypto/dso/dso.h @@ -173,6 +173,9 @@ typedef struct dso_meth_st /* Return pathname of the module containing location */ int (*pathbyaddr)(void *addr,char *path,int sz); + /* Perform global symbol lookup, i.e. among *all* modules, + * see commentray in dso_lib.c for further details. */ + DSO_FUNC_TYPE (*globallookup)(const char *symname); } DSO_METHOD; /**********************************************************************/ @@ -357,6 +360,7 @@ void ERR_load_DSO_strings(void); #define DSO_F_WIN32_SPLITTER 136 #define DSO_F_WIN32_UNLOAD 121 #define DSO_F_PATHBYADDR 137 +#define DSO_F_GLOBAL_LOOKUP_FUNC 138 /* Reason codes. */ #define DSO_R_CTRL_FAILED 100 diff --git a/crypto/dso/dso_dl.c b/crypto/dso/dso_dl.c index dccb8e7ee8..7c123c8580 100644 --- a/crypto/dso/dso_dl.c +++ b/crypto/dso/dso_dl.c @@ -86,6 +86,7 @@ static int dl_ctrl(DSO *dso, int cmd, long larg, void *parg); static char *dl_name_converter(DSO *dso, const char *filename); static char *dl_merger(DSO *dso, const char *filespec1, const char *filespec2); static int dl_pathbyaddr(void *addr,char *path,int sz); +static DSO_FUNC_TYPE dl_globallookup(const char *name); static DSO_METHOD dso_meth_dl = { "OpenSSL 'dl' shared library method", @@ -103,7 +104,8 @@ static DSO_METHOD dso_meth_dl = { dl_merger, NULL, /* init */ NULL, /* finish */ - dl_pathbyaddr + dl_pathbyaddr, + dl_globallookup }; DSO_METHOD *DSO_METHOD_dl(void) @@ -380,4 +382,12 @@ static int dl_pathbyaddr(void *addr,char *path,int sz) return -1; } + +static DSO_FUNC_TYPE dl_globallookup(const char *name) + { + DSO_FUNC_TYPE ret; + shl_t h = NULL; + + return shl_findsym(&h,name,TYPE_UNDEFINED,&ret) ? NULL : ret; + } #endif /* DSO_DL */ diff --git a/crypto/dso/dso_dlfcn.c b/crypto/dso/dso_dlfcn.c index 6d6ee758ef..a4ab38f850 100644 --- a/crypto/dso/dso_dlfcn.c +++ b/crypto/dso/dso_dlfcn.c @@ -99,6 +99,7 @@ static char *dlfcn_name_converter(DSO *dso, const char *filename); static char *dlfcn_merger(DSO *dso, const char *filespec1, const char *filespec2); static int dlfcn_pathbyaddr(void *addr,char *path,int sz); +static DSO_FUNC_TYPE dlfcn_globallookup(const char *name); static DSO_METHOD dso_meth_dlfcn = { "OpenSSL 'dlfcn' shared library method", @@ -116,7 +117,8 @@ static DSO_METHOD dso_meth_dlfcn = { dlfcn_merger, NULL, /* init */ NULL, /* finish */ - dlfcn_pathbyaddr + dlfcn_pathbyaddr, + dlfcn_globallookup }; DSO_METHOD *DSO_METHOD_dlfcn(void) @@ -443,4 +445,18 @@ static int dlfcn_pathbyaddr(void *addr,char *path,int sz) ERR_add_error_data(4, "dlfcn_pathbyaddr(): ", dlerror()); return -1; } + +static DSO_FUNC_TYPE dlfcn_globallookup(const char *name) + { + union { void *p; DSO_FUNC_TYPE f; } ret = { NULL }; + void *handle = dlopen(NULL,RTLD_LAZY); + + if (handle) + { + ret.p = dlsym(handle,name); + dlclose(handle); + } + + return ret.f; + } #endif /* DSO_DLFCN */ diff --git a/crypto/dso/dso_err.c b/crypto/dso/dso_err.c index a88db0dd80..009a543445 100644 --- a/crypto/dso/dso_err.c +++ b/crypto/dso/dso_err.c @@ -108,6 +108,7 @@ static ERR_STRING_DATA DSO_str_functs[]= {ERR_FUNC(DSO_F_WIN32_SPLITTER), "WIN32_SPLITTER"}, {ERR_FUNC(DSO_F_WIN32_UNLOAD), "WIN32_UNLOAD"}, {ERR_FUNC(DSO_F_PATHBYADDR), "DSO_pathbyaddr"}, +{ERR_FUNC(DSO_F_GLOBAL_LOOKUP_FUNC), "DSO_global_lookup_func"}, {0,NULL} }; diff --git a/crypto/dso/dso_lib.c b/crypto/dso/dso_lib.c index 12ad097a28..8330c7d387 100644 --- a/crypto/dso/dso_lib.c +++ b/crypto/dso/dso_lib.c @@ -289,6 +289,7 @@ DSO_FUNC_TYPE DSO_bind_func(DSO *dso, const char *symname) DSOerr(DSO_F_DSO_BIND_FUNC,DSO_R_UNSUPPORTED); return(NULL); } +fprintf(stderr,"boo\n"); if((ret = dso->meth->dso_bind_func(dso, symname)) == NULL) { DSOerr(DSO_F_DSO_BIND_FUNC,DSO_R_SYM_FAILURE); @@ -476,3 +477,23 @@ int DSO_pathbyaddr(void *addr,char *path,int sz) } return (*meth->pathbyaddr)(addr,path,sz); } + +/* This function should be used with caution! It looks up symbols in + * *all* loaded modules and if module gets unloaded by somebody else + * attempt to dereference the pointer is doomed to have fatal + * consequences. Primary usage for this function is to probe *core* + * system functionality, e.g. check if getnameinfo(3) is available + * at run-time without bothering about OS-specific details such as + * libc.so.versioning or where does it actually reside: in libc + * itself or libsocket. */ +DSO_FUNC_TYPE DSO_global_lookup_func(const char *name) + { + DSO_METHOD *meth = default_DSO_meth; + if (meth == NULL) meth = DSO_METHOD_openssl(); + if (meth->globallookup == NULL) + { + DSOerr(DSO_F_GLOBAL_LOOKUP_FUNC,DSO_R_UNSUPPORTED); + return NULL; + } + return (*meth->globallookup)(name); + } diff --git a/crypto/dso/dso_win32.c b/crypto/dso/dso_win32.c index b44f25c579..73ffe36591 100644 --- a/crypto/dso/dso_win32.c +++ b/crypto/dso/dso_win32.c @@ -129,6 +129,7 @@ static char *win32_name_converter(DSO *dso, const char *filename); static char *win32_merger(DSO *dso, const char *filespec1, const char *filespec2); static int win32_pathbyaddr(void *addr,char *path,int sz); +static DSO_FUNC_TYPE win32_globallookup(const char *name); static const char *openssl_strnchr(const char *string, int c, size_t len); @@ -148,7 +149,8 @@ static DSO_METHOD dso_meth_win32 = { win32_merger, NULL, /* init */ NULL, /* finish */ - win32_pathbyaddr + win32_pathbyaddr, + win32_globallookup }; DSO_METHOD *DSO_METHOD_win32(void) @@ -770,4 +772,65 @@ static int win32_pathbyaddr(void *addr,char *path,int sz) FreeLibrary(dll); return 0; } + +static DSO_FUNC_TYPE win32_globallookup(const char *name) + { + HMODULE dll; + HANDLE hModuleSnap = INVALID_HANDLE_VALUE; + MODULEENTRY32 me32; + CREATETOOLHELP32SNAPSHOT create_snap; + CLOSETOOLHELP32SNAPSHOT close_snap; + MODULE32 module_first, module_next; + FARPROC ret=NULL; + + dll = LoadLibrary(TEXT(DLLNAME)); + if (dll == NULL) + { + DSOerr(DSO_F_GLOBAL_LOOKUP_FUNC,DSO_R_UNSUPPORTED); + return NULL; + } + + create_snap = (CREATETOOLHELP32SNAPSHOT) + GetProcAddress(dll,"CreateToolhelp32Snapshot"); + if (create_snap == NULL) + { + FreeLibrary(dll); + DSOerr(DSO_F_GLOBAL_LOOKUP_FUNC,DSO_R_UNSUPPORTED); + return NULL; + } + /* We take the rest for granted... */ +#ifdef _WIN32_WCE + close_snap = (CLOSETOOLHELP32SNAPSHOT) + GetProcAddress(dll,"CloseToolhelp32Snapshot"); +#else + close_snap = (CLOSETOOLHELP32SNAPSHOT)CloseHandle; +#endif + module_first = (MODULE32)GetProcAddress(dll,"Module32First"); + module_next = (MODULE32)GetProcAddress(dll,"Module32Next"); + + hModuleSnap = (*create_snap)(TH32CS_SNAPMODULE,0); + if( hModuleSnap == INVALID_HANDLE_VALUE ) return NULL; + + me32.dwSize = sizeof(me32); + + if (!(*module_first)(hModuleSnap,&me32)) + { + (*close_snap)(hModuleSnap); + FreeLibrary(dll); + return NULL; + } + + do { + if (ret = GetProcAddress(me32.hModule,fname)) + { + (*close_snap)(hModuleSnap); + FreeLibrary(dll); + return ret; + } + } while((*module_next)(hModuleSnap,&me32)); + + (*close_snap)(hModuleSnap); + FreeLibrary(dll); + return NULL; + } #endif /* DSO_WIN32 */ |